Deal with GCC's dead code elimination being suboptimal.
Modify splraise() to allow better optimization.
Make cpl, ipending, and astpending volatile.
Make sure interrupts are disabled before jumping to a resume point,
to prevent races.
Make FPU faults use INTRFASTEXIT, and remove INTREXIT.
Build the frame for recursive interrupts manually, and make sure to
disable interrupts to avoid races.
VS: ----------------------------------------------------------------------
-/* $NetBSD: locore.s,v 1.139.2.1 1995/10/24 16:32:42 mycroft Exp $ */
+/* $NetBSD: locore.s,v 1.142 1996/01/07 03:59:28 mycroft Exp $ */
#undef DIAGNOSTIC
#define DIAGNOSTIC
movl $GSEL(GDATA_SEL, SEL_KPL),%eax ; \
movl %ax,%ds ; \
movl %ax,%es
-#define INTREXIT \
- jmp _Xdoreti
#define INTRFASTEXIT \
popl %es ; \
popl %ds ; \
movl $0,_curproc
movl $0,_cpl # spl0()
- call _spllower # process pending interrupts
+ call _Xspllower # process pending interrupts
switch_search:
/*
incl _cnt+V_TRAP
call _npxintr
addl $4,%esp
- INTREXIT
+ INTRFASTEXIT
#else
ZTRAP(T_ARITHTRAP)
#endif
-/* $NetBSD: psl.h,v 1.22 1995/10/11 04:20:23 mycroft Exp $ */
+/* $NetBSD: psl.h,v 1.25 1996/01/07 03:59:32 mycroft Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
#ifndef LOCORE
-int cpl, ipending, astpending, imask[5];
+volatile int cpl, ipending, astpending;
+int imask[5];
+
+extern void Xspllower __P((void));
/*
* Add a mask to cpl, and return the old value of cpl.
register int ncpl;
{
register int ocpl = cpl;
- cpl |= ncpl;
+
+ cpl = ocpl | ncpl;
return (ocpl);
}
-extern void spllower __P((void));
-
/*
* Restore a value to cpl (unmasking interrupts). If any unmasked
- * interrupts are pending, call spllower() to process them.
- *
- * NOTE: We go to the trouble of returning the old value of cpl for
- * the benefit of some splsoftclock() callers. This extra work is
- * usually optimized away by the compiler.
+ * interrupts are pending, call Xspllower() to process them.
*/
-static __inline int
+static __inline void
splx(ncpl)
register int ncpl;
{
+
+ cpl = ncpl;
+ if (ipending & ~ncpl)
+ Xspllower();
+}
+
+/*
+ * Same as splx(), but we return the old value of spl, for the
+ * benefit of some splsoftclock() callers.
+ */
+static __inline int
+spllower(ncpl)
+ register int ncpl;
+{
register int ocpl = cpl;
+
cpl = ncpl;
if (ipending & ~ncpl)
- spllower();
+ Xspllower();
return (ocpl);
}
* NOTE: splsoftclock() is used by hardclock() to lower the priority from
* clock to softclock before it calls softclock().
*/
-#define splsoftclock() splx(SIR_CLOCKMASK)
+#define splsoftclock() spllower(SIR_CLOCKMASK)
#define splsoftnet() splraise(SIR_NETMASK)
#define splsofttty() splraise(SIR_TTYMASK)
* Miscellaneous
*/
#define splhigh() splraise(-1)
-#define spl0() splx(0)
+#define spl0() spllower(0)
/*
* Software interrupt registration
-/* $NetBSD: icu.h,v 1.17 1994/11/04 19:13:49 mycroft Exp $ */
+/* $NetBSD: icu.h,v 1.18 1996/01/07 02:03:20 mycroft Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
*/
extern unsigned imen; /* interrupt mask enable */
-#define INTRUNMASK(msk,s) (msk &= ~(s))
-#define INTREN(s) (INTRUNMASK(imen, s), SET_ICUS())
-#define INTRMASK(msk,s) (msk |= (s))
-#define INTRDIS(s) (INTRMASK(imen, s), SET_ICUS())
-#if 0
-#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IU_ICU2 + 1, imen >> 8))
-#else
-/*
- * XXX - IO_ICU* are defined in isa.h, not icu.h, and nothing much bothers to
- * include isa.h, while too many things include icu.h.
- */
-#define SET_ICUS() (outb(0x21, imen), outb(0xa1, imen >> 8))
-#endif
+#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8))
#endif /* !LOCORE */
-/* $NetBSD: icu.s,v 1.43 1995/10/11 04:20:31 mycroft Exp $ */
+/* $NetBSD: icu.s,v 1.45 1996/01/07 03:59:34 mycroft Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
* esi - address to resume loop at
* edi - scratch for Xsoftnet
*/
-ENTRY(spllower)
IDTVEC(spllower)
pushl %ebx
pushl %esi
bsfl %eax,%eax # slow, but not worth optimizing
btrl %eax,_ipending
jnc 1b # some intr cleared the in-memory bit
+ cli
jmp *_Xresume(,%eax,4)
2: /* Check for ASTs on exit to user mode. */
cli
-/* $NetBSD: vector.s,v 1.29 1995/05/08 18:00:20 mycroft Exp $ */
+/* $NetBSD: vector.s,v 1.31 1996/01/07 03:59:35 mycroft Exp $ */
/*
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
* XXX
* The interrupt frame is set up to look like a trap frame. This may be a
* waste. The only handler which needs a frame is the clock handler, and it
- * only needs a few bits. doreti() needs a trap frame for handling ASTs, but
+ * only needs a few bits. Xdoreti() needs a trap frame for handling ASTs, but
* it could easily convert the frame on demand.
*
* The direct costs of setting up a trap frame are two pushl's (error code and
* interrupt. On a system with level-triggered interrupts, we could terminate
* immediately when one of them returns 1; but this is a PC.
*
- * On exit, we jump to doreti, to process soft interrupts and ASTs.
+ * On exit, we jump to Xdoreti(), to process soft interrupts and ASTs.
*/
#define INTR(irq_num, icu, enable_icus) \
-IDTVEC(intr/**/irq_num) ;\
+IDTVEC(recurse/**/irq_num) ;\
+ pushfl ;\
+ pushl %cs ;\
+ pushl %esi ;\
+ cli ;\
+_Xintr/**/irq_num/**/: ;\
pushl $0 /* dummy error code */ ;\
pushl $T_ASTFLT /* trap # for doing ASTs */ ;\
INTRENTRY ;\
jnz 7b ;\
STRAY_TEST /* see if it's a stray */ ;\
5: UNMASK(irq_num, icu) /* unmask it in hardware */ ;\
- INTREXIT /* lower spl and do ASTs */ ;\
+ jmp _Xdoreti /* lower spl and do ASTs */ ;\
IDTVEC(stray/**/irq_num) ;\
pushl $irq_num ;\
call _isa_strayintr ;\
INTR(14, IO_ICU2, ENABLE_ICU1_AND_2)
INTR(15, IO_ICU2, ENABLE_ICU1_AND_2)
-/*
- * Recursive interrupts.
- *
- * This is a somewhat nasty hack to deal with resuming interrupts from splx().
- * We can't just jump to the resume point, because some handlers require an
- * interrupt frame. Instead, we just recursively interrupt.
- *
- * On entry, %esi contains a pointer to where we need to return. This is a
- * bit faster than a call/ret/jmp to continue the loop.
- *
- * XXX
- * It might be a little faster to build the interrupt frame manually and jump
- * to the resume point. The code would be larger, though.
- */
-#define RECURSE(irq_num) \
-IDTVEC(recurse/**/irq_num) ;\
- int $(ICU_OFFSET + irq_num) ;\
- jmp %esi
-
-RECURSE(0)
-RECURSE(1)
-RECURSE(2)
-RECURSE(3)
-RECURSE(4)
-RECURSE(5)
-RECURSE(6)
-RECURSE(7)
-RECURSE(8)
-RECURSE(9)
-RECURSE(10)
-RECURSE(11)
-RECURSE(12)
-RECURSE(13)
-RECURSE(14)
-RECURSE(15)
-
/*
* These tables are used by the ISA configuration code.
*/
.long _Xfast13, _Xfast14, _Xfast15
/*
- * These tables are used by doreti() and spllower().
+ * These tables are used by Xdoreti() and Xspllower().
*/
/* resume points for suspended interrupts */
IDTVEC(resume)