Index: kernel/arch/amd64/src/interrupt.c
===================================================================
--- kernel/arch/amd64/src/interrupt.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/amd64/src/interrupt.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -157,7 +157,8 @@
 	
 	int inum = n - IVT_IRQBASE;
+	bool ack = false;
 	ASSERT(inum < IRQ_COUNT);
 	ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
-
+	
 	irq_t *irq = irq_dispatch_and_lock(inum);
 	if (irq) {
@@ -165,4 +166,10 @@
 		 * The IRQ handler was found.
 		 */
+		 
+		if (irq->preack) {
+			/* Send EOI before processing the interrupt */
+			trap_virtual_eoi();
+			ack = true;
+		}
 		irq->handler(irq, irq->arg);
 		spinlock_unlock(&irq->lock);
@@ -175,5 +182,7 @@
 #endif
 	}
-	trap_virtual_eoi();
+	
+	if (!ack)
+		trap_virtual_eoi();
 }
 
Index: kernel/arch/ia32/src/drivers/i8254.c
===================================================================
--- kernel/arch/ia32/src/drivers/i8254.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ia32/src/drivers/i8254.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -83,4 +83,5 @@
 {
 	irq_initialize(&i8254_irq);
+	i8254_irq.preack = true;
 	i8254_irq.devno = device_assign_devno();
 	i8254_irq.inr = IRQ_CLK;
Index: kernel/arch/ia32/src/interrupt.c
===================================================================
--- kernel/arch/ia32/src/interrupt.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ia32/src/interrupt.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -177,7 +177,8 @@
 	
 	int inum = n - IVT_IRQBASE;
+	bool ack = false;
 	ASSERT(inum < IRQ_COUNT);
 	ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
-
+	
 	irq_t *irq = irq_dispatch_and_lock(inum);
 	if (irq) {
@@ -185,4 +186,10 @@
 		 * The IRQ handler was found.
 		 */
+		 
+		if (irq->preack) {
+			/* Send EOI before processing the interrupt */
+			trap_virtual_eoi();
+			ack = true;
+		}
 		irq->handler(irq, irq->arg);
 		spinlock_unlock(&irq->lock);
@@ -195,5 +202,7 @@
 #endif
 	}
-	trap_virtual_eoi();
+	
+	if (!ack)
+		trap_virtual_eoi();
 }
 
Index: kernel/arch/ia32/src/smp/apic.c
===================================================================
--- kernel/arch/ia32/src/smp/apic.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ia32/src/smp/apic.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -170,4 +170,5 @@
 	
 	irq_initialize(&l_apic_timer_irq);
+	l_apic_timer_irq.preack = true;
 	l_apic_timer_irq.devno = device_assign_devno();
 	l_apic_timer_irq.inr = IRQ_CLK;
Index: kernel/arch/ia32xen/src/interrupt.c
===================================================================
--- kernel/arch/ia32xen/src/interrupt.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ia32xen/src/interrupt.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -177,7 +177,8 @@
 	
 	int inum = n - IVT_IRQBASE;
+	bool ack = false;
 	ASSERT(inum < IRQ_COUNT);
 	ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
-
+	
 	irq_t *irq = irq_dispatch_and_lock(inum);
 	if (irq) {
@@ -185,4 +186,10 @@
 		 * The IRQ handler was found.
 		 */
+		 
+		if (irq->preack) {
+			/* Send EOI before processing the interrupt */
+			trap_virtual_eoi();
+			ack = true;
+		}
 		irq->handler(irq, irq->arg);
 		spinlock_unlock(&irq->lock);
@@ -195,5 +202,7 @@
 #endif
 	}
-	trap_virtual_eoi();
+	
+	if (!ack)
+		trap_virtual_eoi();
 }
 
Index: kernel/arch/ppc32/src/interrupt.c
===================================================================
--- kernel/arch/ppc32/src/interrupt.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ppc32/src/interrupt.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -61,4 +61,5 @@
 	
 	while ((inum = pic_get_pending()) != -1) {
+		bool ack = false;
 		irq_t *irq = irq_dispatch_and_lock(inum);
 		if (irq) {
@@ -66,4 +67,11 @@
 			 * The IRQ handler was found.
 			 */
+			
+			if (irq->preack) {
+				/* Acknowledge the interrupt before processing */
+				pic_ack_interrupt(inum);
+				ack = true;
+			}
+			
 			irq->handler(irq, irq->arg);
 			spinlock_unlock(&irq->lock);
@@ -76,5 +84,7 @@
 #endif
 		}
-		pic_ack_interrupt(inum);
+		
+		if (!ack)
+			pic_ack_interrupt(inum);
 	}
 }
Index: kernel/arch/ppc64/src/interrupt.c
===================================================================
--- kernel/arch/ppc64/src/interrupt.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/arch/ppc64/src/interrupt.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -61,4 +61,5 @@
 	
 	while ((inum = pic_get_pending()) != -1) {
+		bool ack = false;
 		irq_t *irq = irq_dispatch_and_lock(inum);
 		if (irq) {
@@ -66,4 +67,11 @@
 			 * The IRQ handler was found.
 			 */
+			
+			if (irq->preack) {
+				/* Acknowledge the interrupt before processing */
+				pic_ack_interrupt(inum);
+				ack = true;
+			}
+			
 			irq->handler(irq, irq->arg);
 			spinlock_unlock(&irq->lock);
@@ -76,5 +84,7 @@
 #endif
 		}
-		pic_ack_interrupt(inum);
+		
+		if (!ack)
+			pic_ack_interrupt(inum);
 	}
 }
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/generic/include/ddi/irq.h	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -122,4 +122,12 @@
 	 */
 	SPINLOCK_DECLARE(lock);
+	
+	/** Send EOI before processing the interrupt.
+	 *  This is essential for timer interrupt which
+	 *  has to be acknowledged before doing preemption
+	 *  to make sure another timer interrupt will
+	 *  be eventually generated.
+	 */
+	bool preack;
 
 	/** Unique device number. -1 if not yet assigned. */
@@ -128,5 +136,5 @@
 	/** Actual IRQ number. -1 if not yet assigned. */
 	inr_t inr;
-	/** Trigger level of the IRQ.*/
+	/** Trigger level of the IRQ. */
 	irq_trigger_t trigger;
 	/** Claim ownership of the IRQ. */
Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision 7e5897971c2ec9ea1f833d1f148bc179a7abf5a7)
+++ kernel/generic/src/ddi/irq.c	(revision 7bcfbbc039dd4d392dc880cbc1a87b94b7ca853f)
@@ -139,4 +139,5 @@
 	link_initialize(&irq->link);
 	spinlock_initialize(&irq->lock, "irq.lock");
+	irq->preack = false;
 	irq->inr = -1;
 	irq->devno = -1;
