From ed3510e3ec23ddc3fdabcc9e73813f8ef36614e8 Mon Sep 17 00:00:00 2001 From: Aaron Campbell Date: Sun, 18 Nov 2001 20:46:50 +0000 Subject: Revert niklas's broken ICU interrupt handling changes; deraadt@ ok --- sys/arch/i386/i386/autoconf.c | 7 +-- sys/arch/i386/i386/locore.s | 4 +- sys/arch/i386/include/intr.h | 115 ++++++++++++++-------------------------- sys/arch/i386/isa/icu.h | 5 +- sys/arch/i386/isa/icu.s | 20 ++++--- sys/arch/i386/isa/isa_machdep.c | 53 +++++++++--------- sys/arch/i386/isa/npx.c | 6 +-- sys/arch/i386/isa/vector.s | 14 +++-- 8 files changed, 89 insertions(+), 135 deletions(-) (limited to 'sys') diff --git a/sys/arch/i386/i386/autoconf.c b/sys/arch/i386/i386/autoconf.c index 77bc9cbafe7..02663b62c6e 100644 --- a/sys/arch/i386/i386/autoconf.c +++ b/sys/arch/i386/i386/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.37 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: autoconf.c,v 1.38 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $ */ /*- @@ -87,8 +87,9 @@ cpu_configure() if (config_rootfound("mainbus", NULL) == NULL) panic("cpu_configure: mainbus not configured"); - printf("biomask %x netmask %x ttymask %x\n", (u_short)IMASK(IPL_BIO), - (u_short)IMASK(IPL_NET), (u_short)IMASK(IPL_TTY)); + printf("biomask %x netmask %x ttymask %x\n", + (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET], + (u_short)imask[IPL_TTY]); spl0(); diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index cdb3d479c00..51e61d3f388 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.60 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: locore.s,v 1.61 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -1653,7 +1653,7 @@ ENTRY(cpu_switch) */ movl $0,_C_LABEL(curproc) - movl $IPL_NONE,_C_LABEL(cpl) # spl0() + movl $0,_C_LABEL(cpl) # spl0() call _C_LABEL(Xspllower) # process pending interrupts switch_search: diff --git a/sys/arch/i386/include/intr.h b/sys/arch/i386/include/intr.h index ca821fea28d..552de36e257 100644 --- a/sys/arch/i386/include/intr.h +++ b/sys/arch/i386/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.8 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: intr.h,v 1.9 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ /* @@ -33,54 +33,19 @@ #ifndef _I386_INTR_H_ #define _I386_INTR_H_ -/* - * Intel APICs (advanced programmable interrupt controllers) have - * bytesized priority registers where the upper nibble is the actual - * interrupt priority level (a.k.a. IPL). Interrupt vectors are - * closely tied to these levels as interrupts whose vectors' upper - * nibble is lower than or equal to the current level are blocked. - * Not all 256 possible vectors are available for interrupts in - * APIC systems, only - * - * For systems where instead the older ICU (interrupt controlling - * unit, a.k.a. PIC or 82C59) is used, the IPL is not directly useful, - * since the interrupt blocking is handled via interrupt masks instead - * of levels. However the IPL is easily used as an offset into arrays - * of masks. - */ -#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ -#define NIPL 16 /* Four bits of information gives as much. */ -#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ -/* XXX Maybe this IDTVECOFF definition should be elsewhere? */ -#define IDTVECOFF 0x20 /* The lower 32 IDT vectors are reserved. */ +/* Interrupt priority `levels'; not mutually exclusive. */ +#define IPL_NONE 0 /* nothing */ +#define IPL_BIO 1 /* block I/O */ +#define IPL_NET 2 /* network */ +#define IPL_TTY 3 /* terminal */ +#define IPL_IMP 4 /* memory allocation */ +#define IPL_AUDIO 5 /* audio */ +#define IPL_CLOCK 6 /* clock */ +#define IPL_HIGH 7 /* everything */ -/* - * This macro is only defined for 0 <= x < 14, i.e. there are fourteen - * distinct priority levels available for interrupts. - */ -#define MAKEIPL(priority) (IDTVECOFF + ((priority) << IPLSHIFT)) - -/* - * Interrupt priority levels. - * XXX We are somewhat sloppy about what we mean by IPLs, sometimes - * XXX we refer to the eight-bit value suitable for storing into APICs' - * XXX priority registers, other times about the four-bit entity found - * XXX in the former values' upper nibble, which can be used as offsets - * XXX in various arrays of our implementation. We are hoping that - * XXX the context will provide enough information to not make this - * XXX sloppy naming a real problem. - */ -#define IPL_NONE 0 /* nothing */ -#define IPL_SOFTCLOCK MAKEIPL(0) /* timeouts */ -#define IPL_SOFTNET MAKEIPL(1) /* protocol stacks */ -#define IPL_BIO MAKEIPL(2) /* block I/O */ -#define IPL_NET MAKEIPL(3) /* network */ -#define IPL_SOFTTTY MAKEIPL(4) /* delayed terminal handling */ -#define IPL_TTY MAKEIPL(5) /* terminal */ -#define IPL_IMP MAKEIPL(6) /* memory allocation */ -#define IPL_AUDIO MAKEIPL(7) /* audio */ -#define IPL_CLOCK MAKEIPL(8) /* clock */ -#define IPL_HIGH MAKEIPL(9) /* everything */ +#ifndef _LOCORE +int imask[IPL_HIGH+1]; +#endif /* Interrupt sharing types. */ #define IST_NONE 0 /* none */ @@ -90,19 +55,16 @@ /* Soft interrupt masks. */ #define SIR_CLOCK 31 +#define SIR_CLOCKMASK ((1 << SIR_CLOCK)) #define SIR_NET 30 +#define SIR_NETMASK ((1 << SIR_NET) | SIR_CLOCKMASK) #define SIR_TTY 29 +#define SIR_TTYMASK ((1 << SIR_TTY) | SIR_CLOCKMASK) +#define SIR_ALLMASK (SIR_CLOCKMASK | SIR_NETMASK | SIR_TTYMASK) #ifndef _LOCORE -volatile int cpl; /* Current interrupt priority level. */ -volatile int ipending; /* Interrupts pending. */ -volatile int astpending;/* Asynchronous software traps (softints) pending. */ -int imask[NIPL]; /* Bitmasks telling what interrupts are blocked. */ -int iunmask[NIPL]; /* Bitmasks telling what interrupts are accepted. */ - -#define IMASK(level) imask[IPL(level)] -#define IUNMASK(level) iunmask[IPL(level)] +volatile int cpl, ipending, astpending; extern void Xspllower __P((void)); @@ -112,7 +74,7 @@ static __inline void splx __P((int)); static __inline void softintr __P((int)); /* - * Raise current interrupt priority level, and return the old one. + * Add a mask to cpl, and return the old value of cpl. */ static __inline int splraise(ncpl) @@ -120,21 +82,21 @@ splraise(ncpl) { register int ocpl = cpl; - if (ncpl > ocpl) - cpl = ncpl; + cpl = ocpl | ncpl; return (ocpl); } /* - * Restore an old interrupt priority level. If any thereby unmasked + * Restore a value to cpl (unmasking interrupts). If any unmasked * interrupts are pending, call Xspllower() to process them. */ static __inline void splx(ncpl) register int ncpl; { + cpl = ncpl; - if (ipending & IUNMASK(ncpl)) + if (ipending & ~ncpl) Xspllower(); } @@ -148,18 +110,20 @@ spllower(ncpl) { register int ocpl = cpl; - splx(ncpl); + cpl = ncpl; + if (ipending & ~ncpl) + Xspllower(); return (ocpl); } /* * Hardware interrupt masks */ -#define splbio() splraise(IPL_BIO) -#define splnet() splraise(IPL_NET) -#define spltty() splraise(IPL_TTY) -#define splaudio() splraise(IPL_AUDIO) -#define splclock() splraise(IPL_CLOCK) +#define splbio() splraise(imask[IPL_BIO]) +#define splnet() splraise(imask[IPL_NET]) +#define spltty() splraise(imask[IPL_TTY]) +#define splaudio() splraise(imask[IPL_AUDIO]) +#define splclock() splraise(imask[IPL_CLOCK]) #define splstatclock() splhigh() /* @@ -168,18 +132,18 @@ spllower(ncpl) * NOTE: spllowersoftclock() is used by hardclock() to lower the priority from * clock to softclock before it calls softclock(). */ -#define spllowersoftclock() spllower(IPL_SOFTCLOCK) -#define splsoftclock() splraise(IPL_SOFTCLOCK) -#define splsoftnet() splraise(IPL_SOFTNET) -#define splsofttty() splraise(IPL_SOFTTTY) +#define spllowersoftclock() spllower(SIR_CLOCKMASK) +#define splsoftclock() splraise(SIR_CLOCKMASK) +#define splsoftnet() splraise(SIR_NETMASK) +#define splsofttty() splraise(SIR_TTYMASK) /* * Miscellaneous */ -#define splimp() splraise(IPL_IMP) -#define splvm() splraise(IPL_IMP) -#define splhigh() splraise(IPL_HIGH) -#define spl0() spllower(IPL_NONE) +#define splimp() splraise(imask[IPL_IMP]) +#define splvm() splraise(imask[IPL_IMP]) +#define splhigh() splraise(imask[IPL_HIGH]) +#define spl0() spllower(0) /* * Software interrupt registration @@ -190,6 +154,7 @@ static __inline void softintr(mask) register int mask; { + __asm __volatile("orl %0,_ipending" : : "ir" (mask)); } diff --git a/sys/arch/i386/isa/icu.h b/sys/arch/i386/isa/icu.h index 5414eeaaf4a..231a4404cbc 100644 --- a/sys/arch/i386/isa/icu.h +++ b/sys/arch/i386/isa/icu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: icu.h,v 1.5 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: icu.h,v 1.6 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: icu.h,v 1.19 1996/02/01 22:31:21 mycroft Exp $ */ /*- @@ -65,9 +65,6 @@ extern unsigned imen; /* interrupt mask enable */ /* * Interrupt Control offset into Interrupt descriptor table (IDT) - * XXX ICU_OFFSET is actually a property of our architecture not of the ICU - * XXX and therefore ought to use the architecture manifest constant IDTVECOFF - * XXX for its definition instead. */ #define ICU_OFFSET 32 /* 0-31 are processor exceptions */ #define ICU_LEN 16 /* 32-47 are ISA interrupts */ diff --git a/sys/arch/i386/isa/icu.s b/sys/arch/i386/isa/icu.s index f348a10b0b9..8be1d64520b 100644 --- a/sys/arch/i386/isa/icu.s +++ b/sys/arch/i386/isa/icu.s @@ -1,4 +1,4 @@ -/* $OpenBSD: icu.s,v 1.16 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: icu.s,v 1.17 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: icu.s,v 1.45 1996/01/07 03:59:34 mycroft Exp $ */ /*- @@ -45,7 +45,7 @@ _C_LABEL(imen): ALIGN_TEXT _C_LABEL(splhigh): - movl $IPL_HIGH,%eax + movl $-1,%eax xchgl %eax,_C_LABEL(cpl) ret @@ -72,9 +72,8 @@ IDTVEC(spllower) pushl %edi movl _C_LABEL(cpl),%ebx # save priority movl $1f,%esi # address to resume loop at -1: movl %ebx,%eax # get cpl - shrl $4,%eax # find its mask. - movl _C_LABEL(iunmask)(,%eax,4),%eax +1: movl %ebx,%eax + notl %eax andl _C_LABEL(ipending),%eax jz 2f bsfl %eax,%eax @@ -98,9 +97,8 @@ IDTVEC(doreti) popl %ebx # get previous priority movl %ebx,_C_LABEL(cpl) movl $1f,%esi # address to resume loop at -1: movl %ebx,%eax # get cpl - shrl $4,%eax # find its mask - movl _C_LABEL(iunmask)(,%eax,4),%eax +1: movl %ebx,%eax + notl %eax andl _C_LABEL(ipending),%eax jz 2f bsfl %eax,%eax # slow, but not worth optimizing @@ -134,7 +132,7 @@ IDTVEC(doreti) IDTVEC(softtty) #if NPCCOM > 0 - movl $IPL_SOFTTTY,%eax + leal SIR_TTYMASK(%ebx),%eax movl %eax,_C_LABEL(cpl) call _C_LABEL(comsoft) movl %ebx,_C_LABEL(cpl) @@ -149,7 +147,7 @@ IDTVEC(softtty) 1: IDTVEC(softnet) - movl $IPL_SOFTNET,%eax + leal SIR_NETMASK(%ebx),%eax movl %eax,_C_LABEL(cpl) xorl %edi,%edi xchgl _C_LABEL(netisr),%edi @@ -159,7 +157,7 @@ IDTVEC(softnet) #undef DONETISR IDTVEC(softclock) - movl $IPL_SOFTCLOCK,%eax + leal SIR_CLOCKMASK(%ebx),%eax movl %eax,_C_LABEL(cpl) call _C_LABEL(softclock) movl %ebx,_C_LABEL(cpl) diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c index b57340a2977..19d352fe8ad 100644 --- a/sys/arch/i386/isa/isa_machdep.c +++ b/sys/arch/i386/isa/isa_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isa_machdep.c,v 1.41 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: isa_machdep.c,v 1.42 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */ #define ISA_DMA_STATS @@ -129,7 +129,6 @@ #define _I386_BUS_DMA_PRIVATE #include -#include #include #include @@ -222,8 +221,8 @@ isa_defaultirq() /* icu vectors */ for (i = 0; i < ICU_LEN; i++) - setgate(&idt[ICU_OFFSET + i], IDTVEC(intr)[i], 0, - SDT_SYS386IGT, SEL_KPL, GICODE_SEL); + setgate(&idt[ICU_OFFSET + i], IDTVEC(intr)[i], 0, SDT_SYS386IGT, + SEL_KPL, GICODE_SEL); /* initialize 8259's */ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ @@ -261,13 +260,13 @@ isa_defaultirq() int isa_nmi() { + /* This is historic garbage; these ports are not readable */ log(LOG_CRIT, "No-maskable interrupt, may be parity error\n"); return(0); } -u_long intrstray[ICU_LEN]; - +u_long intrstray[ICU_LEN] = {0}; /* * Caught a stray interrupt, notify */ @@ -288,7 +287,6 @@ isa_strayintr(irq) int fastvec; int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN]; -int ilevel[ICU_LEN]; struct intrhand *intrhand[ICU_LEN]; /* @@ -307,45 +305,45 @@ intr_calculatemasks() for (irq = 0; irq < ICU_LEN; irq++) { register int levels = 0; for (q = intrhand[irq]; q; q = q->ih_next) - levels |= 1 << IPL(q->ih_level); + levels |= 1 << q->ih_level; intrlevel[irq] = levels; } /* Then figure out which IRQs use each level. */ - for (level = 0; level < NIPL; level++) { + for (level = 0; level < 5; level++) { register int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (intrlevel[irq] & (1 << level)) irqs |= 1 << irq; - imask[level] = irqs; + imask[level] = irqs | SIR_ALLMASK; } /* - * Initialize soft interrupt masks to block themselves. + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). */ - IMASK(IPL_SOFTCLOCK) |= 1 << SIR_CLOCK; - IMASK(IPL_SOFTNET) |= 1 << SIR_NET; - IMASK(IPL_SOFTTTY) |= 1 << SIR_TTY; + imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO]; + imask[IPL_AUDIO] |= imask[IPL_IMP]; /* * Enforce a hierarchy that gives slow devices a better chance at not * dropping data. */ - for (level = 0; level < NIPL - 1; level++) - imask[level + 1] |= imask[level]; + imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO]; + imask[IPL_NET] |= imask[IPL_BIO]; + + /* + * These are pseudo-levels. + */ + imask[IPL_NONE] = 0x00000000; + imask[IPL_HIGH] = 0xffffffff; /* And eventually calculate the complete masks. */ for (irq = 0; irq < ICU_LEN; irq++) { register int irqs = 1 << irq; - int level = IPL_NONE; - - for (q = intrhand[irq]; q; q = q->ih_next) { - irqs |= IMASK(q->ih_level); - if (q->ih_level > level) - level = q->ih_level; - } - intrmask[irq] = irqs; - ilevel[irq] = level; + for (q = intrhand[irq]; q; q = q->ih_next) + irqs |= imask[q->ih_level]; + intrmask[irq] = irqs | SIR_ALLMASK; } /* Lastly, determine which IRQs are actually in use. */ @@ -359,16 +357,13 @@ intr_calculatemasks() imen = ~irqs; SET_ICUS(); } - - /* For speed of splx, provide the inverse of the interrupt masks. */ - for (irq = 0; irq < ICU_LEN; irq++) - iunmask[irq] = ~imask[irq]; } int fakeintr(arg) void *arg; { + return 0; } diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index fe04652777f..04fb03b0533 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.c,v 1.21 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: npx.c,v 1.22 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */ #if 0 @@ -537,7 +537,7 @@ npxdna(p) } #ifdef DIAGNOSTIC - if (cpl != IPL_NONE || npx_nointr != 0) + if (cpl != 0 || npx_nointr != 0) panic("npxdna: masked"); #endif @@ -612,7 +612,7 @@ npxsave() { #ifdef DIAGNOSTIC - if (cpl != IPL_NONE || npx_nointr != 0) + if (cpl != 0 || npx_nointr != 0) panic("npxsave: masked"); #endif iprintf(("Fork")); diff --git a/sys/arch/i386/isa/vector.s b/sys/arch/i386/isa/vector.s index 61c78232624..664477530e9 100644 --- a/sys/arch/i386/isa/vector.s +++ b/sys/arch/i386/isa/vector.s @@ -1,4 +1,4 @@ -/* $OpenBSD: vector.s,v 1.12 2001/11/12 20:28:20 niklas Exp $ */ +/* $OpenBSD: vector.s,v 1.13 2001/11/18 20:46:49 aaron Exp $ */ /* $NetBSD: vector.s,v 1.32 1996/01/07 21:29:47 mycroft Exp $ */ /* @@ -218,15 +218,13 @@ _Xintr/**/irq_num/**/: ;\ MASK(irq_num, icu) /* mask it in hardware */ ;\ ack(irq_num) /* and allow other intrs */ ;\ incl MY_COUNT+V_INTR /* statistical info */ ;\ - movl _C_LABEL(ilevel) + (irq_num) * 4, %eax ;\ - movzbl _C_LABEL(cpl),%ebx ;\ - cmpl %eax,%ebx ;\ - jae _C_LABEL(Xhold/**/irq_num)/* currently masked; hold it */;\ + testb $IRQ_BIT(irq_num),_cpl + IRQ_BYTE(irq_num) ;\ + jnz _Xhold/**/irq_num /* currently masked; hold it */ ;\ _Xresume/**/irq_num/**/: ;\ - movzbl _C_LABEL(cpl),%eax /* cpl to restore on exit */ ;\ + movl _cpl,%eax /* cpl to restore on exit */ ;\ pushl %eax ;\ - movl _C_LABEL(ilevel) + (irq_num) * 4,%eax ;\ - movl %eax,_C_LABEL(cpl) /* block enough for this irq */ ;\ + orl _intrmask + (irq_num) * 4,%eax ;\ + movl %eax,_cpl /* add in this intr's mask */ ;\ sti /* safe to take intrs now */ ;\ movl _intrhand + (irq_num) * 4,%ebx /* head of chain */ ;\ testl %ebx,%ebx ;\ -- cgit v1.2.3