summaryrefslogtreecommitdiff
path: root/sys/arch/i386/isa
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2004-06-13 21:49:30 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2004-06-13 21:49:30 +0000
commit2dd254afa61a7c0cc5ae920b463d3d4266852804 (patch)
tree7adbebef3be24ba910fd83ee1ba09e1577ae21a8 /sys/arch/i386/isa
parent4d62e331dcde739b4067d712dd602c0927ce11b3 (diff)
debranch SMP, have fun
Diffstat (limited to 'sys/arch/i386/isa')
-rw-r--r--sys/arch/i386/isa/clock.c6
-rw-r--r--sys/arch/i386/isa/icu.h71
-rw-r--r--sys/arch/i386/isa/icu.s60
-rw-r--r--sys/arch/i386/isa/isa_machdep.c114
-rw-r--r--sys/arch/i386/isa/mms.c2
-rw-r--r--sys/arch/i386/isa/npx.c361
-rw-r--r--sys/arch/i386/isa/vector.s295
7 files changed, 384 insertions, 525 deletions
diff --git a/sys/arch/i386/isa/clock.c b/sys/arch/i386/isa/clock.c
index 2d932ad788f..fa18701776d 100644
--- a/sys/arch/i386/isa/clock.c
+++ b/sys/arch/i386/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.31 2004/02/27 21:07:49 grange Exp $ */
+/* $OpenBSD: clock.c,v 1.32 2004/06/13 21:49:16 niklas Exp $ */
/* $NetBSD: clock.c,v 1.39 1996/05/12 23:11:54 mycroft Exp $ */
/*-
@@ -331,7 +331,7 @@ gettick()
* wave' mode counts at 2:1).
*/
void
-delay(n)
+i8254_delay(n)
int n;
{
int limit, tick, otick;
@@ -458,7 +458,7 @@ calibrate_cyclecounter()
#endif
void
-cpu_initclocks()
+i8254_initclocks()
{
static struct timeout rtcdrain_timeout;
stathz = 128;
diff --git a/sys/arch/i386/isa/icu.h b/sys/arch/i386/isa/icu.h
deleted file mode 100644
index 9b68025526b..00000000000
--- a/sys/arch/i386/isa/icu.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $OpenBSD: icu.h,v 1.8 2003/06/02 23:27:47 millert Exp $ */
-/* $NetBSD: icu.h,v 1.19 1996/02/01 22:31:21 mycroft Exp $ */
-
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)icu.h 5.6 (Berkeley) 5/9/91
- */
-
-/*
- * AT/386 Interrupt Control constants
- * W. Jolitz 8/89
- */
-
-#ifndef _I386_ISA_ICU_H_
-#define _I386_ISA_ICU_H_
-
-#ifndef _LOCORE
-
-/*
- * Interrupt "level" mechanism variables, masks, and macros
- */
-extern unsigned imen; /* interrupt mask enable */
-
-#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8))
-
-#endif /* !_LOCORE */
-
-/*
- * Interrupt enable bits -- in order of priority
- */
-#define IRQ_SLAVE 2
-
-/*
- * 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 */
-
-#endif /* !_I386_ISA_ICU_H_ */
diff --git a/sys/arch/i386/isa/icu.s b/sys/arch/i386/isa/icu.s
index 8bd2af133ca..d3f749b4a05 100644
--- a/sys/arch/i386/isa/icu.s
+++ b/sys/arch/i386/isa/icu.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: icu.s,v 1.20 2003/11/06 21:09:34 mickey Exp $ */
+/* $OpenBSD: icu.s,v 1.21 2004/06/13 21:49:16 niklas Exp $ */
/* $NetBSD: icu.s,v 1.45 1996/01/07 03:59:34 mycroft Exp $ */
/*-
@@ -33,10 +33,11 @@
#include <net/netisr.h>
.data
- .globl _C_LABEL(imen), _C_LABEL(cpl), _C_LABEL(ipending)
- .globl _C_LABEL(astpending), _C_LABEL(netisr)
+ .globl _C_LABEL(imen),_C_LABEL(ipending),_C_LABEL(netisr)
_C_LABEL(imen):
.long 0xffff # interrupt mask enable (all off)
+_C_LABEL(ipending):
+ .long 0 # interupts pending
_C_LABEL(netisr):
.long 0 # scheduling bits for network
@@ -48,13 +49,13 @@ _C_LABEL(netisr):
ALIGN_TEXT
_C_LABEL(splhigh):
movl $IPL_HIGH,%eax
- xchgl %eax,_C_LABEL(cpl)
+ xchgl %eax,CPL
ret
ALIGN_TEXT
_C_LABEL(splx):
movl 4(%esp),%eax
- movl %eax,_C_LABEL(cpl)
+ movl %eax,CPL
testl %eax,%eax
jnz _C_LABEL(Xspllower)
ret
@@ -72,12 +73,12 @@ IDTVEC(spllower)
pushl %ebx
pushl %esi
pushl %edi
- movl _C_LABEL(cpl),%ebx # save priority
+ movl 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
- andl _C_LABEL(ipending),%eax
+ andl _C_LABEL(ipending),%eax # any non-masked bits left?
jz 2f
bsfl %eax,%eax
btrl %eax,_C_LABEL(ipending)
@@ -98,10 +99,10 @@ IDTVEC(spllower)
*/
IDTVEC(doreti)
popl %ebx # get previous priority
- movl %ebx,_C_LABEL(cpl)
+ movl %ebx,CPL
movl $1f,%esi # address to resume loop at
-1: movl %ebx,%eax # get cpl
- shrl $4,%eax # find its mask
+1: movl %ebx,%eax
+ shrl $4,%eax
movl _C_LABEL(iunmask)(,%eax,4),%eax
andl _C_LABEL(ipending),%eax
jz 2f
@@ -111,8 +112,8 @@ IDTVEC(doreti)
cli
jmp *_C_LABEL(Xresume)(,%eax,4)
2: /* Check for ASTs on exit to user mode. */
+ CHECK_ASTPENDING(%ecx)
cli
- cmpb $0,_C_LABEL(astpending)
je 3f
testb $SEL_RPL,TF_CS(%esp)
#ifdef VM86
@@ -120,10 +121,12 @@ IDTVEC(doreti)
testl $PSL_VM,TF_EFLAGS(%esp)
#endif
jz 3f
-4: movb $0,_C_LABEL(astpending)
+4: CLEAR_ASTPENDING(%ecx)
sti
+ movl $T_ASTFLT,TF_TRAPNO(%esp) /* XXX undo later. */
/* Pushed T_ASTFLT into tf_trapno on entry. */
call _C_LABEL(trap)
+ cli
jmp 2b
3: INTRFASTEXIT
@@ -137,9 +140,16 @@ IDTVEC(doreti)
IDTVEC(softtty)
#if NPCCOM > 0
movl $IPL_SOFTTTY,%eax
- movl %eax,_C_LABEL(cpl)
+ movl %eax,CPL
+ sti
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintlock)
+#endif
call _C_LABEL(comsoft)
- movl %ebx,_C_LABEL(cpl)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintunlock)
+#endif
+ movl %ebx,CPL
#endif
jmp *%esi
@@ -152,18 +162,32 @@ IDTVEC(softtty)
IDTVEC(softnet)
movl $IPL_SOFTNET,%eax
- movl %eax,_C_LABEL(cpl)
+ movl %eax,CPL
+ sti
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintlock)
+#endif
xorl %edi,%edi
xchgl _C_LABEL(netisr),%edi
#include <net/netisr_dispatch.h>
- movl %ebx,_C_LABEL(cpl)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintunlock)
+#endif
+ movl %ebx,CPL
jmp *%esi
#undef DONETISR
IDTVEC(softclock)
movl $IPL_SOFTCLOCK,%eax
- movl %eax,_C_LABEL(cpl)
+ movl %eax,CPL
+ sti
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintlock)
+#endif
call _C_LABEL(softclock)
- movl %ebx,_C_LABEL(cpl)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(i386_softintunlock)
+#endif
+ movl %ebx,CPL
jmp *%esi
diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c
index 0a8b580c6f4..0df077cdb19 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.48 2003/06/02 23:27:47 millert Exp $ */
+/* $OpenBSD: isa_machdep.c,v 1.49 2004/06/13 21:49:16 niklas Exp $ */
/* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */
#define ISA_DMA_STATS
@@ -122,18 +122,25 @@
#include <uvm/uvm_extern.h>
+#include "ioapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+#endif
+
#define _I386_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/pio.h>
#include <machine/cpufunc.h>
+#include <machine/i8259.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
#include <i386/isa/isa_machdep.h>
-#include <i386/isa/icu.h>
#include "isadma.h"
@@ -250,6 +257,16 @@ isa_defaultirq()
outb(IO_ICU2, 0x0a); /* Read IRR by default. */
}
+void
+isa_nodefaultirq()
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < ICU_LEN; i++)
+ unsetgate(&idt[ICU_OFFSET + i]);
+}
+
/*
* Handle a NMI, possibly a machine check.
* return true to panic system, false to ignore.
@@ -286,6 +303,9 @@ int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
int iminlevel[ICU_LEN], imaxlevel[ICU_LEN];
struct intrhand *intrhand[ICU_LEN];
+int imask[NIPL]; /* Bitmask telling what interrupts are blocked. */
+int iunmask[NIPL]; /* Bitmask telling what interrupts are accepted. */
+
/*
* Recalculate the interrupt masks from scratch.
* We could code special registry and deregistry versions of this function that
@@ -295,24 +315,27 @@ struct intrhand *intrhand[ICU_LEN];
void
intr_calculatemasks()
{
- int irq, level;
+ int irq, level, unusedirqs;
struct intrhand *q;
/* First, figure out which levels each IRQ uses. */
+ unusedirqs = 0xffff;
for (irq = 0; irq < ICU_LEN; irq++) {
- register int levels = 0;
+ int levels = 0;
for (q = intrhand[irq]; q; q = q->ih_next)
levels |= 1 << IPL(q->ih_level);
intrlevel[irq] = levels;
+ if (levels)
+ unusedirqs &= ~(1 << irq);
}
/* Then figure out which IRQs use each level. */
for (level = 0; level < NIPL; level++) {
- register int irqs = 0;
+ int irqs = 0;
for (irq = 0; irq < ICU_LEN; irq++)
if (intrlevel[irq] & (1 << level))
irqs |= 1 << irq;
- imask[level] = irqs;
+ imask[level] = irqs | unusedirqs;
}
/*
@@ -331,25 +354,40 @@ intr_calculatemasks()
/* And eventually calculate the complete masks. */
for (irq = 0; irq < ICU_LEN; irq++) {
- register int irqs = 1 << irq;
+ int irqs = 1 << irq;
int minlevel = IPL_NONE;
int maxlevel = IPL_NONE;
- for (q = intrhand[irq]; q; q = q->ih_next) {
- irqs |= IMASK(q->ih_level);
- if (minlevel == IPL_NONE || q->ih_level < minlevel)
- minlevel = q->ih_level;
- if (q->ih_level > maxlevel)
- maxlevel = q->ih_level;
+ if (intrhand[irq] == NULL) {
+ maxlevel = IPL_HIGH;
+ irqs = IMASK(IPL_HIGH);
+ } else {
+ for (q = intrhand[irq]; q; q = q->ih_next) {
+ irqs |= IMASK(q->ih_level);
+ if (minlevel == IPL_NONE ||
+ q->ih_level < minlevel)
+ minlevel = q->ih_level;
+ if (q->ih_level > maxlevel)
+ maxlevel = q->ih_level;
+ }
}
+ if (irqs != IMASK(maxlevel))
+ panic("irq %d level %x mask mismatch: %x vs %x", irq,
+ maxlevel, irqs, IMASK(maxlevel));
+
intrmask[irq] = irqs;
iminlevel[irq] = minlevel;
imaxlevel[irq] = maxlevel;
+
+#if 0
+ printf("irq %d: level %x, mask 0x%x (%x)\n", irq,
+ imaxlevel[irq], intrmask[irq], IMASK(imaxlevel[irq]));
+#endif
}
/* Lastly, determine which IRQs are actually in use. */
{
- register int irqs = 0;
+ int irqs = 0;
for (irq = 0; irq < ICU_LEN; irq++)
if (intrhand[irq])
irqs |= 1 << irq;
@@ -496,17 +534,48 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
struct intrhand **p, *q, *ih;
static struct intrhand fakehand = {fakeintr};
+#if NIOAPIC > 0
+ struct mp_intr_map *mip;
+
+ if (mp_busses != NULL) {
+ int mpspec_pin = irq;
+ int bus = mp_isa_bus;
+ int airq;
+
+ for (mip = mp_busses[bus].mb_intrs; mip != NULL;
+ mip = mip->next) {
+ if (mip->bus_pin == mpspec_pin) {
+ airq = mip->ioapic_ih | irq;
+ break;
+ }
+ }
+ if (mip == NULL && mp_eisa_bus != -1) {
+ for (mip = mp_busses[mp_eisa_bus].mb_intrs;
+ mip != NULL; mip=mip->next) {
+ if (mip->bus_pin == mpspec_pin) {
+ airq = mip->ioapic_ih | irq;
+ break;
+ }
+ }
+ }
+ if (mip == NULL)
+ printf("isa_intr_establish: no MP mapping found\n");
+ else
+ return (apic_intr_establish(airq, type, level, ih_fun,
+ ih_arg, ih_what));
+ }
+#endif
/* no point in sleeping unless someone can free memory. */
ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
if (ih == NULL) {
printf("%s: isa_intr_establish: can't malloc handler info\n",
ih_what);
- return NULL;
+ return (NULL);
}
if (!LEGAL_IRQ(irq) || type == IST_NONE) {
- printf("%s: intr_establish: bogus irq or type\n", ih_what);
- return NULL;
+ printf("%s: isa_intr_establish: bogus irq or type\n", ih_what);
+ return (NULL);
}
switch (intrtype[irq]) {
case IST_NONE:
@@ -521,7 +590,7 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
/*printf("%s: intr_establish: can't share %s with %s, irq %d\n",
ih_what, isa_intr_typename(intrtype[irq]),
isa_intr_typename(type), irq);*/
- return NULL;
+ return (NULL);
}
break;
}
@@ -571,8 +640,15 @@ isa_intr_disestablish(ic, arg)
int irq = ih->ih_irq;
struct intrhand **p, *q;
+#if NIOAPIC > 0
+ if (irq & APIC_INT_VIA_APIC) {
+ apic_intr_disestablish(arg);
+ return;
+ }
+#endif
+
if (!LEGAL_IRQ(irq))
- panic("intr_disestablish: bogus irq");
+ panic("intr_disestablish: bogus irq %d", irq);
/*
* Remove the handler from the chain.
diff --git a/sys/arch/i386/isa/mms.c b/sys/arch/i386/isa/mms.c
index 1b84aecf965..137c18384a5 100644
--- a/sys/arch/i386/isa/mms.c
+++ b/sys/arch/i386/isa/mms.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mms.c,v 1.16 2002/03/14 01:26:33 millert Exp $ */
+/* $OpenBSD: mms.c,v 1.17 2004/06/13 21:49:16 niklas Exp $ */
/* $NetBSD: mms.c,v 1.35 2000/01/08 02:57:25 takemura Exp $ */
/*-
diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c
index b56a17f3875..4111ba0ab90 100644
--- a/sys/arch/i386/isa/npx.c
+++ b/sys/arch/i386/isa/npx.c
@@ -1,10 +1,10 @@
-/* $OpenBSD: npx.c,v 1.31 2004/02/01 19:05:21 deraadt Exp $ */
+/* $OpenBSD: npx.c,v 1.32 2004/06/13 21:49:16 niklas Exp $ */
/* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */
#if 0
-#define iprintf(x) printf x
+#define IPRINTF(x) printf x
#else
-#define iprintf(x)
+#define IPRINTF(x)
#endif
/*-
@@ -54,21 +54,16 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/npx.h>
#include <machine/pio.h>
#include <machine/cpufunc.h>
#include <machine/pcb.h>
#include <machine/trap.h>
#include <machine/specialreg.h>
+#include <machine/i8259.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
-#include <i386/isa/icu.h>
-
-#if 0
-#define IPRINTF(x) printf x
-#else
-#define IPRINTF(x)
-#endif
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
@@ -104,7 +99,6 @@
int npxintr(void *);
static int npxprobe1(struct isa_attach_args *);
-static void npxsave1(void);
struct npx_softc {
struct device sc_dev;
@@ -129,10 +123,7 @@ enum npx_type {
NPX_BROKEN,
};
-struct proc *npxproc;
-
static enum npx_type npx_type;
-static int npx_nointr;
static volatile u_int npx_intrs_while_probing;
static volatile u_int npx_traps_while_probing;
@@ -160,15 +151,15 @@ fpu_save(union savefpu *addr)
}
static int
-npxdna_notset(struct proc *p)
+npxdna_notset(struct cpu_info *ci)
{
panic("npxdna vector not initialized");
}
-int (*npxdna_func)(struct proc *) = npxdna_notset;
-int npxdna_s87(struct proc *);
+int (*npxdna_func)(struct cpu_info *) = npxdna_notset;
+int npxdna_s87(struct cpu_info *);
#ifdef I686_CPU
-int npxdna_xmm(struct proc *);
+int npxdna_xmm(struct cpu_info *);
#endif /* I686_CPU */
void npxexit(void);
@@ -350,6 +341,19 @@ asm (".text\n\t"
"popl %eax\n\t"
"ret\n\t");
+void
+npxinit(struct cpu_info *ci)
+{
+ lcr0(rcr0() & ~(CR0_EM|CR0_TS));
+ fninit();
+ if (npx586bug1(4195835, 3145727) != 0) {
+ i386_fpu_fdivbug = 1;
+ printf("%s: WARNING: Pentium FDIV bug detected!\n",
+ ci->ci_dev.dv_xname);
+ }
+ lcr0(rcr0() | (CR0_TS));
+}
+
/*
* Attach routine - announce which it is, and wire into system
*/
@@ -379,13 +383,7 @@ npxattach(parent, self, aux)
return;
}
- lcr0(rcr0() & ~(CR0_EM|CR0_TS));
- fninit();
- if (npx586bug1(4195835, 3145727) != 0) {
- i386_fpu_fdivbug = 1;
- printf("WARNING: Pentium FDIV bug detected!\n");
- }
- lcr0(rcr0() | (CR0_TS));
+ npxinit(&cpu_info_primary);
i386_fpu_present = 1;
#ifdef I686_CPU
@@ -415,16 +413,17 @@ int
npxintr(arg)
void *arg;
{
- register struct proc *p = npxproc;
+ struct cpu_info *ci = curcpu();
+ struct proc *p = ci->ci_fpcurproc;
union savefpu *addr;
struct intrframe *frame = arg;
int code;
union sigval sv;
uvmexp.traps++;
- iprintf(("Intr"));
+ IPRINTF(("%s: fp intr\n", ci->ci_dev.dv_xname));
- if (p == 0 || npx_type == NPX_NONE) {
+ if (p == NULL || npx_type == NPX_NONE) {
/* XXX no %p in stand/printf.c. Cast to quiet gcc -Wall. */
printf("npxintr: p = %lx, curproc = %lx, npx_type = %d\n",
(u_long) p, (u_long) curproc, npx_type);
@@ -438,11 +437,21 @@ npxintr(arg)
* If we're saving, ignore the interrupt. The FPU will happily
* generate another one when we restore the state later.
*/
- if (npx_nointr != 0)
+ if (ci->ci_fpsaving)
return (1);
+
+#ifdef DIAGNOSTIC
/*
- * Find the address of npxproc's savefpu. This is not necessarily
- * the one in curpcb.
+ * At this point, fpcurproc should be curproc. If it wasn't, the TS
+ * bit should be set, and we should have gotten a DNA exception.
+ */
+ if (p != curproc)
+ panic("npxintr: wrong process");
+#endif
+
+ /*
+ * Find the address of fpcurproc's saved FPU state. (Given the
+ * invariant above, this is always the one in curpcb.)
*/
addr = &p->p_addr->u_pcb.pcb_savefpu;
/*
@@ -504,7 +513,7 @@ npxintr(arg)
if (addr->sv_87.sv_ex_sw & EN_SW_IE)
code = FPE_FLTINV;
#ifdef notyet
- else if (addr->sv_ex_sw & EN_SW_DE)
+ else if (addr->sv_87.sv_ex_sw & EN_SW_DE)
code = FPE_FLTDEN;
#endif
else if (addr->sv_87.sv_ex_sw & EN_SW_ZE)
@@ -541,115 +550,147 @@ npxintr(arg)
}
/*
- * Wrapper for fnsave instruction to handle h/w bugs. If there is an error
- * pending, then fnsave generates a bogus IRQ13 on some systems. Force any
- * IRQ13 to be handled immediately, and then ignore it.
- *
- * This routine is always called at spl0. If it might called with the NPX
- * interrupt masked, it would be necessary to forcibly unmask the NPX interrupt
- * so that it could succeed.
- */
-static __inline void
-npxsave1(void)
-{
- register struct pcb *pcb;
-
- npx_nointr = 1;
- pcb = &npxproc->p_addr->u_pcb;
- fpu_save(&pcb->pcb_savefpu);
- pcb->pcb_cr0 |= CR0_TS;
- fwait();
- npx_nointr = 0;
-}
-
-/*
* Implement device not available (DNA) exception
*
- * If the we were the last process to use the FPU, we can simply return.
+ * If we were the last process to use the FPU, we can simply return.
* Otherwise, we save the previous state, if necessary, and restore our last
* saved state.
*/
+
+/*
+ * XXX It is unclear if the code below is correct in the multiprocessor
+ * XXX case. Check the NetBSD sources once again to be sure.
+ */
#ifdef I686_CPU
int
-npxdna_xmm(struct proc *p)
+npxdna_xmm(struct cpu_info *ci)
{
+ struct proc *p;
+ int s;
-#ifdef DIAGNOSTIC
- if (cpl != 0 || npx_nointr != 0)
- panic("npxdna: masked");
+ if (ci->ci_fpsaving) {
+ printf("recursive npx trap; cr0=%x\n", rcr0());
+ return (0);
+ }
+
+ s = splipi(); /* lock out IPI's while we clean house.. */
+
+#ifdef MULTIPROCESSOR
+ p = ci->ci_curproc;
+#else
+ p = curproc;
#endif
- p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
- clts();
+ IPRINTF(("%s: dna for %lx%s\n", ci->ci_dev.dv_xname, (u_long)p,
+ (p->p_md.md_flags & MDP_USEDFPU) ? " (used fpu)" : ""));
/*
+ * XXX should have a fast-path here when no save/restore is necessary
+ */
+ /*
* Initialize the FPU state to clear any exceptions. If someone else
* was using the FPU, save their state (which does an implicit
* initialization).
*/
- npx_nointr = 1;
- if (npxproc != 0 && npxproc != p) {
- IPRINTF(("Save"));
- npxsave1();
+ if (ci->ci_fpcurproc != NULL) {
+ IPRINTF(("%s: fp save %lx\n", ci->ci_dev.dv_xname,
+ (u_long)ci->ci_fpcurproc));
+ npxsave_cpu(ci, 1);
} else {
- IPRINTF(("Init"));
- fninit();
- fwait();
+ clts();
+ IPRINTF(("%s: fp init\n", ci->ci_dev.dv_xname));
+ fninit();
+ fwait();
+ stts();
}
- npx_nointr = 0;
- npxproc = p;
+ splx(s);
+
+ IPRINTF(("%s: done saving\n", ci->ci_dev.dv_xname));
+ KDASSERT(ci->ci_fpcurproc == NULL);
+#ifndef MULTIPROCESSOR
+ KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
+#else
+ if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+ npxsave_proc(p, 1);
+#endif
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+ clts();
+ s = splipi();
+ ci->ci_fpcurproc = p;
+ p->p_addr->u_pcb.pcb_fpcpu = ci;
+ splx(s);
if ((p->p_md.md_flags & MDP_USEDFPU) == 0) {
fldcw(&p->p_addr->u_pcb.pcb_savefpu.sv_xmm.sv_env.en_cw);
p->p_md.md_flags |= MDP_USEDFPU;
- } else
+ } else {
fxrstor(&p->p_addr->u_pcb.pcb_savefpu.sv_xmm);
+ }
return (1);
}
#endif /* I686_CPU */
int
-npxdna_s87(struct proc *p)
+npxdna_s87(struct cpu_info *ci)
{
- static u_short control = __INITIAL_NPXCW__;
+ struct proc *p;
+ int s;
+
+ KDASSERT(i386_use_fxsave == 0);
- if (npx_type == NPX_NONE) {
- iprintf(("Emul"));
+ if (ci->ci_fpsaving) {
+ printf("recursive npx trap; cr0=%x\n", rcr0());
return (0);
}
-#ifdef DIAGNOSTIC
- if (cpl != IPL_NONE || npx_nointr != 0)
- panic("npxdna: masked");
+ s = splipi(); /* lock out IPI's while we clean house.. */
+#ifdef MULTIPROCESSOR
+ p = ci->ci_curproc;
+#else
+ p = curproc;
#endif
+ IPRINTF(("%s: dna for %lx%s\n", ci->ci_dev.dv_xname, (u_long)p,
+ (p->p_md.md_flags & MDP_USEDFPU) ? " (used fpu)" : ""));
+
+ /*
+ * If someone else was using our FPU, save their state (which does an
+ * implicit initialization); otherwise, initialize the FPU state to
+ * clear any exceptions.
+ */
+ if (ci->ci_fpcurproc != NULL) {
+ IPRINTF(("%s: fp save %lx\n", ci->ci_dev.dv_xname,
+ (u_long)ci->ci_fpcurproc));
+ npxsave_cpu(ci, 1);
+ } else {
+ clts();
+ IPRINTF(("%s: fp init\n", ci->ci_dev.dv_xname));
+ fninit();
+ fwait();
+ stts();
+ }
+ splx(s);
+
+ IPRINTF(("%s: done saving\n", ci->ci_dev.dv_xname));
+ KDASSERT(ci->ci_fpcurproc == NULL);
+#ifndef MULTIPROCESSOR
+ KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
+#else
+ if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+ npxsave_proc(p, 1);
+#endif
p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
clts();
+ s = splipi();
+ ci->ci_fpcurproc = p;
+ p->p_addr->u_pcb.pcb_fpcpu = ci;
+ splx(s);
if ((p->p_md.md_flags & MDP_USEDFPU) == 0) {
+ fldcw(&p->p_addr->u_pcb.pcb_savefpu.sv_87.sv_env.en_cw);
p->p_md.md_flags |= MDP_USEDFPU;
- iprintf(("Init"));
- if (npxproc != 0 && npxproc != p)
- npxsave1();
- else {
- npx_nointr = 1;
- fninit();
- fwait();
- npx_nointr = 0;
- }
- npxproc = p;
- fldcw(&control);
} else {
- if (npxproc != 0) {
-#ifdef DIAGNOSTIC
- if (npxproc == p)
- panic("npxdna: same process");
-#endif
- iprintf(("Save"));
- npxsave1();
- }
- npxproc = p;
/*
* The following frstor may cause an IRQ13 when the state being
* restored has a pending error. The error will appear to have
@@ -670,37 +711,121 @@ npxdna_s87(struct proc *p)
}
/*
- * Drop the current FPU state on the floor.
+ * The FNSAVE instruction clears the FPU state. Rather than reloading the FPU
+ * immediately, we clear fpcurproc and turn on CR0_TS to force a DNA and a
+ * reload of the FPU state the next time we try to use it. This routine
+ * is only called when forking, core dumping, or debugging, or swapping,
+ * so the lazy reload at worst forces us to trap once per fork(), and at best
+ * saves us a reload once per fork().
*/
void
-npxdrop()
+npxsave_cpu(struct cpu_info *ci, int save)
{
+ struct proc *p;
+ int s;
+
+ KDASSERT(ci == curcpu());
+
+ p = ci->ci_fpcurproc;
+ if (p == NULL)
+ return;
+
+ IPRINTF(("%s: fp cpu %s %lx\n", ci->ci_dev.dv_xname,
+ save ? "save" : "flush", (u_long)p));
+
+ if (save) {
+#ifdef DIAGNOSTIC
+ if (ci->ci_fpsaving != 0)
+ panic("npxsave_cpu: recursive save!");
+#endif
+ /*
+ * Set ci->ci_fpsaving, so that any pending exception will be
+ * thrown away. (It will be caught again if/when the FPU
+ * state is restored.)
+ *
+ * XXX on i386 and earlier, this routine should always be
+ * called at spl0; if it might called with the NPX interrupt
+ * masked, it would be necessary to forcibly unmask the NPX
+ * interrupt so that it could succeed.
+ * XXX this is irrelevant on 486 and above (systems
+ * which report FP failures via traps rather than irq13).
+ * XXX punting for now..
+ */
+ clts();
+ ci->ci_fpsaving = 1;
+ fpu_save(&p->p_addr->u_pcb.pcb_savefpu);
+ ci->ci_fpsaving = 0;
+ /* It is unclear if this is needed. */
+ fwait();
+ }
+ /*
+ * We set the TS bit in the saved CR0 for this process, so that it
+ * will get a DNA exception on any FPU instruction and force a reload.
+ */
stts();
- npxproc->p_addr->u_pcb.pcb_cr0 |= CR0_TS;
- npxproc = 0;
+ p->p_addr->u_pcb.pcb_cr0 |= CR0_TS;
+
+ s = splipi();
+ p->p_addr->u_pcb.pcb_fpcpu = NULL;
+ ci->ci_fpcurproc = NULL;
+ splx(s);
}
/*
- * Save npxproc's FPU state.
- *
- * The FNSAVE instruction clears the FPU state. Rather than reloading the FPU
- * immediately, we clear npxproc and turn on CR0_TS to force a DNA and a reload
- * of the FPU state the next time we try to use it. This routine is only
- * called when forking or core dump, so this algorithm at worst forces us to
- * trap once per fork(), and at best saves us a reload once per fork().
+ * Save p's FPU state, which may be on this processor or another processor.
*/
-void
-npxsave()
+ void
+npxsave_proc(struct proc *p, int save)
{
+ struct cpu_info *ci = curcpu();
+ struct cpu_info *oci;
+
+ KDASSERT(p->p_addr != NULL);
+ KDASSERT(p->p_flag & P_INMEM);
+ oci = p->p_addr->u_pcb.pcb_fpcpu;
+ if (oci == NULL)
+ return;
+
+ IPRINTF(("%s: fp proc %s %lx\n", ci->ci_dev.dv_xname,
+ save ? "save" : "flush", (u_long)p));
+
+#if defined(MULTIPROCESSOR)
+ if (oci == ci) {
+ int s = splipi();
+ npxsave_cpu(ci, save);
+ splx(s);
+ } else {
#ifdef DIAGNOSTIC
- if (cpl != IPL_NONE || npx_nointr != 0)
- panic("npxsave: masked");
+ int spincount;
+#endif
+
+ IPRINTF(("%s: fp ipi to %s %s %lx\n", ci->ci_dev.dv_xname,
+ oci->ci_dev.dv_xname, save ? "save" : "flush", (u_long)p));
+
+ i386_send_ipi(oci,
+ save ? I386_IPI_SYNCH_FPU : I386_IPI_FLUSH_FPU);
+
+#ifdef DIAGNOSTIC
+ spincount = 0;
+#endif
+ while (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+#ifdef DIAGNOSTIC
+ {
+ spincount++;
+ if (spincount > 100000000) {
+ panic("fp_save ipi didn't");
+ }
+ }
+#else
+ __splbarrier(); /* XXX replace by generic barrier */
+ ;
+#endif
+ }
+#else
+ KASSERT(ci->ci_fpcurproc == p);
+ npxsave_cpu(ci, save);
#endif
- iprintf(("Fork"));
- clts();
- npxsave1();
- stts();
- npxproc = 0;
}
+
diff --git a/sys/arch/i386/isa/vector.s b/sys/arch/i386/isa/vector.s
deleted file mode 100644
index 93a7bab51da..00000000000
--- a/sys/arch/i386/isa/vector.s
+++ /dev/null
@@ -1,295 +0,0 @@
-/* $OpenBSD: vector.s,v 1.16 2003/04/17 03:42:14 drahn Exp $ */
-/* $NetBSD: vector.s,v 1.32 1996/01/07 21:29:47 mycroft Exp $ */
-
-/*
- * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Charles M. Hannum.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <i386/isa/icu.h>
-#include <dev/isa/isareg.h>
-
-#define ICU_HARDWARE_MASK
-
-#define MY_COUNT _C_LABEL(uvmexp)
-
-/*
- * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is
- * defined, we try to take advantage of the ICU's `special mask mode' by only
- * EOIing the interrupts on return. This avoids the requirement of masking and
- * unmasking. We can't do this without special mask mode, because the ICU
- * would also hold interrupts that it thinks are of lower priority.
- *
- * Many machines do not support special mask mode, so by default we don't try
- * to use it.
- */
-
-#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
-#define IRQ_BYTE(irq_num) ((irq_num) / 8)
-
-#ifdef ICU_SPECIAL_MASK_MODE
-
-#define ACK1(irq_num)
-#define ACK2(irq_num) \
- movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\
- outb %al,$IO_ICU1
-#define MASK(irq_num, icu)
-#define UNMASK(irq_num, icu) \
- movb $(0x60|(irq_num%8)),%al /* specific EOI */ ;\
- outb %al,$icu
-
-#else /* ICU_SPECIAL_MASK_MODE */
-
-#ifndef AUTO_EOI_1
-#define ACK1(irq_num) \
- movb $(0x60|(irq_num%8)),%al /* specific EOI */ ;\
- outb %al,$IO_ICU1
-#else
-#define ACK1(irq_num)
-#endif
-
-#ifndef AUTO_EOI_2
-#define ACK2(irq_num) \
- movb $(0x60|(irq_num%8)),%al /* specific EOI */ ;\
- outb %al,$IO_ICU2 /* do the second ICU first */ ;\
- movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\
- outb %al,$IO_ICU1
-#else
-#define ACK2(irq_num)
-#endif
-
-#ifdef ICU_HARDWARE_MASK
-
-#define MASK(irq_num, icu) \
- movb _C_LABEL(imen) + IRQ_BYTE(irq_num),%al ;\
- orb $IRQ_BIT(irq_num),%al ;\
- movb %al,_C_LABEL(imen) + IRQ_BYTE(irq_num) ;\
- FASTER_NOP ;\
- outb %al,$(icu+1)
-#define UNMASK(irq_num, icu) \
- cli ;\
- movb _C_LABEL(imen) + IRQ_BYTE(irq_num),%al ;\
- andb $~IRQ_BIT(irq_num),%al ;\
- movb %al,_C_LABEL(imen) + IRQ_BYTE(irq_num) ;\
- FASTER_NOP ;\
- outb %al,$(icu+1) ;\
- sti
-
-#else /* ICU_HARDWARE_MASK */
-
-#define MASK(irq_num, icu)
-#define UNMASK(irq_num, icu)
-
-#endif /* ICU_HARDWARE_MASK */
-
-#endif /* ICU_SPECIAL_MASK_MODE */
-
-/*
- * Macros for interrupt entry, call to handler, and exit.
- *
- * 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. 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
- * trap number), an addl to get rid of these, and pushing and popping the
- * callee-saved registers %esi, %edi, %ebx, and %ebp twice.
- *
- * If the interrupt frame is made more flexible, INTR can push %eax first and
- * decide the ipending case with less overhead, e.g., by avoiding loading the
- * segment registers.
- *
- * XXX
- * Should we do a cld on every system entry to avoid the requirement for
- * scattered cld's?
- */
-
- .globl _C_LABEL(isa_strayintr)
-
-/*
- * Normal vectors.
- *
- * We cdr down the intrhand chain, calling each handler with its appropriate
- * argument (0 meaning a pointer to the frame, for clock interrupts).
- *
- * The handler returns one of three values:
- * 0 - This interrupt wasn't for me.
- * 1 - This interrupt was for me.
- * -1 - This interrupt might have been for me, but I don't know.
- * If there are no handlers, or they all return 0, we flags it as a `stray'
- * 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 Xdoreti(), to process soft interrupts and ASTs.
- */
-#define INTR(irq_num, icu, ack) \
-IDTVEC(recurse/**/irq_num) ;\
- pushfl ;\
- pushl %cs ;\
- pushl %esi ;\
- cli ;\
-_C_LABEL(Xintr)/**/irq_num/**/: ;\
- pushl $0 /* dummy error code */ ;\
- pushl $T_ASTFLT /* trap # for doing ASTs */ ;\
- INTRENTRY ;\
- MAKE_FRAME ;\
- 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(iminlevel) + (irq_num) * 4, %eax ;\
- movzbl _C_LABEL(cpl),%ebx ;\
- cmpl %eax,%ebx ;\
- jae _C_LABEL(Xhold/**/irq_num)/* currently masked; hold it */;\
-_C_LABEL(Xresume)/**/irq_num/**/: ;\
- movzbl _C_LABEL(cpl),%eax /* cpl to restore on exit */ ;\
- pushl %eax ;\
- movl _C_LABEL(imaxlevel) + (irq_num) * 4,%eax ;\
- movl %eax,_C_LABEL(cpl) /* block enough for this irq */ ;\
- sti /* safe to take intrs now */ ;\
- movl _C_LABEL(intrhand) + (irq_num) * 4,%ebx /* head of chain */ ;\
- testl %ebx,%ebx ;\
- jz _C_LABEL(Xstray)/**/irq_num /* no handlears; we're stray */ ;\
- STRAY_INITIALIZE /* nobody claimed it yet */ ;\
-7: movl IH_ARG(%ebx),%eax /* get handler arg */ ;\
- testl %eax,%eax ;\
- jnz 4f ;\
- movl %esp,%eax /* 0 means frame pointer */ ;\
-4: pushl %eax ;\
- call *IH_FUN(%ebx) /* call it */ ;\
- addl $4,%esp /* toss the arg */ ;\
- STRAY_INTEGRATE /* maybe he claimed it */ ;\
- orl %eax,%eax /* should it be counted? */ ;\
- jz 5f /* no, skip it */ ;\
- incl IH_COUNT(%ebx) /* count the intrs */ ;\
-5: movl IH_NEXT(%ebx),%ebx /* next handler in chain */ ;\
- testl %ebx,%ebx ;\
- jnz 7b ;\
- STRAY_TEST /* see if it's a stray */ ;\
-6: UNMASK(irq_num, icu) /* unmask it in hardware */ ;\
- jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
-IDTVEC(stray/**/irq_num) ;\
- pushl $irq_num ;\
- call _C_LABEL(isa_strayintr) ;\
- addl $4,%esp ;\
- jmp 6b ;\
-IDTVEC(hold/**/irq_num) ;\
- orb $IRQ_BIT(irq_num),_C_LABEL(ipending) + IRQ_BYTE(irq_num) ;\
- INTRFASTEXIT
-
-#if defined(DEBUG) && defined(notdef)
-#define STRAY_INITIALIZE \
- xorl %esi,%esi
-#define STRAY_INTEGRATE \
- orl %eax,%esi
-#define STRAY_TEST \
- testl %esi,%esi ;\
- jz _C_LABEL(Xstray)/**/irq_num
-#else /* !DEBUG */
-#define STRAY_INITIALIZE
-#define STRAY_INTEGRATE
-#define STRAY_TEST
-#endif /* DEBUG */
-
-#ifdef DDB
-#define MAKE_FRAME \
- leal -8(%esp),%ebp
-#else /* !DDB */
-#define MAKE_FRAME
-#endif /* DDB */
-
-INTR(0, IO_ICU1, ACK1)
-INTR(1, IO_ICU1, ACK1)
-INTR(2, IO_ICU1, ACK1)
-INTR(3, IO_ICU1, ACK1)
-INTR(4, IO_ICU1, ACK1)
-INTR(5, IO_ICU1, ACK1)
-INTR(6, IO_ICU1, ACK1)
-INTR(7, IO_ICU1, ACK1)
-INTR(8, IO_ICU2, ACK2)
-INTR(9, IO_ICU2, ACK2)
-INTR(10, IO_ICU2, ACK2)
-INTR(11, IO_ICU2, ACK2)
-INTR(12, IO_ICU2, ACK2)
-INTR(13, IO_ICU2, ACK2)
-INTR(14, IO_ICU2, ACK2)
-INTR(15, IO_ICU2, ACK2)
-
-/*
- * These tables are used by the ISA configuration code.
- */
-/* interrupt service routine entry points */
-IDTVEC(intr)
- .long _C_LABEL(Xintr0), _C_LABEL(Xintr1), _C_LABEL(Xintr2)
- .long _C_LABEL(Xintr3), _C_LABEL(Xintr4), _C_LABEL(Xintr5)
- .long _C_LABEL(Xintr6), _C_LABEL(Xintr7), _C_LABEL(Xintr8)
- .long _C_LABEL(Xintr9), _C_LABEL(Xintr10), _C_LABEL(Xintr11)
- .long _C_LABEL(Xintr12), _C_LABEL(Xintr13)
- .long _C_LABEL(Xintr14), _C_LABEL(Xintr15)
-
-/*
- * These tables are used by Xdoreti() and Xspllower().
- */
-/* resume points for suspended interrupts */
-IDTVEC(resume)
- .long _C_LABEL(Xresume0), _C_LABEL(Xresume1)
- .long _C_LABEL(Xresume2), _C_LABEL(Xresume3)
- .long _C_LABEL(Xresume4), _C_LABEL(Xresume5)
- .long _C_LABEL(Xresume6), _C_LABEL(Xresume7)
- .long _C_LABEL(Xresume8), _C_LABEL(Xresume9)
- .long _C_LABEL(Xresume10), _C_LABEL(Xresume11)
- .long _C_LABEL(Xresume12), _C_LABEL(Xresume13)
- .long _C_LABEL(Xresume14), _C_LABEL(Xresume15)
- /* for soft interrupts */
- .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- .long _C_LABEL(Xsofttty), _C_LABEL(Xsoftnet)
- .long _C_LABEL(Xsoftclock)
-/* fake interrupts to resume from splx() */
-IDTVEC(recurse)
- .long _C_LABEL(Xrecurse0), _C_LABEL(Xrecurse1)
- .long _C_LABEL(Xrecurse2), _C_LABEL(Xrecurse3)
- .long _C_LABEL(Xrecurse4), _C_LABEL(Xrecurse5)
- .long _C_LABEL(Xrecurse6), _C_LABEL(Xrecurse7)
- .long _C_LABEL(Xrecurse8), _C_LABEL(Xrecurse9)
- .long _C_LABEL(Xrecurse10), _C_LABEL(Xrecurse11)
- .long _C_LABEL(Xrecurse12), _C_LABEL(Xrecurse13)
- .long _C_LABEL(Xrecurse14), _C_LABEL(Xrecurse15)
- /* for soft interrupts */
- .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- .long _C_LABEL(Xsofttty), _C_LABEL(Xsoftnet)
- .long _C_LABEL(Xsoftclock)
-
-/* Some bogus data, to keep vmstat happy, for now. */
- .globl _C_LABEL(intrnames), _C_LABEL(eintrnames)
- .globl _C_LABEL(intrcnt), _C_LABEL(eintrcnt)
-_C_LABEL(intrnames):
- .long 0
-_C_LABEL(eintrnames):
-_C_LABEL(intrcnt):
- .long 0
-_C_LABEL(eintrcnt):