aboutsummaryrefslogtreecommitdiff
path: root/i386/i386at/interrupt.S
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2023-08-10 19:18:43 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-08-10 19:25:04 +0200
commit362c84a08a1b8f1eb7f9c1c37c6ed7cece348ee4 (patch)
treef9fd181c21759c63b19b8a33fb8b928fbb368195 /i386/i386at/interrupt.S
parentd2a853126d4b017d5029e2adbdcb844542fb7d7a (diff)
downloadgnumach-362c84a08a1b8f1eb7f9c1c37c6ed7cece348ee4.tar.gz
gnumach-362c84a08a1b8f1eb7f9c1c37c6ed7cece348ee4.tar.bz2
gnumach-362c84a08a1b8f1eb7f9c1c37c6ed7cece348ee4.zip
Acknowledge IRQ *before* calling the handler
5da1aea7ab3c ("Acknoledge interrupt after handler call") moved the IRQ ack to after calling the handler because of overflows. But that was because the interrupts were getting enabled at some point. Now that all spl levels above 0 just disable interrupts, once we have called spl7 we are safe until splx_cli is called (and even that doesn't release interrupts, only the eventual iret will). And if the handler triggers another IRQ, it will be lost, so we do want to ack the IRQ before handling it.
Diffstat (limited to 'i386/i386at/interrupt.S')
-rw-r--r--i386/i386at/interrupt.S52
1 files changed, 27 insertions, 25 deletions
diff --git a/i386/i386at/interrupt.S b/i386/i386at/interrupt.S
index 1f661f8d..e9e9c0ef 100644
--- a/i386/i386at/interrupt.S
+++ b/i386/i386at/interrupt.S
@@ -41,38 +41,19 @@
ENTRY(interrupt)
#ifdef APIC
cmpl $255,%eax /* was this a spurious intr? */
- je _no_eoi /* if so, just return */
+ jne 1f
+ ret /* if so, just return */
+1:
#endif
cmpl $CALL_SINGLE_FUNCTION_BASE,%eax /* was this a SMP call single function request? */
je _call_single
subl $24,%esp /* Two local variables + 4 parameters */
movl %eax,S_IRQ /* save irq number */
+
call spl7 /* set ipl */
movl %eax,S_IPL /* save previous ipl */
- movl S_IPL,%eax
- movl %eax,4(%esp) /* previous ipl as 2nd arg */
-
- movl S_RET,%eax
- movl %eax,8(%esp) /* return address as 3rd arg */
-
- movl S_REGS,%eax
- movl %eax,12(%esp) /* address of interrupted registers as 4th arg */
-
- movl S_IRQ,%eax /* copy irq number */
-
- shll $2,%eax /* irq * 4 */
- movl EXT(iunit)(%eax),%edx /* get device unit number */
- movl %edx,(%esp) /* unit number as 1st arg */
-
- call *EXT(ivect)(%eax) /* call interrupt handler */
-
- movl S_IPL,%eax /* restore previous ipl */
- movl %eax,(%esp)
- call splx_cli /* restore previous ipl */
- cli /* XXX no more nested interrupts */
-
movl S_IRQ,%ecx /* restore irq number */
#ifndef APIC
@@ -114,12 +95,33 @@ ENTRY(interrupt)
#else
cmpl $16,%ecx /* was this a low ISA intr? */
jge _no_eoi /* no, must be PCI (let irq_ack handle EOI) */
-_isa_eoi:
movl %ecx,(%esp) /* load irq number as 1st arg */
call EXT(ioapic_irq_eoi) /* ioapic irq specific EOI */
+_no_eoi:
#endif
+
+ movl S_IPL,%eax
+ movl %eax,4(%esp) /* previous ipl as 2nd arg */
+
+ movl S_RET,%eax
+ movl %eax,8(%esp) /* return address as 3rd arg */
+
+ movl S_REGS,%eax
+ movl %eax,12(%esp) /* address of interrupted registers as 4th arg */
+
+ movl S_IRQ,%eax /* copy irq number */
+
+ shll $2,%eax /* irq * 4 */
+ movl EXT(iunit)(%eax),%edx /* get device unit number */
+ movl %edx,(%esp) /* unit number as 1st arg */
+
+ call *EXT(ivect)(%eax) /* call interrupt handler */
+
+ movl S_IPL,%eax /* restore previous ipl */
+ movl %eax,(%esp)
+ call splx_cli /* restore previous ipl */
+
addl $24,%esp /* pop local variables */
-_no_eoi:
ret
_call_single: