diff options
-rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 70 | ||||
-rw-r--r-- | sys/amd64/amd64/mptable.c | 70 | ||||
-rw-r--r-- | sys/amd64/amd64/tsc.c | 36 | ||||
-rw-r--r-- | sys/amd64/include/mptable.h | 70 | ||||
-rw-r--r-- | sys/amd64/include/smp.h | 2 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 36 | ||||
-rw-r--r-- | sys/i386/i386/mp_machdep.c | 70 | ||||
-rw-r--r-- | sys/i386/i386/mptable.c | 70 | ||||
-rw-r--r-- | sys/i386/i386/tsc.c | 36 | ||||
-rw-r--r-- | sys/i386/include/mptable.h | 70 | ||||
-rw-r--r-- | sys/i386/include/smp.h | 2 | ||||
-rw-r--r-- | sys/i386/isa/clock.c | 36 | ||||
-rw-r--r-- | sys/isa/atrtc.c | 36 | ||||
-rw-r--r-- | sys/kern/subr_smp.c | 70 | ||||
-rw-r--r-- | sys/sys/smp.h | 2 |
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)); |