summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/apic_vector.S91
-rw-r--r--sys/amd64/isa/intr_machdep.c42
-rw-r--r--sys/amd64/isa/intr_machdep.h77
-rw-r--r--sys/amd64/isa/nmi.c42
-rw-r--r--sys/i386/i386/apic_vector.s91
-rw-r--r--sys/i386/isa/apic_ipl.s18
-rw-r--r--sys/i386/isa/apic_vector.s91
-rw-r--r--sys/i386/isa/intr_machdep.c42
-rw-r--r--sys/i386/isa/intr_machdep.h77
-rw-r--r--sys/i386/isa/ipl.s47
-rw-r--r--sys/i386/isa/ipl_funcs.c4
-rw-r--r--sys/i386/isa/nmi.c42
12 files changed, 529 insertions, 135 deletions
diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S
index 71c341d..d78d320 100644
--- a/sys/amd64/amd64/apic_vector.S
+++ b/sys/amd64/amd64/apic_vector.S
@@ -1,6 +1,6 @@
/*
* from: vector.s, 386BSD 0.1 unknown origin
- * $Id: apic_vector.s,v 1.27 1997/08/23 05:15:12 smp Exp smp $
+ * $Id: apic_vector.s,v 1.32 1997/08/29 18:37:23 smp Exp smp $
*/
@@ -11,17 +11,17 @@
#include "i386/isa/intr_machdep.h"
-#if defined(SMP) && defined(REAL_AVCPL)
+#ifdef REAL_AVCPL
#define AVCPL_LOCK CPL_LOCK
#define AVCPL_UNLOCK CPL_UNLOCK
-#else
+#else /* REAL_AVCPL */
#define AVCPL_LOCK
#define AVCPL_UNLOCK
-#endif
+#endif /* REAL_AVCPL */
#ifdef FAST_SIMPLELOCK
@@ -213,6 +213,8 @@ IDTVEC(vec_name) ; \
9: ; \
IMASK_UNLOCK
+#ifdef INTR_SIMPLELOCK
+
#define INTR(irq_num, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
@@ -233,6 +235,8 @@ IDTVEC(vec_name) ; \
AVCPL_LOCK ; /* MP-safe */ \
testl $IRQ_BIT(irq_num), _cpl ; \
jne 2f ; /* this INT masked */ \
+ testl $IRQ_BIT(irq_num), _cml ; \
+ jne 2f ; /* this INT masked */ \
orl $IRQ_BIT(irq_num), _cil ; \
AVCPL_UNLOCK ; \
; \
@@ -245,6 +249,75 @@ __CONCAT(Xresume,irq_num): ; \
lock ; incl (%eax) ; \
; \
AVCPL_LOCK ; /* MP-safe */ \
+ movl _cml, %eax ; \
+ pushl %eax ; \
+ orl _intr_mask + (irq_num) * 4, %eax ; \
+ movl %eax, _cml ; \
+ AVCPL_UNLOCK ; \
+; \
+ pushl _intr_unit + (irq_num) * 4 ; \
+ sti ; \
+ call *_intr_handler + (irq_num) * 4 ; \
+ cli ; \
+; \
+ lock ; andl $~IRQ_BIT(irq_num), iactive ; \
+ lock ; andl $~IRQ_BIT(irq_num), _cil ; \
+ UNMASK_IRQ(irq_num) ; \
+ sti ; /* doreti repeats cli/sti */ \
+ MEXITCOUNT ; \
+ jmp _doreti ; \
+; \
+ ALIGN_TEXT ; \
+1: ; /* active or locked */ \
+ MASK_LEVEL_IRQ(irq_num) ; \
+ movl $0, lapic_eoi ; /* do the EOI */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ orl $IRQ_BIT(irq_num), _ipending ; \
+ AVCPL_UNLOCK ; \
+; \
+ POP_FRAME ; \
+ iret ; \
+; \
+ ALIGN_TEXT ; \
+2: ; /* masked by cpl|cml */ \
+ AVCPL_UNLOCK ; \
+ ISR_RELLOCK ; /* XXX this is going away... */ \
+ jmp 1b
+
+#else /* INTR_SIMPLELOCK */
+
+#define INTR(irq_num, vec_name) \
+ .text ; \
+ SUPERALIGN_TEXT ; \
+IDTVEC(vec_name) ; \
+ PUSH_FRAME ; \
+ movl $KDSEL, %eax ; /* reload with kernel's data segment */ \
+ movl %ax, %ds ; \
+ movl %ax, %es ; \
+; \
+ lock ; /* MP-safe */ \
+ btsl $(irq_num), iactive ; /* lazy masking */ \
+ jc 1f ; /* already active */ \
+; \
+ ISR_TRYLOCK ; /* XXX this is going away... */ \
+ testl %eax, %eax ; /* did we get it? */ \
+ jz 1f ; /* no */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ testl $IRQ_BIT(irq_num), _cpl ; \
+ jne 2f ; /* this INT masked */ \
+ AVCPL_UNLOCK ; \
+; \
+ movl $0, lapic_eoi ; /* XXX too soon? */ \
+ incb _intr_nesting_level ; \
+__CONCAT(Xresume,irq_num): ; \
+ FAKE_MCOUNT(12*4(%esp)) ; /* XXX avoid dbl cnt */ \
+ lock ; incl _cnt+V_INTR ; /* tally interrupts */ \
+ movl _intr_countp + (irq_num) * 4, %eax ; \
+ lock ; incl (%eax) ; \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
movl _cpl, %eax ; \
pushl %eax ; \
orl _intr_mask + (irq_num) * 4, %eax ; \
@@ -280,6 +353,8 @@ __CONCAT(Xresume,irq_num): ; \
ISR_RELLOCK ; /* XXX this is going away... */ \
jmp 1b
+#endif /* INTR_SIMPLELOCK */
+
/*
* Handle "spurious INTerrupts".
@@ -344,23 +419,15 @@ _Xcpustop:
movl _cpuid, %eax
- ASMPOSTCODE_HI(0x1)
-
lock
btsl %eax, _stopped_cpus /* stopped_cpus |= (1<<id) */
-
- ASMPOSTCODE_HI(0x2);
1:
btl %eax, _started_cpus /* while (!(started_cpus & (1<<id))) */
jnc 1b
- ASMPOSTCODE_HI(0x3)
-
lock
btrl %eax, _started_cpus /* started_cpus &= ~(1<<id) */
- ASMPOSTCODE_HI(0x4)
-
movl $0, lapic_eoi /* End Of Interrupt to APIC */
popl %ds /* restore previous data segment */
diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c
index 5f241d6..c9b5da5 100644
--- a/sys/amd64/isa/intr_machdep.c
+++ b/sys/amd64/isa/intr_machdep.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.3 1997/06/22 16:04:04 peter Exp $
+ * $Id: intr_machdep.c,v 1.1 1997/08/29 18:38:35 smp Exp smp $
*/
#include "opt_auto_eoi.h"
@@ -47,6 +47,7 @@
#include <machine/segments.h>
#if defined(APIC_IO)
#include <machine/smp.h>
+#include <machine/smptests.h> /** FAST_HI */
#endif /* APIC_IO */
#include <i386/isa/isa_device.h>
#ifdef PC98
@@ -260,9 +261,17 @@ int
isa_irq_pending(dvp)
struct isa_device *dvp;
{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic.irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
+#ifdef FAST_HI
+/* XXX not quite right for >1 IO APIC yet */
+ if (dvp->id_ri_flags & RI_FAST)
+ /* read APIC IRR containing the FAST INTerrupts */
+ return ((lapic.irr3 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+ else
+#endif /* FAST_HI */
+ /* read APIC IRR containing the SLOW INTerrupts */
+ return ((lapic.irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
}
/*
@@ -396,6 +405,11 @@ update_intrname(int intr, int device_id)
int
icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
{
+#ifdef FAST_HI
+ int select; /* the select register is 8 bits */
+ int vector;
+ u_int32_t value; /* the window register is 32 bits */
+#endif /* FAST_HI */
u_long ef;
u_int mask = (maskptr ? *maskptr : 0);
@@ -413,9 +427,29 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
intr_mptr[intr] = maskptr;
intr_mask[intr] = mask | (1 << intr);
intr_unit[intr] = (int) arg;
+#ifdef FAST_HI
+ if (flags & INTR_FAST) {
+ vector = TPR_FAST_INTS + intr;
+ setidt(vector, fastintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+ /*
+ * XXX MULTIPLE_IOAPICSXXX
+ * Reprogram the vector in the IO APIC.
+ */
+ select = (intr * 2) + IOAPIC_REDTBL0;
+ value = io_apic_read(0, select) & ~IOART_INTVEC;
+ io_apic_write(0, select, value | vector);
+ }
+ else
+ setidt(TPR_SLOW_INTS + intr, slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+#else
setidt(ICU_OFFSET + intr,
flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif /* FAST_HI */
INTREN(1 << intr);
write_eflags(ef);
return (0);
diff --git a/sys/amd64/isa/intr_machdep.h b/sys/amd64/isa/intr_machdep.h
index c164799..6df8f3a 100644
--- a/sys/amd64/isa/intr_machdep.h
+++ b/sys/amd64/isa/intr_machdep.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: intr_machdep.h,v 1.5 1997/07/18 21:27:14 fsmp Exp $
+ * $Id: intr_machdep.h,v 1.10 1997/08/29 18:37:23 smp Exp smp $
*/
#ifndef _I386_ISA_INTR_MACHDEP_H_
@@ -50,43 +50,50 @@
/*
APIC TPR priority vector levels:
- 0xff (255) +------------+
- | | 15 (IPIs: Xspuriousint)
- 0xf0 (240) +------------+
- | | 14
- 0xe0 (224) +------------+
- | | 13
- 0xd0 (208) +------------+
- | | 12
- 0xc0 (192) +------------+
- | | 11
- 0xb0 (176) +------------+
- | | 10 (IPIs: Xcpustop)
- 0xa0 (160) +------------+
- | | 9 (IPIs: Xinvltlb)
- 0x90 (144) +------------+
- | | 8 (linux compat @ vector 0x80)
- 0x80 (128) +------------+
- | | 7
- 0x70 (112) +------------+
- | | 6
- 0x60 (96) +------------+
- | | 5
- 0x50 (80) +------------+
- | | 4
- 0x40 (64) +------------+
- | | 3 (upper APIC hardware INTs: PCI)
- 0x30 (48) +------------+
- | | 2 (start of hardware INTs: ISA)
- 0x20 (32) +------------+
- | | 1 (exceptions, traps, etc.)
- 0x10 (16) +------------+
- | | 0 (exceptions, traps, etc.)
- 0x00 (0) +------------+
+ 0xff (255) +-------------+
+ | | 15 (IPIs: Xspuriousint)
+ 0xf0 (240) +-------------+
+ | | 14
+ 0xe0 (224) +-------------+
+ | | 13
+ 0xd0 (208) +-------------+
+ | | 12
+ 0xc0 (192) +-------------+
+ | | 11
+ 0xb0 (176) +-------------+
+ | | 10 (IPIs: Xcpustop)
+ 0xa0 (160) +-------------+
+ | | 9 (IPIs: Xinvltlb)
+ 0x90 (144) +-------------+
+ | | 8 (linux/BSD syscall, IGNORE FAST HW INTS)
+ 0x80 (128) +-------------+
+ | | 7 (FAST_INTR 16-23)
+ 0x70 (112) +-------------+
+ | | 6 (FAST_INTR 0-15)
+ 0x60 (96) +-------------+
+ | | 5 (IGNORE HW INTS)
+ 0x50 (80) +-------------+
+ | | 4 (2nd IO APIC)
+ 0x40 (64) +------+------+
+ | | | 3 (upper APIC hardware INTs: PCI)
+ 0x30 (48) +------+------+
+ | | 2 (start of hardware INTs: ISA)
+ 0x20 (32) +-------------+
+ | | 1 (exceptions, traps, etc.)
+ 0x10 (16) +-------------+
+ | | 0 (exceptions, traps, etc.)
+ 0x00 (0) +-------------+
*/
+/* IDT vector base for regular (aka. slow) and fast interrupts */
+#define TPR_SLOW_INTS 0x20
+#define TPR_FAST_INTS 0x60
+
/* blocking values for local APIC Task Priority Register */
-#define TPR_BLOCK_HWI 0x3f /* hardware INTs */
+#define TPR_BLOCK_HWI 0x4f /* hardware INTs */
+#define TPR_IGNORE_HWI 0x5f /* ignore INTs */
+#define TPR_BLOCK_FHWI 0x7f /* hardware FAST INTs */
+#define TPR_IGNORE_FHWI 0x8f /* ignore FAST INTs */
#define TPR_BLOCK_XINVLTLB 0x9f /* */
#define TPR_BLOCK_XCPUSTOP 0xaf /* */
#define TPR_BLOCK_ALL 0xff /* all INTs */
diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c
index 5f241d6..c9b5da5 100644
--- a/sys/amd64/isa/nmi.c
+++ b/sys/amd64/isa/nmi.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.3 1997/06/22 16:04:04 peter Exp $
+ * $Id: intr_machdep.c,v 1.1 1997/08/29 18:38:35 smp Exp smp $
*/
#include "opt_auto_eoi.h"
@@ -47,6 +47,7 @@
#include <machine/segments.h>
#if defined(APIC_IO)
#include <machine/smp.h>
+#include <machine/smptests.h> /** FAST_HI */
#endif /* APIC_IO */
#include <i386/isa/isa_device.h>
#ifdef PC98
@@ -260,9 +261,17 @@ int
isa_irq_pending(dvp)
struct isa_device *dvp;
{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic.irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
+#ifdef FAST_HI
+/* XXX not quite right for >1 IO APIC yet */
+ if (dvp->id_ri_flags & RI_FAST)
+ /* read APIC IRR containing the FAST INTerrupts */
+ return ((lapic.irr3 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+ else
+#endif /* FAST_HI */
+ /* read APIC IRR containing the SLOW INTerrupts */
+ return ((lapic.irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
}
/*
@@ -396,6 +405,11 @@ update_intrname(int intr, int device_id)
int
icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
{
+#ifdef FAST_HI
+ int select; /* the select register is 8 bits */
+ int vector;
+ u_int32_t value; /* the window register is 32 bits */
+#endif /* FAST_HI */
u_long ef;
u_int mask = (maskptr ? *maskptr : 0);
@@ -413,9 +427,29 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
intr_mptr[intr] = maskptr;
intr_mask[intr] = mask | (1 << intr);
intr_unit[intr] = (int) arg;
+#ifdef FAST_HI
+ if (flags & INTR_FAST) {
+ vector = TPR_FAST_INTS + intr;
+ setidt(vector, fastintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+ /*
+ * XXX MULTIPLE_IOAPICSXXX
+ * Reprogram the vector in the IO APIC.
+ */
+ select = (intr * 2) + IOAPIC_REDTBL0;
+ value = io_apic_read(0, select) & ~IOART_INTVEC;
+ io_apic_write(0, select, value | vector);
+ }
+ else
+ setidt(TPR_SLOW_INTS + intr, slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+#else
setidt(ICU_OFFSET + intr,
flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif /* FAST_HI */
INTREN(1 << intr);
write_eflags(ef);
return (0);
diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s
index 71c341d..d78d320 100644
--- a/sys/i386/i386/apic_vector.s
+++ b/sys/i386/i386/apic_vector.s
@@ -1,6 +1,6 @@
/*
* from: vector.s, 386BSD 0.1 unknown origin
- * $Id: apic_vector.s,v 1.27 1997/08/23 05:15:12 smp Exp smp $
+ * $Id: apic_vector.s,v 1.32 1997/08/29 18:37:23 smp Exp smp $
*/
@@ -11,17 +11,17 @@
#include "i386/isa/intr_machdep.h"
-#if defined(SMP) && defined(REAL_AVCPL)
+#ifdef REAL_AVCPL
#define AVCPL_LOCK CPL_LOCK
#define AVCPL_UNLOCK CPL_UNLOCK
-#else
+#else /* REAL_AVCPL */
#define AVCPL_LOCK
#define AVCPL_UNLOCK
-#endif
+#endif /* REAL_AVCPL */
#ifdef FAST_SIMPLELOCK
@@ -213,6 +213,8 @@ IDTVEC(vec_name) ; \
9: ; \
IMASK_UNLOCK
+#ifdef INTR_SIMPLELOCK
+
#define INTR(irq_num, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
@@ -233,6 +235,8 @@ IDTVEC(vec_name) ; \
AVCPL_LOCK ; /* MP-safe */ \
testl $IRQ_BIT(irq_num), _cpl ; \
jne 2f ; /* this INT masked */ \
+ testl $IRQ_BIT(irq_num), _cml ; \
+ jne 2f ; /* this INT masked */ \
orl $IRQ_BIT(irq_num), _cil ; \
AVCPL_UNLOCK ; \
; \
@@ -245,6 +249,75 @@ __CONCAT(Xresume,irq_num): ; \
lock ; incl (%eax) ; \
; \
AVCPL_LOCK ; /* MP-safe */ \
+ movl _cml, %eax ; \
+ pushl %eax ; \
+ orl _intr_mask + (irq_num) * 4, %eax ; \
+ movl %eax, _cml ; \
+ AVCPL_UNLOCK ; \
+; \
+ pushl _intr_unit + (irq_num) * 4 ; \
+ sti ; \
+ call *_intr_handler + (irq_num) * 4 ; \
+ cli ; \
+; \
+ lock ; andl $~IRQ_BIT(irq_num), iactive ; \
+ lock ; andl $~IRQ_BIT(irq_num), _cil ; \
+ UNMASK_IRQ(irq_num) ; \
+ sti ; /* doreti repeats cli/sti */ \
+ MEXITCOUNT ; \
+ jmp _doreti ; \
+; \
+ ALIGN_TEXT ; \
+1: ; /* active or locked */ \
+ MASK_LEVEL_IRQ(irq_num) ; \
+ movl $0, lapic_eoi ; /* do the EOI */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ orl $IRQ_BIT(irq_num), _ipending ; \
+ AVCPL_UNLOCK ; \
+; \
+ POP_FRAME ; \
+ iret ; \
+; \
+ ALIGN_TEXT ; \
+2: ; /* masked by cpl|cml */ \
+ AVCPL_UNLOCK ; \
+ ISR_RELLOCK ; /* XXX this is going away... */ \
+ jmp 1b
+
+#else /* INTR_SIMPLELOCK */
+
+#define INTR(irq_num, vec_name) \
+ .text ; \
+ SUPERALIGN_TEXT ; \
+IDTVEC(vec_name) ; \
+ PUSH_FRAME ; \
+ movl $KDSEL, %eax ; /* reload with kernel's data segment */ \
+ movl %ax, %ds ; \
+ movl %ax, %es ; \
+; \
+ lock ; /* MP-safe */ \
+ btsl $(irq_num), iactive ; /* lazy masking */ \
+ jc 1f ; /* already active */ \
+; \
+ ISR_TRYLOCK ; /* XXX this is going away... */ \
+ testl %eax, %eax ; /* did we get it? */ \
+ jz 1f ; /* no */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ testl $IRQ_BIT(irq_num), _cpl ; \
+ jne 2f ; /* this INT masked */ \
+ AVCPL_UNLOCK ; \
+; \
+ movl $0, lapic_eoi ; /* XXX too soon? */ \
+ incb _intr_nesting_level ; \
+__CONCAT(Xresume,irq_num): ; \
+ FAKE_MCOUNT(12*4(%esp)) ; /* XXX avoid dbl cnt */ \
+ lock ; incl _cnt+V_INTR ; /* tally interrupts */ \
+ movl _intr_countp + (irq_num) * 4, %eax ; \
+ lock ; incl (%eax) ; \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
movl _cpl, %eax ; \
pushl %eax ; \
orl _intr_mask + (irq_num) * 4, %eax ; \
@@ -280,6 +353,8 @@ __CONCAT(Xresume,irq_num): ; \
ISR_RELLOCK ; /* XXX this is going away... */ \
jmp 1b
+#endif /* INTR_SIMPLELOCK */
+
/*
* Handle "spurious INTerrupts".
@@ -344,23 +419,15 @@ _Xcpustop:
movl _cpuid, %eax
- ASMPOSTCODE_HI(0x1)
-
lock
btsl %eax, _stopped_cpus /* stopped_cpus |= (1<<id) */
-
- ASMPOSTCODE_HI(0x2);
1:
btl %eax, _started_cpus /* while (!(started_cpus & (1<<id))) */
jnc 1b
- ASMPOSTCODE_HI(0x3)
-
lock
btrl %eax, _started_cpus /* started_cpus &= ~(1<<id) */
- ASMPOSTCODE_HI(0x4)
-
movl $0, lapic_eoi /* End Of Interrupt to APIC */
popl %ds /* restore previous data segment */
diff --git a/sys/i386/isa/apic_ipl.s b/sys/i386/isa/apic_ipl.s
index ec9b94f..6df74c3 100644
--- a/sys/i386/isa/apic_ipl.s
+++ b/sys/i386/isa/apic_ipl.s
@@ -22,21 +22,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: apic_ipl.s,v 1.28 1997/08/23 05:15:12 smp Exp smp $
+ * $Id: apic_ipl.s,v 1.32 1997/08/29 18:39:36 smp Exp smp $
*/
-#if defined(SMP) && defined(REAL_AICPL)
+#ifdef REAL_AICPL
#define AICPL_LOCK SCPL_LOCK
#define AICPL_UNLOCK SCPL_UNLOCK
-#else /* SMP */
+#else /* REAL_AICPL */
#define AICPL_LOCK
#define AICPL_UNLOCK
-#endif /* SMP */
+#endif /* REAL_AICPL */
.data
ALIGN_DATA
@@ -45,6 +45,10 @@
.globl _cil
_cil: .long 0
+/* current INTerrupt level mask */
+ .globl _cml
+_cml: .long 0
+
/* this allows us to change the 8254 APIC pin# assignment */
.globl _Xintr8254
_Xintr8254:
@@ -107,6 +111,9 @@ ENTRY(splz)
*/
AICPL_LOCK
movl _cpl,%eax
+#ifdef INTR_SIMPLELOCK
+ orl _cml, %eax /* add cml to cpl */
+#endif
splz_next:
/*
* We don't need any locking here. (ipending & ~cpl) cannot grow
@@ -137,6 +144,9 @@ splz_unpend:
* frame. Also, there's a problem determining the unit number.
* We should change the interface so that the unit number is not
* determined at config time.
+ *
+ * The vec[] routines build the proper frame on the stack,
+ * then call one of _Xintr0 thru _Xintr23
*/
jmp *_vec(,%ecx,4)
diff --git a/sys/i386/isa/apic_vector.s b/sys/i386/isa/apic_vector.s
index 71c341d..d78d320 100644
--- a/sys/i386/isa/apic_vector.s
+++ b/sys/i386/isa/apic_vector.s
@@ -1,6 +1,6 @@
/*
* from: vector.s, 386BSD 0.1 unknown origin
- * $Id: apic_vector.s,v 1.27 1997/08/23 05:15:12 smp Exp smp $
+ * $Id: apic_vector.s,v 1.32 1997/08/29 18:37:23 smp Exp smp $
*/
@@ -11,17 +11,17 @@
#include "i386/isa/intr_machdep.h"
-#if defined(SMP) && defined(REAL_AVCPL)
+#ifdef REAL_AVCPL
#define AVCPL_LOCK CPL_LOCK
#define AVCPL_UNLOCK CPL_UNLOCK
-#else
+#else /* REAL_AVCPL */
#define AVCPL_LOCK
#define AVCPL_UNLOCK
-#endif
+#endif /* REAL_AVCPL */
#ifdef FAST_SIMPLELOCK
@@ -213,6 +213,8 @@ IDTVEC(vec_name) ; \
9: ; \
IMASK_UNLOCK
+#ifdef INTR_SIMPLELOCK
+
#define INTR(irq_num, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
@@ -233,6 +235,8 @@ IDTVEC(vec_name) ; \
AVCPL_LOCK ; /* MP-safe */ \
testl $IRQ_BIT(irq_num), _cpl ; \
jne 2f ; /* this INT masked */ \
+ testl $IRQ_BIT(irq_num), _cml ; \
+ jne 2f ; /* this INT masked */ \
orl $IRQ_BIT(irq_num), _cil ; \
AVCPL_UNLOCK ; \
; \
@@ -245,6 +249,75 @@ __CONCAT(Xresume,irq_num): ; \
lock ; incl (%eax) ; \
; \
AVCPL_LOCK ; /* MP-safe */ \
+ movl _cml, %eax ; \
+ pushl %eax ; \
+ orl _intr_mask + (irq_num) * 4, %eax ; \
+ movl %eax, _cml ; \
+ AVCPL_UNLOCK ; \
+; \
+ pushl _intr_unit + (irq_num) * 4 ; \
+ sti ; \
+ call *_intr_handler + (irq_num) * 4 ; \
+ cli ; \
+; \
+ lock ; andl $~IRQ_BIT(irq_num), iactive ; \
+ lock ; andl $~IRQ_BIT(irq_num), _cil ; \
+ UNMASK_IRQ(irq_num) ; \
+ sti ; /* doreti repeats cli/sti */ \
+ MEXITCOUNT ; \
+ jmp _doreti ; \
+; \
+ ALIGN_TEXT ; \
+1: ; /* active or locked */ \
+ MASK_LEVEL_IRQ(irq_num) ; \
+ movl $0, lapic_eoi ; /* do the EOI */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ orl $IRQ_BIT(irq_num), _ipending ; \
+ AVCPL_UNLOCK ; \
+; \
+ POP_FRAME ; \
+ iret ; \
+; \
+ ALIGN_TEXT ; \
+2: ; /* masked by cpl|cml */ \
+ AVCPL_UNLOCK ; \
+ ISR_RELLOCK ; /* XXX this is going away... */ \
+ jmp 1b
+
+#else /* INTR_SIMPLELOCK */
+
+#define INTR(irq_num, vec_name) \
+ .text ; \
+ SUPERALIGN_TEXT ; \
+IDTVEC(vec_name) ; \
+ PUSH_FRAME ; \
+ movl $KDSEL, %eax ; /* reload with kernel's data segment */ \
+ movl %ax, %ds ; \
+ movl %ax, %es ; \
+; \
+ lock ; /* MP-safe */ \
+ btsl $(irq_num), iactive ; /* lazy masking */ \
+ jc 1f ; /* already active */ \
+; \
+ ISR_TRYLOCK ; /* XXX this is going away... */ \
+ testl %eax, %eax ; /* did we get it? */ \
+ jz 1f ; /* no */ \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
+ testl $IRQ_BIT(irq_num), _cpl ; \
+ jne 2f ; /* this INT masked */ \
+ AVCPL_UNLOCK ; \
+; \
+ movl $0, lapic_eoi ; /* XXX too soon? */ \
+ incb _intr_nesting_level ; \
+__CONCAT(Xresume,irq_num): ; \
+ FAKE_MCOUNT(12*4(%esp)) ; /* XXX avoid dbl cnt */ \
+ lock ; incl _cnt+V_INTR ; /* tally interrupts */ \
+ movl _intr_countp + (irq_num) * 4, %eax ; \
+ lock ; incl (%eax) ; \
+; \
+ AVCPL_LOCK ; /* MP-safe */ \
movl _cpl, %eax ; \
pushl %eax ; \
orl _intr_mask + (irq_num) * 4, %eax ; \
@@ -280,6 +353,8 @@ __CONCAT(Xresume,irq_num): ; \
ISR_RELLOCK ; /* XXX this is going away... */ \
jmp 1b
+#endif /* INTR_SIMPLELOCK */
+
/*
* Handle "spurious INTerrupts".
@@ -344,23 +419,15 @@ _Xcpustop:
movl _cpuid, %eax
- ASMPOSTCODE_HI(0x1)
-
lock
btsl %eax, _stopped_cpus /* stopped_cpus |= (1<<id) */
-
- ASMPOSTCODE_HI(0x2);
1:
btl %eax, _started_cpus /* while (!(started_cpus & (1<<id))) */
jnc 1b
- ASMPOSTCODE_HI(0x3)
-
lock
btrl %eax, _started_cpus /* started_cpus &= ~(1<<id) */
- ASMPOSTCODE_HI(0x4)
-
movl $0, lapic_eoi /* End Of Interrupt to APIC */
popl %ds /* restore previous data segment */
diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c
index 5f241d6..c9b5da5 100644
--- a/sys/i386/isa/intr_machdep.c
+++ b/sys/i386/isa/intr_machdep.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.3 1997/06/22 16:04:04 peter Exp $
+ * $Id: intr_machdep.c,v 1.1 1997/08/29 18:38:35 smp Exp smp $
*/
#include "opt_auto_eoi.h"
@@ -47,6 +47,7 @@
#include <machine/segments.h>
#if defined(APIC_IO)
#include <machine/smp.h>
+#include <machine/smptests.h> /** FAST_HI */
#endif /* APIC_IO */
#include <i386/isa/isa_device.h>
#ifdef PC98
@@ -260,9 +261,17 @@ int
isa_irq_pending(dvp)
struct isa_device *dvp;
{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic.irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
+#ifdef FAST_HI
+/* XXX not quite right for >1 IO APIC yet */
+ if (dvp->id_ri_flags & RI_FAST)
+ /* read APIC IRR containing the FAST INTerrupts */
+ return ((lapic.irr3 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+ else
+#endif /* FAST_HI */
+ /* read APIC IRR containing the SLOW INTerrupts */
+ return ((lapic.irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
}
/*
@@ -396,6 +405,11 @@ update_intrname(int intr, int device_id)
int
icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
{
+#ifdef FAST_HI
+ int select; /* the select register is 8 bits */
+ int vector;
+ u_int32_t value; /* the window register is 32 bits */
+#endif /* FAST_HI */
u_long ef;
u_int mask = (maskptr ? *maskptr : 0);
@@ -413,9 +427,29 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
intr_mptr[intr] = maskptr;
intr_mask[intr] = mask | (1 << intr);
intr_unit[intr] = (int) arg;
+#ifdef FAST_HI
+ if (flags & INTR_FAST) {
+ vector = TPR_FAST_INTS + intr;
+ setidt(vector, fastintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+ /*
+ * XXX MULTIPLE_IOAPICSXXX
+ * Reprogram the vector in the IO APIC.
+ */
+ select = (intr * 2) + IOAPIC_REDTBL0;
+ value = io_apic_read(0, select) & ~IOART_INTVEC;
+ io_apic_write(0, select, value | vector);
+ }
+ else
+ setidt(TPR_SLOW_INTS + intr, slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+#else
setidt(ICU_OFFSET + intr,
flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif /* FAST_HI */
INTREN(1 << intr);
write_eflags(ef);
return (0);
diff --git a/sys/i386/isa/intr_machdep.h b/sys/i386/isa/intr_machdep.h
index c164799..6df8f3a 100644
--- a/sys/i386/isa/intr_machdep.h
+++ b/sys/i386/isa/intr_machdep.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: intr_machdep.h,v 1.5 1997/07/18 21:27:14 fsmp Exp $
+ * $Id: intr_machdep.h,v 1.10 1997/08/29 18:37:23 smp Exp smp $
*/
#ifndef _I386_ISA_INTR_MACHDEP_H_
@@ -50,43 +50,50 @@
/*
APIC TPR priority vector levels:
- 0xff (255) +------------+
- | | 15 (IPIs: Xspuriousint)
- 0xf0 (240) +------------+
- | | 14
- 0xe0 (224) +------------+
- | | 13
- 0xd0 (208) +------------+
- | | 12
- 0xc0 (192) +------------+
- | | 11
- 0xb0 (176) +------------+
- | | 10 (IPIs: Xcpustop)
- 0xa0 (160) +------------+
- | | 9 (IPIs: Xinvltlb)
- 0x90 (144) +------------+
- | | 8 (linux compat @ vector 0x80)
- 0x80 (128) +------------+
- | | 7
- 0x70 (112) +------------+
- | | 6
- 0x60 (96) +------------+
- | | 5
- 0x50 (80) +------------+
- | | 4
- 0x40 (64) +------------+
- | | 3 (upper APIC hardware INTs: PCI)
- 0x30 (48) +------------+
- | | 2 (start of hardware INTs: ISA)
- 0x20 (32) +------------+
- | | 1 (exceptions, traps, etc.)
- 0x10 (16) +------------+
- | | 0 (exceptions, traps, etc.)
- 0x00 (0) +------------+
+ 0xff (255) +-------------+
+ | | 15 (IPIs: Xspuriousint)
+ 0xf0 (240) +-------------+
+ | | 14
+ 0xe0 (224) +-------------+
+ | | 13
+ 0xd0 (208) +-------------+
+ | | 12
+ 0xc0 (192) +-------------+
+ | | 11
+ 0xb0 (176) +-------------+
+ | | 10 (IPIs: Xcpustop)
+ 0xa0 (160) +-------------+
+ | | 9 (IPIs: Xinvltlb)
+ 0x90 (144) +-------------+
+ | | 8 (linux/BSD syscall, IGNORE FAST HW INTS)
+ 0x80 (128) +-------------+
+ | | 7 (FAST_INTR 16-23)
+ 0x70 (112) +-------------+
+ | | 6 (FAST_INTR 0-15)
+ 0x60 (96) +-------------+
+ | | 5 (IGNORE HW INTS)
+ 0x50 (80) +-------------+
+ | | 4 (2nd IO APIC)
+ 0x40 (64) +------+------+
+ | | | 3 (upper APIC hardware INTs: PCI)
+ 0x30 (48) +------+------+
+ | | 2 (start of hardware INTs: ISA)
+ 0x20 (32) +-------------+
+ | | 1 (exceptions, traps, etc.)
+ 0x10 (16) +-------------+
+ | | 0 (exceptions, traps, etc.)
+ 0x00 (0) +-------------+
*/
+/* IDT vector base for regular (aka. slow) and fast interrupts */
+#define TPR_SLOW_INTS 0x20
+#define TPR_FAST_INTS 0x60
+
/* blocking values for local APIC Task Priority Register */
-#define TPR_BLOCK_HWI 0x3f /* hardware INTs */
+#define TPR_BLOCK_HWI 0x4f /* hardware INTs */
+#define TPR_IGNORE_HWI 0x5f /* ignore INTs */
+#define TPR_BLOCK_FHWI 0x7f /* hardware FAST INTs */
+#define TPR_IGNORE_FHWI 0x8f /* ignore FAST INTs */
#define TPR_BLOCK_XINVLTLB 0x9f /* */
#define TPR_BLOCK_XCPUSTOP 0xaf /* */
#define TPR_BLOCK_ALL 0xff /* all INTs */
diff --git a/sys/i386/isa/ipl.s b/sys/i386/isa/ipl.s
index 6393882..481f886 100644
--- a/sys/i386/isa/ipl.s
+++ b/sys/i386/isa/ipl.s
@@ -36,23 +36,23 @@
*
* @(#)ipl.s
*
- * $Id: ipl.s,v 1.13 1997/08/23 05:15:12 smp Exp smp $
+ * $Id: ipl.s,v 1.16 1997/08/28 09:51:32 smp Exp smp $
*/
-#if defined(SMP) && defined(REAL_ICPL)
+#ifdef REAL_ICPL
#define ICPL_LOCK CPL_LOCK
#define ICPL_UNLOCK CPL_UNLOCK
#define FAST_ICPL_UNLOCK movl $0, _cpl_lock
-#else /* SMP */
+#else /* REAL_ICPL */
#define ICPL_LOCK
#define ICPL_UNLOCK
#define FAST_ICPL_UNLOCK
-#endif /* SMP */
+#endif /* REAL_ICPL */
/*
* AT/386
@@ -108,7 +108,7 @@ _netisrs:
_doreti:
FAKE_MCOUNT(_bintr) /* init "from" _bintr -> _doreti */
addl $4,%esp /* discard unit number */
- popl %eax /* cpl to restore */
+ popl %eax /* cpl or cml to restore */
doreti_next:
/*
* Check for pending HWIs and SWIs atomically with restoring cpl
@@ -126,6 +126,9 @@ doreti_next:
movl %edx, %eax
#endif
movl %eax,%ecx
+#ifdef INTR_SIMPLELOCK
+ orl _cpl, %ecx /* add cpl to cml */
+#endif
notl %ecx /* set bit = unmasked level */
#ifndef SMP
cli
@@ -133,11 +136,19 @@ doreti_next:
andl _ipending,%ecx /* set bit = unmasked pending INT */
jne doreti_unpend
doreti_exit:
+#ifdef INTR_SIMPLELOCK
+ movl %eax, _cml
+#else
movl %eax,_cpl
+#endif
FAST_ICPL_UNLOCK /* preserves %eax */
MPLOCKED decb _intr_nesting_level
MEXITCOUNT
#ifdef VM86
+#ifdef INTR_SIMPLELOCK
+ /* XXX INTR_SIMPLELOCK needs work */
+#error not ready for vm86
+#endif
/*
* XXX
* Sometimes when attempting to return to vm86 mode, cpl is not
@@ -158,6 +169,9 @@ doreti_stop:
#endif /* VM86 */
#ifdef SMP
+#ifdef INTR_SIMPLELOCK
+/**#error code needed here to decide which lock to release, INTR or giant*/
+#endif
/* release the kernel lock */
pushl $_mp_lock /* GIANT_LOCK */
call _MPrellock
@@ -211,6 +225,11 @@ doreti_unpend:
btrl %ecx,_ipending
#endif /* SMP */
jnc doreti_next /* some intr cleared memory copy */
+
+ /*
+ * setup call to _Xresume0 thru _Xresume23 for hwi,
+ * or swi_tty, swi_net, _softclock, swi_ast for swi.
+ */
movl ihandlers(,%ecx,4),%edx
testl %edx,%edx
je doreti_next /* "can't happen" */
@@ -220,7 +239,11 @@ doreti_unpend:
#ifdef SMP
pushl %eax /* preserve %eax */
ICPL_LOCK
+#ifdef INTR_SIMPLELOCK
+ popl _cml
+#else
popl _cpl
+#endif
FAST_ICPL_UNLOCK
#else
movl %eax,_cpl
@@ -243,9 +266,13 @@ doreti_swi:
#ifdef SMP
orl imasks(,%ecx,4), %eax
cli /* prevent INT deadlock */
- pushl %eax /* save cpl */
+ pushl %eax /* save cpl|cmpl */
ICPL_LOCK
+#ifdef INTR_SIMPLELOCK
+ popl _cml /* restore cml */
+#else
popl _cpl /* restore cpl */
+#endif
FAST_ICPL_UNLOCK
sti
#else
@@ -265,7 +292,10 @@ swi_ast_user:
movl $T_ASTFLT,(2+8+0)*4(%esp)
movb $0,_intr_nesting_level /* finish becoming a trap handler */
call _trap
- subl %eax,%eax /* recover cpl */
+ subl %eax,%eax /* recover cpl|cml */
+#ifdef INTR_SIMPLELOCK
+ movl %eax, _cpl
+#endif
movb $1,_intr_nesting_level /* for doreti_next to decrement */
jmp doreti_next
@@ -291,6 +321,9 @@ swi_ast_phantom:
orl $SWI_AST_PENDING, _ipending
/* cpl is unlocked in doreti_exit */
subl %eax,%eax
+#ifdef INTR_SIMPLELOCK
+ movl %eax, _cpl
+#endif
jmp doreti_exit /* SWI_AST is highest so we must be done */
diff --git a/sys/i386/isa/ipl_funcs.c b/sys/i386/isa/ipl_funcs.c
index 78977eb..ecc34e7 100644
--- a/sys/i386/isa/ipl_funcs.c
+++ b/sys/i386/isa/ipl_funcs.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ipl_funcs.c,v 1.7 1997/08/24 20:18:28 smp Exp smp $
+ * $Id: ipl_funcs.c,v 1.8 1997/08/28 09:51:32 smp Exp smp $
*/
#include <sys/types.h>
@@ -100,7 +100,7 @@ splx(unsigned ipl)
#include <machine/smp.h>
extern int bspEarly; /* XXX */
-#if defined(REAL_IFCPL)
+#ifdef REAL_IFCPL
#define IFCPL_LOCK() SCPL_LOCK()
#define IFCPL_UNLOCK() SCPL_UNLOCK()
diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c
index 5f241d6..c9b5da5 100644
--- a/sys/i386/isa/nmi.c
+++ b/sys/i386/isa/nmi.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.3 1997/06/22 16:04:04 peter Exp $
+ * $Id: intr_machdep.c,v 1.1 1997/08/29 18:38:35 smp Exp smp $
*/
#include "opt_auto_eoi.h"
@@ -47,6 +47,7 @@
#include <machine/segments.h>
#if defined(APIC_IO)
#include <machine/smp.h>
+#include <machine/smptests.h> /** FAST_HI */
#endif /* APIC_IO */
#include <i386/isa/isa_device.h>
#ifdef PC98
@@ -260,9 +261,17 @@ int
isa_irq_pending(dvp)
struct isa_device *dvp;
{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic.irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
+#ifdef FAST_HI
+/* XXX not quite right for >1 IO APIC yet */
+ if (dvp->id_ri_flags & RI_FAST)
+ /* read APIC IRR containing the FAST INTerrupts */
+ return ((lapic.irr3 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+ else
+#endif /* FAST_HI */
+ /* read APIC IRR containing the SLOW INTerrupts */
+ return ((lapic.irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
}
/*
@@ -396,6 +405,11 @@ update_intrname(int intr, int device_id)
int
icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
{
+#ifdef FAST_HI
+ int select; /* the select register is 8 bits */
+ int vector;
+ u_int32_t value; /* the window register is 32 bits */
+#endif /* FAST_HI */
u_long ef;
u_int mask = (maskptr ? *maskptr : 0);
@@ -413,9 +427,29 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
intr_mptr[intr] = maskptr;
intr_mask[intr] = mask | (1 << intr);
intr_unit[intr] = (int) arg;
+#ifdef FAST_HI
+ if (flags & INTR_FAST) {
+ vector = TPR_FAST_INTS + intr;
+ setidt(vector, fastintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+ /*
+ * XXX MULTIPLE_IOAPICSXXX
+ * Reprogram the vector in the IO APIC.
+ */
+ select = (intr * 2) + IOAPIC_REDTBL0;
+ value = io_apic_read(0, select) & ~IOART_INTVEC;
+ io_apic_write(0, select, value | vector);
+ }
+ else
+ setidt(TPR_SLOW_INTS + intr, slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+
+#else
setidt(ICU_OFFSET + intr,
flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif /* FAST_HI */
INTREN(1 << intr);
write_eflags(ef);
return (0);
OpenPOWER on IntegriCloud