summaryrefslogtreecommitdiff
path: root/i386
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2023-10-02 03:39:13 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-03 20:23:37 +0200
commit60c53f565454a6afd8f0b80d36d791d50653751d (patch)
treec564a05516645344dbca35a40a198951627458b9 /i386
parent34623c520c66df73663a6e02a05551e7330b9e5e (diff)
Fix interrupt handling
Logic for interrupts: - interrupt.S raises spl (thus IF cleared) - interrupt.S EOI - interrupt.S calls the handler - for pure in-kernel handlers, they do whatever they want with IF cleared. - when a userland handler is registers, queue_intr masks the irq. - interrupt.S lowers spl with splx_cli, thus IF still cleared - iret, that sets IF - later on, userland acks the IRQ, that unmasks the irq The key to this change is that all interrupts, including IPIs, are treated the same way. Eg. the spl level is now raised before an IPI and restored after. Also, EOI is not needed inside irq_acknowledge. With this change and the experimental change not to dispatch threads direct to idle processors in the scheduler, I no longer observe kernel faults, but an occasional hang does occur. Message-Id: <20231002033906.124427-1-damien@zamaudio.com>
Diffstat (limited to 'i386')
-rw-r--r--i386/i386at/interrupt.S28
1 files changed, 13 insertions, 15 deletions
diff --git a/i386/i386at/interrupt.S b/i386/i386at/interrupt.S
index 8ae6b97c..77424b43 100644
--- a/i386/i386at/interrupt.S
+++ b/i386/i386at/interrupt.S
@@ -45,14 +45,6 @@ ENTRY(interrupt)
ret /* if so, just return */
1:
#endif
-#if NCPUS > 1
- cmpl $CALL_PMAP_UPDATE,%eax /* was this a SMP pmap_update request? */
- je _call_single
-
- cmpl $CALL_AST_CHECK,%eax /* was this a SMP remote -> local ast request? */
- je _call_local_ast
-#endif
-
subl $24,%esp /* Two local variables + 4 parameters */
movl %eax,S_IRQ /* save irq number */
@@ -61,6 +53,14 @@ ENTRY(interrupt)
movl S_IRQ,%ecx /* restore irq number */
+#if NCPUS > 1
+ cmpl $CALL_PMAP_UPDATE,%ecx /* was this a SMP pmap_update request? */
+ je _call_single
+
+ cmpl $CALL_AST_CHECK,%ecx /* was this a SMP remote -> local ast request? */
+ je _call_local_ast
+#endif
+
#ifndef APIC
movl $1,%eax
shll %cl,%eax /* get corresponding IRQ mask */
@@ -98,11 +98,8 @@ ENTRY(interrupt)
outb %al,$(PIC_MASTER_OCW) /* unmask master */
2:
#else
- cmpl $16,%ecx /* was this a low ISA intr? */
- jge _no_eoi /* no, must be PCI (let irq_ack handle 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
@@ -122,6 +119,7 @@ _no_eoi:
call *EXT(ivect)(%eax) /* call interrupt handler */
+_completed:
movl S_IPL,%eax /* restore previous ipl */
movl %eax,(%esp)
call splx_cli /* restore previous ipl */
@@ -131,14 +129,14 @@ _no_eoi:
#if NCPUS > 1
_call_single:
- cli /* no nested interrupts */
call EXT(lapic_eoi) /* lapic EOI before the handler to allow extra update */
call EXT(pmap_update_interrupt)
- ret
+ jmp _completed
_call_local_ast:
- call EXT(ast_check) /* AST check on this cpu */
call EXT(lapic_eoi) /* lapic EOI */
- ret
+ call EXT(ast_check) /* AST check on this cpu */
+ jmp _completed
+
#endif
END(interrupt)