aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--device/intr.c16
-rw-r--r--i386/i386at/interrupt.S28
-rw-r--r--x86_64/interrupt.S28
3 files changed, 40 insertions, 32 deletions
diff --git a/device/intr.c b/device/intr.c
index 15029440..9035c036 100644
--- a/device/intr.c
+++ b/device/intr.c
@@ -50,6 +50,20 @@ search_intr (struct irqdev *dev, ipc_port_t dst_port)
return NULL;
}
+
+/*
+ * Interrupt handling logic:
+ *
+ * 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 registered, queue_intr masks the irq.
+ * interrupt.S lowers spl with splx_cli, thus IF still cleared
+ * iret, that also sets IF
+ *
+ * later on, (irq_acknowledge), userland acks the IRQ, that unmasks the irq
+ */
kern_return_t
irq_acknowledge (ipc_port_t receive_port)
{
@@ -76,8 +90,6 @@ irq_acknowledge (ipc_port_t receive_port)
if (ret)
return ret;
- (*(irqtab.irqdev_ack)) (&irqtab, e->id);
-
__enable_irq (irqtab.irq[e->id]);
return D_SUCCESS;
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)
diff --git a/x86_64/interrupt.S b/x86_64/interrupt.S
index fcd5a032..6fb77727 100644
--- a/x86_64/interrupt.S
+++ b/x86_64/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
-
subq $16,%rsp /* Two local variables */
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,%edi /* load irq number as 1st arg */
call EXT(ioapic_irq_eoi) /* ioapic irq specific EOI */
-_no_eoi:
#endif
;
@@ -121,6 +118,7 @@ _no_eoi:
shll $1,%eax /* irq * 8 */
call *EXT(ivect)(%rax) /* call interrupt handler */
+_completed:
movl S_IPL,%edi /* restore previous ipl */
call splx_cli /* restore previous ipl */
@@ -129,14 +127,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)