Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/sommerfeld_i386mp_1]: src/sys/arch/i386 Notice if multiple handlers with...
details: https://anonhg.NetBSD.org/src/rev/047dad37856a
branches: sommerfeld_i386mp_1
changeset: 482317:047dad37856a
user: sommerfeld <sommerfeld%NetBSD.org@localhost>
date: Sun Nov 19 00:20:29 2000 +0000
description:
Notice if multiple handlers with different IPL's share a single interrupt pin.
For now, warn if this is the case; in the future, we'll handle this correctly.
diffstat:
sys/arch/i386/i386/ioapic.c | 136 ++++++++++++++++++++++++-------------
sys/arch/i386/include/i82093var.h | 9 +-
2 files changed, 91 insertions(+), 54 deletions(-)
diffs (truncated from 341 to 300 lines):
diff -r 2b7b54dc58df -r 047dad37856a sys/arch/i386/i386/ioapic.c
--- a/sys/arch/i386/i386/ioapic.c Sat Nov 18 23:25:50 2000 +0000
+++ b/sys/arch/i386/i386/ioapic.c Sun Nov 19 00:20:29 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ioapic.c,v 1.1.2.10 2000/09/23 17:27:00 sommerfeld Exp $ */
+/* $NetBSD: ioapic.c,v 1.1.2.11 2000/11/19 00:20:30 sommerfeld Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
extern int i386_mem_add_mapping __P((bus_addr_t, bus_size_t,
int, bus_space_handle_t *)); /* XXX XXX */
-void apic_vectorset __P((struct ioapic_softc *, int, int));
+static void apic_vectorset __P((struct ioapic_softc *, int, int, int));
int apic_verbose = 0;
@@ -193,7 +193,6 @@
return 0;
}
-
/*
* can't use bus_space_xxx as we don't have a bus handle ...
*/
@@ -254,7 +253,8 @@
sc->sc_pins[i].ip_map = NULL;
sc->sc_pins[i].ip_vector = 0;
sc->sc_pins[i].ip_type = 0;
- sc->sc_pins[i].ip_level = 0;
+ sc->sc_pins[i].ip_minlevel = 0xff; /* XXX magic*/
+ sc->sc_pins[i].ip_maxlevel = 0; /* XXX magic */
}
/*
@@ -315,17 +315,17 @@
#define LEGAL_IRQ(x) ((x) >= 0 && (x) < APIC_ICU_LEN && (x) != 2)
static void
-apic_set_redir (struct ioapic_softc *sc, int irq)
+apic_set_redir (struct ioapic_softc *sc, int pin)
{
u_int32_t redlo;
u_int32_t redhi = 0;
int delmode;
- struct ioapic_pin *pin;
+ struct ioapic_pin *pp;
struct mp_intr_map *map;
- pin = &sc->sc_pins[irq];
- map = pin->ip_map;
+ pp = &sc->sc_pins[pin];
+ map = pp->ip_map;
if (map == NULL) {
redlo = IOAPIC_REDLO_MASK;
} else {
@@ -336,33 +336,35 @@
/* XXX magic numbers */
if ((delmode != 0) && (delmode != 1))
;
- else if (pin->ip_handler == NULL) {
+ else if (pp->ip_handler == NULL) {
redlo |= IOAPIC_REDLO_MASK;
} else {
- redlo |= (pin->ip_vector & 0xff);
+ redlo |= (pp->ip_vector & 0xff);
redlo |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
redlo &= ~IOAPIC_REDLO_DSTMOD;
- /* destination: BSP CPU */
-
/*
- * XXX will want to eventually switch to
- * lowest-priority delivery mode, possibly with focus
- * processor.
+ * Destination: BSP CPU
+ *
+ * XXX will want to distribute interrupts across cpu's
+ * eventually. most likely, we'll want to vector each
+ * interrupt to a specific CPU and load-balance across
+ * cpu's. but there's no point in doing that until after
+ * most interrupts run without the kernel lock.
*/
redhi |= (ioapic_bsp_id << IOAPIC_REDHI_DEST_SHIFT);
/* XXX derive this bit from BIOS info */
- if (pin->ip_type == IST_LEVEL)
+ if (pp->ip_type == IST_LEVEL)
redlo |= IOAPIC_REDLO_LEVEL;
else
redlo &= ~IOAPIC_REDLO_LEVEL;
/* XXX polarity goo, too */
}
- ioapic_write(sc,IOAPIC_REDLO(irq), redlo);
- ioapic_write(sc,IOAPIC_REDHI(irq), redhi);
+ ioapic_write(sc, IOAPIC_REDLO(pin), redlo);
+ ioapic_write(sc, IOAPIC_REDHI(pin), redhi);
if (mp_verbose)
- ioapic_print_redir(sc, "int", irq);
+ ioapic_print_redir(sc, "int", pin);
}
static int fakeintr __P((void *)); /* XXX headerify */
@@ -391,25 +393,36 @@
* interrupt configuration.
*/
-void
-apic_vectorset (sc, irq, level)
+static void
+apic_vectorset (sc, pin, minlevel, maxlevel)
struct ioapic_softc *sc;
- int irq;
- int level;
+ int pin;
+ int minlevel;
+ int maxlevel;
{
- struct ioapic_pin *pin = &sc->sc_pins[irq];
+ struct ioapic_pin *pp = &sc->sc_pins[pin];
int ovector = 0;
int nvector = 0;
void (*handler)(void);
- ovector = pin->ip_vector;
-
- if (level == 0) {
+ ovector = pp->ip_vector;
+
+ if (maxlevel == 0) {
/* no vector needed. */
- pin->ip_level = 0;
- pin->ip_vector = 0;
- } else if (level != pin->ip_level) {
- nvector = idt_vec_alloc (level, level+15);
+ pp->ip_minlevel = 0xff;/* XXX magic */
+ pp->ip_maxlevel = 0; /* XXX magic */
+ pp->ip_vector = 0;
+ } else if (maxlevel != pp->ip_maxlevel) {
+ if (minlevel != maxlevel) {
+ printf("%s: WARNING: sharing interrupt "
+ "between different IPLs (currently broken)\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: pin %d, ipls %x..%x",
+ sc->sc_dev.dv_xname,
+ pin, minlevel, maxlevel);
+ }
+
+ nvector = idt_vec_alloc (maxlevel, maxlevel+15);
if (nvector == NULL) {
/*
@@ -419,15 +432,20 @@
*/
panic("%s: can't alloc vector "
"for pin %d at level %x",
- sc->sc_dev.dv_xname, irq, level);
+ sc->sc_dev.dv_xname, pin, maxlevel);
}
+ /*
+ * XXX want special handler for the maxlevel != minlevel
+ * case here!
+ */
handler = apichandler[(nvector & 0xf) +
- ((level > IPL_HIGH) ? 0x10 : 0)];
+ ((maxlevel > IPL_HIGH) ? 0x10 : 0)];
idt_vec_set(nvector, handler);
- pin->ip_vector = nvector;
- pin->ip_level = level;
+ pp->ip_vector = nvector;
+ pp->ip_minlevel = minlevel;
+ pp->ip_maxlevel = maxlevel;
}
- apic_intrhand[pin->ip_vector] = pin->ip_handler;
+ apic_intrhand[pp->ip_vector] = pp->ip_handler;
if (ovector) {
/*
@@ -448,7 +466,7 @@
printf("freed vector %x\n", ovector);
}
- apic_set_redir (sc, irq);
+ apic_set_redir (sc, pin);
}
/*
@@ -458,7 +476,7 @@
void
ioapic_enable ()
{
- int p, maxlevel;
+ int p, maxlevel, minlevel;
struct ioapic_softc *sc;
struct intrhand *q;
extern void intr_calculatemasks __P((void)); /* XXX */
@@ -482,14 +500,17 @@
printf("%s: enabling\n", sc->sc_dev.dv_xname);
for (p=0; p<sc->sc_apic_sz; p++) {
- maxlevel = 0;
+ maxlevel = 0; /* magic */
+ minlevel = 0xff; /* magic */
for (q = sc->sc_pins[p].ip_handler; q != NULL;
q = q->ih_next) {
if (q->ih_level > maxlevel)
maxlevel = q->ih_level;
+ if (q->ih_level < minlevel)
+ minlevel = q->ih_level;
}
- apic_vectorset (sc, p, maxlevel);
+ apic_vectorset (sc, p, minlevel, maxlevel);
}
}
}
@@ -529,7 +550,7 @@
struct intrhand **p, *q, *ih;
static struct intrhand fakehand = {fakeintr};
extern int cold;
- int maxlevel;
+ int minlevel, maxlevel;
if (sc == NULL)
panic("apic_intr_establish: unknown ioapic %d", ioapic);
@@ -571,27 +592,36 @@
* preserve the order, and N is generally small.
*/
maxlevel = level;
+ minlevel = level;
for (p = &pin->ip_handler; (q = *p) != NULL; p = &q->ih_next) {
if (q->ih_level > maxlevel)
maxlevel = q->ih_level;
+ if (q->ih_level < minlevel)
+ minlevel = q->ih_level;
}
/*
* Actually install a fake handler momentarily, since we might be doing
* this with interrupts enabled and don't want the real routine called
* until masking is set up.
+ *
+ * XXX MP locking?
*/
fakehand.ih_level = level;
*p = &fakehand;
/*
- * fix up the vector for this pin.
- * XXX perhaps defer this until most interrupts have been established?
- * (to avoid too much thrashing of the idt..)
+ * Fix up the vector for this pin.
+ * (if cold, defer this until most interrupts have been established,
+ * to avoid too much thrashing of the idt..)
*/
if (!ioapic_cold)
- apic_vectorset(sc, intr, maxlevel);
+ apic_vectorset(sc, intr, minlevel, maxlevel);
+
+#if 0
+ apic_calculatemasks();
+#endif
/*
* Poke the real handler in now.
@@ -634,7 +664,7 @@
struct ioapic_softc *sc = ioapic_find(ioapic);
struct ioapic_pin *pin = &sc->sc_pins[intr];
struct intrhand **p, *q;
- int maxlevel;
+ int minlevel, maxlevel;
if (sc == NULL)
panic("apic_intr_disestablish: unknown ioapic %d", ioapic);
@@ -647,21 +677,27 @@
* This is O(n^2), too.
*/
maxlevel = 0;
+ minlevel = 0xff;
for (p = &pin->ip_handler; (q = *p) != NULL && q != ih;
- p = &q->ih_next)
+ p = &q->ih_next) {
if (q->ih_level > maxlevel)
maxlevel = q->ih_level;
-
+ if (q->ih_level < minlevel)
+ minlevel = q->ih_level;
+ }
if (q)
*p = q->ih_next;
else
panic("intr_disestablish: handler not registered");
- for (; q != NULL; q = q->ih_next)
+ for (; q != NULL; q = q->ih_next) {
if (q->ih_level > maxlevel)
maxlevel = q->ih_level;
+ if (q->ih_level < minlevel)
Home |
Main Index |
Thread Index |
Old Index