summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2000-01-04 22:24:59 +0000
committertegge <tegge@FreeBSD.org>2000-01-04 22:24:59 +0000
commit8bfa846d9356da2586f4a6e1d554c39177f59e14 (patch)
treec6080f3bb42c4a733d4d4ce7c0d651f056f6f374 /sys
parent4f702e355c9a539bf4c04e5f1f2a333c2bc4fe25 (diff)
downloadFreeBSD-src-8bfa846d9356da2586f4a6e1d554c39177f59e14.zip
FreeBSD-src-8bfa846d9356da2586f4a6e1d554c39177f59e14.tar.gz
ISA device drivers use the ISA source interrupt number in locations where
the low level interrupt handler number should be used. Change setup_apic_irq_mapping() to allocate low level interrupt handler X (Xintr${X}) for any ISA interrupt X mentioned in the MP table. Remove an assumption in the driver for the system clock (clock.c) that interrupts mentioned in the MP table as delivered to IOAPIC #0 intpin Y is handled by low level interrupt handler Y (Xintr${Y}) but don't assume that low level interrupt handler 0 (Xintr0) is used. Don't allocate two low level interrupt handlers for the system clock. Reviewed by: NOKUBI Hirotaka <hnokubi@yyy.or.jp>
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/mp_machdep.c70
-rw-r--r--sys/amd64/amd64/mptable.c70
-rw-r--r--sys/amd64/amd64/tsc.c36
-rw-r--r--sys/amd64/include/mptable.h70
-rw-r--r--sys/amd64/include/smp.h2
-rw-r--r--sys/amd64/isa/clock.c36
-rw-r--r--sys/i386/i386/mp_machdep.c70
-rw-r--r--sys/i386/i386/mptable.c70
-rw-r--r--sys/i386/i386/tsc.c36
-rw-r--r--sys/i386/include/mptable.h70
-rw-r--r--sys/i386/include/smp.h2
-rw-r--r--sys/i386/isa/clock.c36
-rw-r--r--sys/isa/atrtc.c36
-rw-r--r--sys/kern/subr_smp.c70
-rw-r--r--sys/sys/smp.h2
15 files changed, 589 insertions, 87 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index b565cee..48d716a 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c
index b565cee..48d716a 100644
--- a/sys/amd64/amd64/mptable.c
+++ b/sys/amd64/amd64/mptable.c
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index 11b1426..ea39018 100644
--- a/sys/amd64/amd64/tsc.c
+++ b/sys/amd64/amd64/tsc.c
@@ -1001,7 +1001,7 @@ cpu_initclocks()
} else {
/* look for ExtInt on pin 0 */
if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = 0;
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
} else
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
@@ -1062,21 +1062,39 @@ cpu_initclocks()
INTRDIS(1 << apic_8254_intr);
inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to IO APIC int pin %d\n",
- apic_8254_intr);
-
- apic_8254_intr = 0;
+ "8254 is not connected to "
+ "IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
+ /*
+ * Revoke current ISA IRQ 0 assignment and
+ * configure a fallback interrupt routing from
+ * the 8254 Timer via the 8259 PIC to the
+ * an ExtInt interrupt line on IOAPIC #0 intpin 0.
+ * We reuse the low level interrupt handler number.
+ */
+ if (apic_irq(0, 0) < 0) {
+ revoke_apic_irq(apic_8254_intr);
+ assign_apic_irq(0, 0, apic_8254_intr);
+ }
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ inthand_add("clk", apic_8254_intr,
+ (inthand2_t *)clkintr,
NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
}
- if (apic_8254_intr)
- printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
+ if (apic_int_type(0, 0) != 3 ||
+ int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
+ int_to_apicintpin[apic_8254_intr].int_pin != 0)
+ printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
else
- printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
+ printf("APIC_IO: "
+ "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
#endif
}
diff --git a/sys/amd64/include/mptable.h b/sys/amd64/include/mptable.h
index b565cee..48d716a 100644
--- a/sys/amd64/include/mptable.h
+++ b/sys/amd64/include/mptable.h
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h
index 8f0a2f8..c2340ae 100644
--- a/sys/amd64/include/smp.h
+++ b/sys/amd64/include/smp.h
@@ -132,6 +132,8 @@ int apic_src_bus_irq __P((int, int));
int apic_int_type __P((int, int));
int apic_trigger __P((int, int));
int apic_polarity __P((int, int));
+void assign_apic_irq __P((int apic, int intpin, int irq));
+void revoke_apic_irq __P((int irq));
void bsp_apic_configure __P((void));
void init_secondary __P((void));
void smp_invltlb __P((void));
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index 11b1426..ea39018 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -1001,7 +1001,7 @@ cpu_initclocks()
} else {
/* look for ExtInt on pin 0 */
if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = 0;
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
} else
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
@@ -1062,21 +1062,39 @@ cpu_initclocks()
INTRDIS(1 << apic_8254_intr);
inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to IO APIC int pin %d\n",
- apic_8254_intr);
-
- apic_8254_intr = 0;
+ "8254 is not connected to "
+ "IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
+ /*
+ * Revoke current ISA IRQ 0 assignment and
+ * configure a fallback interrupt routing from
+ * the 8254 Timer via the 8259 PIC to the
+ * an ExtInt interrupt line on IOAPIC #0 intpin 0.
+ * We reuse the low level interrupt handler number.
+ */
+ if (apic_irq(0, 0) < 0) {
+ revoke_apic_irq(apic_8254_intr);
+ assign_apic_irq(0, 0, apic_8254_intr);
+ }
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ inthand_add("clk", apic_8254_intr,
+ (inthand2_t *)clkintr,
NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
}
- if (apic_8254_intr)
- printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
+ if (apic_int_type(0, 0) != 3 ||
+ int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
+ int_to_apicintpin[apic_8254_intr].int_pin != 0)
+ printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
else
- printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
+ printf("APIC_IO: "
+ "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
#endif
}
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index b565cee..48d716a 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c
index b565cee..48d716a 100644
--- a/sys/i386/i386/mptable.c
+++ b/sys/i386/i386/mptable.c
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c
index 11b1426..ea39018 100644
--- a/sys/i386/i386/tsc.c
+++ b/sys/i386/i386/tsc.c
@@ -1001,7 +1001,7 @@ cpu_initclocks()
} else {
/* look for ExtInt on pin 0 */
if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = 0;
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
} else
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
@@ -1062,21 +1062,39 @@ cpu_initclocks()
INTRDIS(1 << apic_8254_intr);
inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to IO APIC int pin %d\n",
- apic_8254_intr);
-
- apic_8254_intr = 0;
+ "8254 is not connected to "
+ "IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
+ /*
+ * Revoke current ISA IRQ 0 assignment and
+ * configure a fallback interrupt routing from
+ * the 8254 Timer via the 8259 PIC to the
+ * an ExtInt interrupt line on IOAPIC #0 intpin 0.
+ * We reuse the low level interrupt handler number.
+ */
+ if (apic_irq(0, 0) < 0) {
+ revoke_apic_irq(apic_8254_intr);
+ assign_apic_irq(0, 0, apic_8254_intr);
+ }
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ inthand_add("clk", apic_8254_intr,
+ (inthand2_t *)clkintr,
NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
}
- if (apic_8254_intr)
- printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
+ if (apic_int_type(0, 0) != 3 ||
+ int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
+ int_to_apicintpin[apic_8254_intr].int_pin != 0)
+ printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
else
- printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
+ printf("APIC_IO: "
+ "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
#endif
}
diff --git a/sys/i386/include/mptable.h b/sys/i386/include/mptable.h
index b565cee..48d716a 100644
--- a/sys/i386/include/mptable.h
+++ b/sys/i386/include/mptable.h
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h
index 8f0a2f8..c2340ae 100644
--- a/sys/i386/include/smp.h
+++ b/sys/i386/include/smp.h
@@ -132,6 +132,8 @@ int apic_src_bus_irq __P((int, int));
int apic_int_type __P((int, int));
int apic_trigger __P((int, int));
int apic_polarity __P((int, int));
+void assign_apic_irq __P((int apic, int intpin, int irq));
+void revoke_apic_irq __P((int irq));
void bsp_apic_configure __P((void));
void init_secondary __P((void));
void smp_invltlb __P((void));
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index 11b1426..ea39018 100644
--- a/sys/i386/isa/clock.c
+++ b/sys/i386/isa/clock.c
@@ -1001,7 +1001,7 @@ cpu_initclocks()
} else {
/* look for ExtInt on pin 0 */
if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = 0;
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
} else
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
@@ -1062,21 +1062,39 @@ cpu_initclocks()
INTRDIS(1 << apic_8254_intr);
inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to IO APIC int pin %d\n",
- apic_8254_intr);
-
- apic_8254_intr = 0;
+ "8254 is not connected to "
+ "IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
+ /*
+ * Revoke current ISA IRQ 0 assignment and
+ * configure a fallback interrupt routing from
+ * the 8254 Timer via the 8259 PIC to the
+ * an ExtInt interrupt line on IOAPIC #0 intpin 0.
+ * We reuse the low level interrupt handler number.
+ */
+ if (apic_irq(0, 0) < 0) {
+ revoke_apic_irq(apic_8254_intr);
+ assign_apic_irq(0, 0, apic_8254_intr);
+ }
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ inthand_add("clk", apic_8254_intr,
+ (inthand2_t *)clkintr,
NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
}
- if (apic_8254_intr)
- printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
+ if (apic_int_type(0, 0) != 3 ||
+ int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
+ int_to_apicintpin[apic_8254_intr].int_pin != 0)
+ printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
else
- printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
+ printf("APIC_IO: "
+ "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
#endif
}
diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c
index 11b1426..ea39018 100644
--- a/sys/isa/atrtc.c
+++ b/sys/isa/atrtc.c
@@ -1001,7 +1001,7 @@ cpu_initclocks()
} else {
/* look for ExtInt on pin 0 */
if (apic_int_type(0, 0) == 3) {
- apic_8254_intr = 0;
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
} else
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
@@ -1062,21 +1062,39 @@ cpu_initclocks()
INTRDIS(1 << apic_8254_intr);
inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
- "8254 is not connected to IO APIC int pin %d\n",
- apic_8254_intr);
-
- apic_8254_intr = 0;
+ "8254 is not connected to "
+ "IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
+ /*
+ * Revoke current ISA IRQ 0 assignment and
+ * configure a fallback interrupt routing from
+ * the 8254 Timer via the 8259 PIC to the
+ * an ExtInt interrupt line on IOAPIC #0 intpin 0.
+ * We reuse the low level interrupt handler number.
+ */
+ if (apic_irq(0, 0) < 0) {
+ revoke_apic_irq(apic_8254_intr);
+ assign_apic_irq(0, 0, apic_8254_intr);
+ }
+ apic_8254_intr = apic_irq(0, 0);
setup_8254_mixed_mode();
- inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ inthand_add("clk", apic_8254_intr,
+ (inthand2_t *)clkintr,
NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
}
- if (apic_8254_intr)
- printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
+ if (apic_int_type(0, 0) != 3 ||
+ int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
+ int_to_apicintpin[apic_8254_intr].int_pin != 0)
+ printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
+ int_to_apicintpin[apic_8254_intr].ioapic,
+ int_to_apicintpin[apic_8254_intr].int_pin);
else
- printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
+ printf("APIC_IO: "
+ "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
#endif
}
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index b565cee..48d716a 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -335,6 +335,7 @@ static void init_locks(void);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
+static int apic_int_is_bus_type(int intr, int bus_type);
/*
* Calculate usable address in base memory for AP trampoline code.
@@ -960,7 +961,7 @@ mptable_pass2(void)
}
-static void
+void
assign_apic_irq(int apic, int intpin, int irq)
{
int x;
@@ -983,6 +984,34 @@ assign_apic_irq(int apic, int intpin, int irq)
}
}
+void
+revoke_apic_irq(int irq)
+{
+ int x;
+ int oldapic;
+ int oldintpin;
+
+ if (int_to_apicintpin[irq].ioapic == -1)
+ panic("assign_apic_irq: inconsistent table");
+
+ oldapic = int_to_apicintpin[irq].ioapic;
+ oldintpin = int_to_apicintpin[irq].int_pin;
+
+ int_to_apicintpin[irq].ioapic = -1;
+ int_to_apicintpin[irq].int_pin = 0;
+ int_to_apicintpin[irq].apic_address = NULL;
+ int_to_apicintpin[irq].redirindex = 0;
+
+ for (x = 0; x < nintrs; x++) {
+ if ((io_apic_ints[x].int_type == 0 ||
+ io_apic_ints[x].int_type == 3) &&
+ io_apic_ints[x].int_vector == 0xff &&
+ io_apic_ints[x].dst_apic_id == IO_TO_ID(oldapic) &&
+ io_apic_ints[x].dst_apic_int == oldintpin)
+ io_apic_ints[x].int_vector = 0xff;
+ }
+}
+
/*
* parse an Intel MP specification table
*/
@@ -1049,37 +1078,66 @@ fix_mp_table(void)
}
+/* Assign low level interrupt handlers */
static void
setup_apic_irq_mapping(void)
{
int x;
int int_vector;
- /* Assign low level interrupt handlers */
+ /* Clear array */
for (x = 0; x < APIC_INTMAPSIZE; x++) {
int_to_apicintpin[x].ioapic = -1;
int_to_apicintpin[x].int_pin = 0;
int_to_apicintpin[x].apic_address = NULL;
int_to_apicintpin[x].redirindex = 0;
}
+
+ /* First assign ISA/EISA interrupts */
+ for (x = 0; x < nintrs; x++) {
+ int_vector = io_apic_ints[x].src_bus_irq;
+ if (int_vector < APIC_INTMAPSIZE &&
+ io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
+ (apic_int_is_bus_type(x, ISA) ||
+ apic_int_is_bus_type(x, EISA)) &&
+ io_apic_ints[x].int_type == 0) {
+ assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
+ io_apic_ints[x].dst_apic_int,
+ int_vector);
+ }
+ }
+
+ /* Assign interrupts on first 24 intpins on IOAPIC #0 */
for (x = 0; x < nintrs; x++) {
- if (io_apic_ints[x].dst_apic_int < APIC_INTMAPSIZE &&
+ int_vector = io_apic_ints[x].dst_apic_int;
+ if (int_vector < APIC_INTMAPSIZE &&
io_apic_ints[x].dst_apic_id == IO_TO_ID(0) &&
io_apic_ints[x].int_vector == 0xff &&
+ int_to_apicintpin[int_vector].ioapic == -1 &&
(io_apic_ints[x].int_type == 0 ||
io_apic_ints[x].int_type == 3)) {
- assign_apic_irq(0,
+ assign_apic_irq(0,
io_apic_ints[x].dst_apic_int,
- io_apic_ints[x].dst_apic_int);
+ int_vector);
}
}
+ /*
+ * Assign interrupts for remaining intpins.
+ * Skip IOAPIC #0 intpin 0 if the type is ExtInt, since this indicates
+ * that an entry for ISA/EISA irq 0 exist, and a fallback to mixed mode
+ * due to 8254 interrupts not being delivered can reuse that low level
+ * interrupt handler.
+ */
int_vector = 0;
while (int_vector < APIC_INTMAPSIZE &&
int_to_apicintpin[int_vector].ioapic != -1)
int_vector++;
for (x = 0; x < nintrs && int_vector < APIC_INTMAPSIZE; x++) {
if ((io_apic_ints[x].int_type == 0 ||
- io_apic_ints[x].int_type == 3) &&
+ (io_apic_ints[x].int_type == 3 &&
+ (io_apic_ints[x].dst_apic_id != IO_TO_ID(0) ||
+ io_apic_ints[x].dst_apic_int != 0))) &&
io_apic_ints[x].int_vector == 0xff) {
assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id),
io_apic_ints[x].dst_apic_int,
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 8f0a2f8..c2340ae 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -132,6 +132,8 @@ int apic_src_bus_irq __P((int, int));
int apic_int_type __P((int, int));
int apic_trigger __P((int, int));
int apic_polarity __P((int, int));
+void assign_apic_irq __P((int apic, int intpin, int irq));
+void revoke_apic_irq __P((int irq));
void bsp_apic_configure __P((void));
void init_secondary __P((void));
void smp_invltlb __P((void));
OpenPOWER on IntegriCloud