From 05420fa9d0f5b39c4de44d5b7b0bdb6285b656d5 Mon Sep 17 00:00:00 2001 From: tegge Date: Sun, 6 Sep 1998 22:41:42 +0000 Subject: [PATCH] Maintain a mapping from irq number to (ioapic number, int pin) tuple, and use this when masking/unmasking interrupts. Maintain a mapping from (iopaic number, int pin) tuple to irq number, and use this when configuring devices and programming the ioapics. Previous code assumed that irq number was equal to int pin number, and that the ioapic number was 0. Don't let an AP enter _cpu_switch before all local apics are initialized. --- sys/amd64/amd64/apic_vector.S | 17 +++-- sys/amd64/amd64/mp_machdep.c | 129 ++++++++++++++++++++++++++++++---- sys/amd64/amd64/mpboot.S | 8 ++- sys/amd64/amd64/mptable.c | 129 ++++++++++++++++++++++++++++++---- sys/amd64/amd64/tsc.c | 6 +- sys/amd64/include/apicreg.h | 8 +-- sys/amd64/include/mptable.h | 129 ++++++++++++++++++++++++++++++---- sys/amd64/include/smp.h | 22 +++--- sys/amd64/isa/clock.c | 6 +- sys/amd64/isa/intr_machdep.c | 13 ++-- sys/amd64/isa/nmi.c | 13 ++-- sys/dev/pci/pci.c | 6 +- sys/i386/i386/apic_vector.s | 17 +++-- sys/i386/i386/mp_machdep.c | 129 ++++++++++++++++++++++++++++++---- sys/i386/i386/mpapic.c | 97 +++++++++++++------------ sys/i386/i386/mpboot.s | 8 ++- sys/i386/i386/mptable.c | 129 ++++++++++++++++++++++++++++++---- sys/i386/i386/tsc.c | 6 +- sys/i386/include/apic.h | 8 +-- sys/i386/include/apicreg.h | 8 +-- sys/i386/include/mptable.h | 129 ++++++++++++++++++++++++++++++---- sys/i386/include/smp.h | 22 +++--- sys/i386/isa/apic_ipl.s | 18 ++--- sys/i386/isa/apic_vector.s | 17 +++-- sys/i386/isa/clock.c | 6 +- sys/i386/isa/intr_machdep.c | 13 ++-- sys/i386/isa/nmi.c | 13 ++-- sys/isa/atrtc.c | 6 +- sys/kern/subr_smp.c | 129 ++++++++++++++++++++++++++++++---- sys/pci/pci.c | 6 +- sys/pci/pci_compat.c | 12 ++-- sys/sys/smp.h | 22 +++--- 32 files changed, 1008 insertions(+), 273 deletions(-) diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 4bd4f777eb1e..17f894204dd9 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: apic_vector.s,v 1.32 1998/08/11 17:01:32 bde Exp $ + * $Id: apic_vector.s,v 1.33 1998/09/04 23:03:04 luoqi Exp $ */ @@ -166,13 +166,17 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +#define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 +#define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 + #define MASK_IRQ(irq_num) \ IMASK_LOCK ; /* into critical reg */ \ testl $IRQ_BIT(irq_num), _apic_imen ; \ jne 7f ; /* masked, don't mask */ \ orl $IRQ_BIT(irq_num), _apic_imen ; /* set the mask bit */ \ - movl _ioapic, %ecx ; /* ioapic[0] addr */ \ - movl $REDTBL_IDX(irq_num), (%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num), %ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax, (%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx), %eax ; /* current value */ \ orl $IOART_INTMASK, %eax ; /* set the mask */ \ movl %eax, IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -218,8 +222,9 @@ IDTVEC(vec_name) ; \ testl $IRQ_BIT(irq_num), _apic_imen ; \ je 7f ; /* bit clear, not masked */ \ andl $~IRQ_BIT(irq_num), _apic_imen ;/* clear mask bit */ \ - movl _ioapic,%ecx ; /* ioapic[0]addr */ \ - movl $REDTBL_IDX(irq_num),(%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num),%ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax,(%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx),%eax ; /* current value */ \ andl $~IOART_INTMASK,%eax ; /* clear the mask */ \ movl %eax,IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -990,7 +995,7 @@ CNAME(cpustop_restartfunc): .globl _apic_pin_trigger _apic_pin_trigger: - .space (NAPIC * 4), 0 + .long 0 /* diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/amd64/amd64/mpboot.S b/sys/amd64/amd64/mpboot.S index e3661f255509..1c311fe08ad7 100644 --- a/sys/amd64/amd64/mpboot.S +++ b/sys/amd64/amd64/mpboot.S @@ -31,7 +31,7 @@ * mpboot.s: FreeBSD machine support for the Intel MP Spec * multiprocessor systems. * - * $Id: mpboot.s,v 1.5 1997/09/22 05:03:03 peter Exp $ + * $Id: mpboot.s,v 1.6 1997/10/10 09:44:05 peter Exp $ */ #include "opt_vm86.h" @@ -124,6 +124,12 @@ mp_begin: /* now running relocated at KERNBASE */ /* Now, let's prepare for some REAL WORK :-) */ call _ap_init + call _rel_mplock +2: + cmpl $0, CNAME(smp_started) /* Wait for last AP to be ready */ + jz 2b + call _get_mplock + /* let her rip! (loads new stack) */ jmp _cpu_switch diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/amd64/amd64/mptable.c +++ b/sys/amd64/amd64/mptable.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 4e14052e946b..3d8f8cd50da4 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.123 1998/06/07 20:36:39 phk Exp $ + * $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $ */ /* @@ -953,7 +953,7 @@ cpu_initclocks() /* Finish initializing 8253 timer 0. */ #ifdef APIC_IO - apic_8254_intr = isa_apic_pin(0); + apic_8254_intr = isa_apic_irq(0); apic_8254_trial = 0; if (apic_8254_intr >= 0 ) { if (apic_int_type(0, 0) == 3) @@ -993,7 +993,7 @@ cpu_initclocks() printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); #ifdef APIC_IO - if (isa_apic_pin(8) != 8) + if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); #endif /* APIC_IO */ diff --git a/sys/amd64/include/apicreg.h b/sys/amd64/include/apicreg.h index 50f84166c4ab..55e44e0bec2f 100644 --- a/sys/amd64/include/apicreg.h +++ b/sys/amd64/include/apicreg.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic.h,v 1.7 1997/08/04 17:20:39 smp Exp smp $ + * $Id: apic.h,v 1.11 1997/08/04 17:31:24 fsmp Exp $ */ #ifndef _MACHINE_APIC_H_ @@ -113,12 +113,6 @@ * global defines, etc. */ -/** - * this enables code concerned with handling more than one IO APIC. - * Note: this is NOT READY for use! - * -#define MULTIPLE_IOAPICS - */ /****************************************************************************** * LOCAL APIC structure diff --git a/sys/amd64/include/mptable.h b/sys/amd64/include/mptable.h index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/amd64/include/mptable.h +++ b/sys/amd64/include/mptable.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index f2586304524c..0f4f915366b6 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: smp.h,v 1.42 1998/04/01 21:07:36 tegge Exp $ + * $Id: smp.h,v 1.43 1998/05/17 22:12:05 tegge Exp $ * */ @@ -103,6 +103,14 @@ extern u_int32_t io_apic_versions[]; extern int cpu_num_to_apic_id[]; extern int io_num_to_apic_id[]; extern int apic_id_to_logical[]; +#define APIC_INTMAPSIZE 24 +struct apic_intmapinfo { + int ioapic; + int int_pin; + volatile void *apic_address; + int redirindex; +}; +extern struct apic_intmapinfo int_to_apicintpin[]; extern u_int all_cpus; extern u_char SMP_ioapic[]; extern struct pcb stoppcbs[]; @@ -113,9 +121,10 @@ int mp_probe __P((void)); void mp_start __P((void)); void mp_announce __P((void)); u_int isa_apic_mask __P((u_int)); -int isa_apic_pin __P((int)); -int pci_apic_pin __P((int, int, int)); -int next_apic_pin __P((int)); +int isa_apic_irq __P((int)); +int pci_apic_irq __P((int, int, int)); +int apic_irq __P((int, int)); +int next_apic_irq __P((int)); int undirect_isa_irq __P((int)); int undirect_pci_irq __P((int)); int apic_bus_type __P((int)); @@ -141,12 +150,7 @@ void set_lapic_isrloc __P((int, int)); /* global data in mpapic.c */ extern volatile lapic_t lapic; - -#if defined(MULTIPLE_IOAPICS) -#error MULTIPLE_IOAPICSXXX -#else extern volatile ioapic_t *ioapic[]; -#endif /* MULTIPLE_IOAPICS */ /* functions in mpapic.c */ void apic_dump __P((char*)); diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 4e14052e946b..3d8f8cd50da4 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.123 1998/06/07 20:36:39 phk Exp $ + * $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $ */ /* @@ -953,7 +953,7 @@ cpu_initclocks() /* Finish initializing 8253 timer 0. */ #ifdef APIC_IO - apic_8254_intr = isa_apic_pin(0); + apic_8254_intr = isa_apic_irq(0); apic_8254_trial = 0; if (apic_8254_intr >= 0 ) { if (apic_int_type(0, 0) == 3) @@ -993,7 +993,7 @@ cpu_initclocks() printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); #ifdef APIC_IO - if (isa_apic_pin(8) != 8) + if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); #endif /* APIC_IO */ diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c index 49c7f2451fb9..3f891f2af315 100644 --- a/sys/amd64/isa/intr_machdep.c +++ b/sys/amd64/isa/intr_machdep.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.12 1998/06/18 15:32:06 bde Exp $ + * $Id: intr_machdep.c,v 1.13 1998/06/18 16:08:46 bde Exp $ */ #include "opt_auto_eoi.h" @@ -429,12 +429,15 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) set_lapic_isrloc(intr, vector); #endif /* - * XXX MULTIPLE_IOAPICSXXX * Reprogram the vector in the IO APIC. */ - select = (intr * 2) + IOAPIC_REDTBL0; - value = io_apic_read(0, select) & ~IOART_INTVEC; - io_apic_write(0, select, value | vector); + if (int_to_apicintpin[intr].ioapic >= 0) { + select = int_to_apicintpin[intr].redirindex; + value = io_apic_read(int_to_apicintpin[intr].ioapic, + select) & ~IOART_INTVEC; + io_apic_write(int_to_apicintpin[intr].ioapic, + select, value | vector); + } #else setidt(ICU_OFFSET + intr, flags & INTR_FAST ? fastintr[intr] : slowintr[intr], diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c index 49c7f2451fb9..3f891f2af315 100644 --- a/sys/amd64/isa/nmi.c +++ b/sys/amd64/isa/nmi.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.12 1998/06/18 15:32:06 bde Exp $ + * $Id: intr_machdep.c,v 1.13 1998/06/18 16:08:46 bde Exp $ */ #include "opt_auto_eoi.h" @@ -429,12 +429,15 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) set_lapic_isrloc(intr, vector); #endif /* - * XXX MULTIPLE_IOAPICSXXX * Reprogram the vector in the IO APIC. */ - select = (intr * 2) + IOAPIC_REDTBL0; - value = io_apic_read(0, select) & ~IOART_INTVEC; - io_apic_write(0, select, value | vector); + if (int_to_apicintpin[intr].ioapic >= 0) { + select = int_to_apicintpin[intr].redirindex; + value = io_apic_read(int_to_apicintpin[intr].ioapic, + select) & ~IOART_INTVEC; + io_apic_write(int_to_apicintpin[intr].ioapic, + select, value | vector); + } #else setidt(ICU_OFFSET + intr, flags & INTR_FAST ? fastintr[intr] : slowintr[intr], diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 2dac6de36177..fceb2205e5d1 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci.c,v 1.84 1998/07/22 08:40:46 dfr Exp $ + * $Id: pci.c,v 1.85 1998/08/13 19:12:20 gibbs Exp $ * */ @@ -343,7 +343,7 @@ pci_readcfg(pcicfgregs *probe) if (cfg->intpin != 0) { int airq; - airq = pci_apic_pin(cfg->bus, cfg->slot, cfg->intpin); + airq = pci_apic_irq(cfg->bus, cfg->slot, cfg->intpin); if (airq >= 0) { /* PCI specific entry found in MP table */ if (airq != cfg->intline) { @@ -357,7 +357,7 @@ pci_readcfg(pcicfgregs *probe) * same methods as used by the ISA devices * devices to find the proper IOAPIC int pin. */ - airq = isa_apic_pin(cfg->intline); + airq = isa_apic_irq(cfg->intline); if ((airq >= 0) && (airq != cfg->intline)) { /* XXX: undirect_pci_irq() ? */ undirect_isa_irq(cfg->intline); diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index 4bd4f777eb1e..17f894204dd9 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: apic_vector.s,v 1.32 1998/08/11 17:01:32 bde Exp $ + * $Id: apic_vector.s,v 1.33 1998/09/04 23:03:04 luoqi Exp $ */ @@ -166,13 +166,17 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +#define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 +#define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 + #define MASK_IRQ(irq_num) \ IMASK_LOCK ; /* into critical reg */ \ testl $IRQ_BIT(irq_num), _apic_imen ; \ jne 7f ; /* masked, don't mask */ \ orl $IRQ_BIT(irq_num), _apic_imen ; /* set the mask bit */ \ - movl _ioapic, %ecx ; /* ioapic[0] addr */ \ - movl $REDTBL_IDX(irq_num), (%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num), %ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax, (%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx), %eax ; /* current value */ \ orl $IOART_INTMASK, %eax ; /* set the mask */ \ movl %eax, IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -218,8 +222,9 @@ IDTVEC(vec_name) ; \ testl $IRQ_BIT(irq_num), _apic_imen ; \ je 7f ; /* bit clear, not masked */ \ andl $~IRQ_BIT(irq_num), _apic_imen ;/* clear mask bit */ \ - movl _ioapic,%ecx ; /* ioapic[0]addr */ \ - movl $REDTBL_IDX(irq_num),(%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num),%ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax,(%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx),%eax ; /* current value */ \ andl $~IOART_INTMASK,%eax ; /* clear the mask */ \ movl %eax,IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -990,7 +995,7 @@ CNAME(cpustop_restartfunc): .globl _apic_pin_trigger _apic_pin_trigger: - .space (NAPIC * 4), 0 + .long 0 /* diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/i386/i386/mpapic.c b/sys/i386/i386/mpapic.c index a101a2cc9883..48663a445bbe 100644 --- a/sys/i386/i386/mpapic.c +++ b/sys/i386/i386/mpapic.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mpapic.c,v 1.30 1998/04/19 23:19:20 tegge Exp $ + * $Id: mpapic.c,v 1.31 1998/05/17 17:32:10 tegge Exp $ */ #include "opt_smp.h" @@ -146,7 +146,7 @@ static void polarity __P((int apic, int pin, u_int32_t * flags, int level)); /* * Setup the IO APIC. */ -extern int apic_pin_trigger[]; /* 'opaque' */ +extern int apic_pin_trigger; /* 'opaque' */ int io_apic_setup(int apic) { @@ -159,56 +159,55 @@ io_apic_setup(int apic) target = IOART_DEST; - apic_pin_trigger[apic] = 0; /* default to edge-triggered */ + if (apic == 0) + apic_pin_trigger = 0; /* default to edge-triggered */ - if (apic == 0) { - maxpin = REDIRCNT_IOAPIC(apic); /* pins in APIC */ - for (pin = 0; pin < maxpin; ++pin) { - int bus, bustype; + maxpin = REDIRCNT_IOAPIC(apic); /* pins in APIC */ + printf("Programming %d pins in IOAPIC #%d\n", maxpin, apic); + + for (pin = 0; pin < maxpin; ++pin) { + int bus, bustype, irq; + + /* we only deal with vectored INTs here */ + if (apic_int_type(apic, pin) != 0) + continue; - /* we only deal with vectored INTs here */ - if (apic_int_type(apic, pin) != 0) - continue; - - /* determine the bus type for this pin */ - bus = apic_src_bus_id(apic, pin); - if (bus == -1) - continue; - bustype = apic_bus_type(bus); - - /* the "ISA" type INTerrupts */ - if ((bustype == ISA) && - (pin < IOAPIC_ISA_INTS) && - (isa_apic_pin(pin) == pin) && - (apic_polarity(apic, pin) == 0x1) && - (apic_trigger(apic, pin) == 0x3)) { - flags = DEFAULT_ISA_FLAGS; - } - - /* PCI or other bus */ - else { - flags = DEFAULT_FLAGS; - level = trigger(apic, pin, &flags); - if (level == 1) - apic_pin_trigger[apic] |= (1 << pin); - polarity(apic, pin, &flags, level); - } - - /* program the appropriate registers */ - select = pin * 2 + IOAPIC_REDTBL0; /* register */ - vector = NRSVIDT + pin; /* IDT vec */ - io_apic_write(apic, select, flags | vector); - io_apic_write(apic, select + 1, target); + irq = apic_irq(apic, pin); + if (irq == 0xff) + continue; + + /* determine the bus type for this pin */ + bus = apic_src_bus_id(apic, pin); + if (bus == -1) + continue; + bustype = apic_bus_type(bus); + + /* the "ISA" type INTerrupts */ + if ((bustype == ISA) && + (pin < IOAPIC_ISA_INTS) && + (irq == pin) && + (apic_polarity(apic, pin) == 0x1) && + (apic_trigger(apic, pin) == 0x3)) { + flags = DEFAULT_ISA_FLAGS; } - } - - /* program entry according to MP table. */ - else { -#if defined(MULTIPLE_IOAPICS) -#error MULTIPLE_IOAPICSXXX -#else - panic("io_apic_setup: apic #%d", apic); -#endif/* MULTIPLE_IOAPICS */ + + /* PCI or other bus */ + else { + flags = DEFAULT_FLAGS; + level = trigger(apic, pin, &flags); + if (level == 1) + apic_pin_trigger |= (1 << irq); + polarity(apic, pin, &flags, level); + } + + /* program the appropriate registers */ + if (apic != 0 || pin != irq) + printf("IOAPIC #%d intpint %d -> irq %d\n", + apic, pin, irq); + select = pin * 2 + IOAPIC_REDTBL0; /* register */ + vector = NRSVIDT + irq; /* IDT vec */ + io_apic_write(apic, select, flags | vector); + io_apic_write(apic, select + 1, target); } /* return GOOD status */ diff --git a/sys/i386/i386/mpboot.s b/sys/i386/i386/mpboot.s index e3661f255509..1c311fe08ad7 100644 --- a/sys/i386/i386/mpboot.s +++ b/sys/i386/i386/mpboot.s @@ -31,7 +31,7 @@ * mpboot.s: FreeBSD machine support for the Intel MP Spec * multiprocessor systems. * - * $Id: mpboot.s,v 1.5 1997/09/22 05:03:03 peter Exp $ + * $Id: mpboot.s,v 1.6 1997/10/10 09:44:05 peter Exp $ */ #include "opt_vm86.h" @@ -124,6 +124,12 @@ mp_begin: /* now running relocated at KERNBASE */ /* Now, let's prepare for some REAL WORK :-) */ call _ap_init + call _rel_mplock +2: + cmpl $0, CNAME(smp_started) /* Wait for last AP to be ready */ + jz 2b + call _get_mplock + /* let her rip! (loads new stack) */ jmp _cpu_switch diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/i386/i386/mptable.c +++ b/sys/i386/i386/mptable.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 4e14052e946b..3d8f8cd50da4 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.123 1998/06/07 20:36:39 phk Exp $ + * $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $ */ /* @@ -953,7 +953,7 @@ cpu_initclocks() /* Finish initializing 8253 timer 0. */ #ifdef APIC_IO - apic_8254_intr = isa_apic_pin(0); + apic_8254_intr = isa_apic_irq(0); apic_8254_trial = 0; if (apic_8254_intr >= 0 ) { if (apic_int_type(0, 0) == 3) @@ -993,7 +993,7 @@ cpu_initclocks() printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); #ifdef APIC_IO - if (isa_apic_pin(8) != 8) + if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); #endif /* APIC_IO */ diff --git a/sys/i386/include/apic.h b/sys/i386/include/apic.h index 50f84166c4ab..55e44e0bec2f 100644 --- a/sys/i386/include/apic.h +++ b/sys/i386/include/apic.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic.h,v 1.7 1997/08/04 17:20:39 smp Exp smp $ + * $Id: apic.h,v 1.11 1997/08/04 17:31:24 fsmp Exp $ */ #ifndef _MACHINE_APIC_H_ @@ -113,12 +113,6 @@ * global defines, etc. */ -/** - * this enables code concerned with handling more than one IO APIC. - * Note: this is NOT READY for use! - * -#define MULTIPLE_IOAPICS - */ /****************************************************************************** * LOCAL APIC structure diff --git a/sys/i386/include/apicreg.h b/sys/i386/include/apicreg.h index 50f84166c4ab..55e44e0bec2f 100644 --- a/sys/i386/include/apicreg.h +++ b/sys/i386/include/apicreg.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic.h,v 1.7 1997/08/04 17:20:39 smp Exp smp $ + * $Id: apic.h,v 1.11 1997/08/04 17:31:24 fsmp Exp $ */ #ifndef _MACHINE_APIC_H_ @@ -113,12 +113,6 @@ * global defines, etc. */ -/** - * this enables code concerned with handling more than one IO APIC. - * Note: this is NOT READY for use! - * -#define MULTIPLE_IOAPICS - */ /****************************************************************************** * LOCAL APIC structure diff --git a/sys/i386/include/mptable.h b/sys/i386/include/mptable.h index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/i386/include/mptable.h +++ b/sys/i386/include/mptable.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h index f2586304524c..0f4f915366b6 100644 --- a/sys/i386/include/smp.h +++ b/sys/i386/include/smp.h @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: smp.h,v 1.42 1998/04/01 21:07:36 tegge Exp $ + * $Id: smp.h,v 1.43 1998/05/17 22:12:05 tegge Exp $ * */ @@ -103,6 +103,14 @@ extern u_int32_t io_apic_versions[]; extern int cpu_num_to_apic_id[]; extern int io_num_to_apic_id[]; extern int apic_id_to_logical[]; +#define APIC_INTMAPSIZE 24 +struct apic_intmapinfo { + int ioapic; + int int_pin; + volatile void *apic_address; + int redirindex; +}; +extern struct apic_intmapinfo int_to_apicintpin[]; extern u_int all_cpus; extern u_char SMP_ioapic[]; extern struct pcb stoppcbs[]; @@ -113,9 +121,10 @@ int mp_probe __P((void)); void mp_start __P((void)); void mp_announce __P((void)); u_int isa_apic_mask __P((u_int)); -int isa_apic_pin __P((int)); -int pci_apic_pin __P((int, int, int)); -int next_apic_pin __P((int)); +int isa_apic_irq __P((int)); +int pci_apic_irq __P((int, int, int)); +int apic_irq __P((int, int)); +int next_apic_irq __P((int)); int undirect_isa_irq __P((int)); int undirect_pci_irq __P((int)); int apic_bus_type __P((int)); @@ -141,12 +150,7 @@ void set_lapic_isrloc __P((int, int)); /* global data in mpapic.c */ extern volatile lapic_t lapic; - -#if defined(MULTIPLE_IOAPICS) -#error MULTIPLE_IOAPICSXXX -#else extern volatile ioapic_t *ioapic[]; -#endif /* MULTIPLE_IOAPICS */ /* functions in mpapic.c */ void apic_dump __P((char*)); diff --git a/sys/i386/isa/apic_ipl.s b/sys/i386/isa/apic_ipl.s index 5bbdca65d6ee..8d9b9d835cc4 100644 --- a/sys/i386/isa/apic_ipl.s +++ b/sys/i386/isa/apic_ipl.s @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apic_ipl.s,v 1.20 1998/04/22 22:49:29 tegge Exp $ + * $Id: apic_ipl.s,v 1.21 1998/08/11 15:08:12 bde Exp $ */ @@ -227,7 +227,6 @@ bad_mask: .asciz "bad mask" #endif /* - * MULTIPLE_IOAPICSXXX: cannot assume apic #0 in the following function. * (soon to be) MP-safe function to clear ONE INT mask bit. * The passed arg is a 32bit u_int MASK. * It sets the associated bit in _apic_imen. @@ -244,10 +243,9 @@ ENTRY(INTREN) QUALIFY_MASK - leal 16(,%ecx,2), %ecx /* calculate register index */ - - movl $0, %edx /* XXX FIXME: APIC # */ - movl _ioapic(,%edx,4), %edx /* %edx holds APIC base address */ + shll $4, %ecx + movl CNAME(int_to_apicintpin) + 8(%ecx), %edx + movl CNAME(int_to_apicintpin) + 12(%ecx), %ecx movl %ecx, (%edx) /* write the target register index */ movl 16(%edx), %eax /* read the target register data */ @@ -259,7 +257,6 @@ ENTRY(INTREN) ret /* - * MULTIPLE_IOAPICSXXX: cannot assume apic #0 in the following function. * (soon to be) MP-safe function to set ONE INT mask bit. * The passed arg is a 32bit u_int MASK. * It clears the associated bit in _apic_imen. @@ -276,10 +273,9 @@ ENTRY(INTRDIS) QUALIFY_MASK - leal 16(,%ecx,2), %ecx /* calculate register index */ - - movl $0, %edx /* XXX FIXME: APIC # */ - movl _ioapic(,%edx,4), %edx /* %edx holds APIC base address */ + shll $4, %ecx + movl CNAME(int_to_apicintpin) + 8(%ecx), %edx + movl CNAME(int_to_apicintpin) + 12(%ecx), %ecx movl %ecx, (%edx) /* write the target register index */ movl 16(%edx), %eax /* read the target register data */ diff --git a/sys/i386/isa/apic_vector.s b/sys/i386/isa/apic_vector.s index 4bd4f777eb1e..17f894204dd9 100644 --- a/sys/i386/isa/apic_vector.s +++ b/sys/i386/isa/apic_vector.s @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: apic_vector.s,v 1.32 1998/08/11 17:01:32 bde Exp $ + * $Id: apic_vector.s,v 1.33 1998/09/04 23:03:04 luoqi Exp $ */ @@ -166,13 +166,17 @@ IDTVEC(vec_name) ; \ popal ; \ addl $4+4,%esp +#define IOAPICADDR(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 8 +#define REDIRIDX(irq_num) CNAME(int_to_apicintpin) + 16 * (irq_num) + 12 + #define MASK_IRQ(irq_num) \ IMASK_LOCK ; /* into critical reg */ \ testl $IRQ_BIT(irq_num), _apic_imen ; \ jne 7f ; /* masked, don't mask */ \ orl $IRQ_BIT(irq_num), _apic_imen ; /* set the mask bit */ \ - movl _ioapic, %ecx ; /* ioapic[0] addr */ \ - movl $REDTBL_IDX(irq_num), (%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num), %ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax, (%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx), %eax ; /* current value */ \ orl $IOART_INTMASK, %eax ; /* set the mask */ \ movl %eax, IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -218,8 +222,9 @@ IDTVEC(vec_name) ; \ testl $IRQ_BIT(irq_num), _apic_imen ; \ je 7f ; /* bit clear, not masked */ \ andl $~IRQ_BIT(irq_num), _apic_imen ;/* clear mask bit */ \ - movl _ioapic,%ecx ; /* ioapic[0]addr */ \ - movl $REDTBL_IDX(irq_num),(%ecx) ; /* write the index */ \ + movl IOAPICADDR(irq_num),%ecx ; /* ioapic addr */ \ + movl REDIRIDX(irq_num), %eax ; /* get the index */ \ + movl %eax,(%ecx) ; /* write the index */ \ movl IOAPIC_WINDOW(%ecx),%eax ; /* current value */ \ andl $~IOART_INTMASK,%eax ; /* clear the mask */ \ movl %eax,IOAPIC_WINDOW(%ecx) ; /* new value */ \ @@ -990,7 +995,7 @@ CNAME(cpustop_restartfunc): .globl _apic_pin_trigger _apic_pin_trigger: - .space (NAPIC * 4), 0 + .long 0 /* diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 4e14052e946b..3d8f8cd50da4 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.123 1998/06/07 20:36:39 phk Exp $ + * $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $ */ /* @@ -953,7 +953,7 @@ cpu_initclocks() /* Finish initializing 8253 timer 0. */ #ifdef APIC_IO - apic_8254_intr = isa_apic_pin(0); + apic_8254_intr = isa_apic_irq(0); apic_8254_trial = 0; if (apic_8254_intr >= 0 ) { if (apic_int_type(0, 0) == 3) @@ -993,7 +993,7 @@ cpu_initclocks() printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); #ifdef APIC_IO - if (isa_apic_pin(8) != 8) + if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); #endif /* APIC_IO */ diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c index 49c7f2451fb9..3f891f2af315 100644 --- a/sys/i386/isa/intr_machdep.c +++ b/sys/i386/isa/intr_machdep.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.12 1998/06/18 15:32:06 bde Exp $ + * $Id: intr_machdep.c,v 1.13 1998/06/18 16:08:46 bde Exp $ */ #include "opt_auto_eoi.h" @@ -429,12 +429,15 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) set_lapic_isrloc(intr, vector); #endif /* - * XXX MULTIPLE_IOAPICSXXX * Reprogram the vector in the IO APIC. */ - select = (intr * 2) + IOAPIC_REDTBL0; - value = io_apic_read(0, select) & ~IOART_INTVEC; - io_apic_write(0, select, value | vector); + if (int_to_apicintpin[intr].ioapic >= 0) { + select = int_to_apicintpin[intr].redirindex; + value = io_apic_read(int_to_apicintpin[intr].ioapic, + select) & ~IOART_INTVEC; + io_apic_write(int_to_apicintpin[intr].ioapic, + select, value | vector); + } #else setidt(ICU_OFFSET + intr, flags & INTR_FAST ? fastintr[intr] : slowintr[intr], diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c index 49c7f2451fb9..3f891f2af315 100644 --- a/sys/i386/isa/nmi.c +++ b/sys/i386/isa/nmi.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.12 1998/06/18 15:32:06 bde Exp $ + * $Id: intr_machdep.c,v 1.13 1998/06/18 16:08:46 bde Exp $ */ #include "opt_auto_eoi.h" @@ -429,12 +429,15 @@ icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) set_lapic_isrloc(intr, vector); #endif /* - * XXX MULTIPLE_IOAPICSXXX * Reprogram the vector in the IO APIC. */ - select = (intr * 2) + IOAPIC_REDTBL0; - value = io_apic_read(0, select) & ~IOART_INTVEC; - io_apic_write(0, select, value | vector); + if (int_to_apicintpin[intr].ioapic >= 0) { + select = int_to_apicintpin[intr].redirindex; + value = io_apic_read(int_to_apicintpin[intr].ioapic, + select) & ~IOART_INTVEC; + io_apic_write(int_to_apicintpin[intr].ioapic, + select, value | vector); + } #else setidt(ICU_OFFSET + intr, flags & INTR_FAST ? fastintr[intr] : slowintr[intr], diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 4e14052e946b..3d8f8cd50da4 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.123 1998/06/07 20:36:39 phk Exp $ + * $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $ */ /* @@ -953,7 +953,7 @@ cpu_initclocks() /* Finish initializing 8253 timer 0. */ #ifdef APIC_IO - apic_8254_intr = isa_apic_pin(0); + apic_8254_intr = isa_apic_irq(0); apic_8254_trial = 0; if (apic_8254_intr >= 0 ) { if (apic_int_type(0, 0) == 3) @@ -993,7 +993,7 @@ cpu_initclocks() printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); #ifdef APIC_IO - if (isa_apic_pin(8) != 8) + if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); #endif /* APIC_IO */ diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index 04e3c693c6b6..e00c2f4864e2 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.78 1998/08/18 07:46:58 msmith Exp $ + * $Id: mp_machdep.c,v 1.79 1998/08/24 02:28:15 bde Exp $ */ #include "opt_smp.h" @@ -278,6 +278,8 @@ struct { } apic_isrbit_location[32]; #endif +struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE]; + /* * APIC ID logical/physical mapping structures. * We oversize these to simplify boot-time config. @@ -315,7 +317,7 @@ extern pd_entry_t *my_idlePTD; struct pcb stoppcbs[NCPU]; -static int smp_started; /* has the system started? */ +int smp_started; /* has the system started? */ /* * Local data and functions. @@ -334,6 +336,7 @@ static int mptable_pass1(void); static int mptable_pass2(void); static void default_mp_table(int type); static void fix_mp_table(void); +static void setup_apic_irq_mapping(void); static void init_locks(void); static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); @@ -569,6 +572,7 @@ mp_enable(u_int boot_addr) /* post scan cleanup */ fix_mp_table(); + setup_apic_irq_mapping(); #if defined(APIC_IO) @@ -675,6 +679,7 @@ typedef struct INTDATA { u_char src_bus_irq; u_char dst_apic_id; u_char dst_apic_int; + u_char int_vector; } io_int, local_int; typedef struct BUSTYPENAME { @@ -905,8 +910,10 @@ mptable_pass2(void) bus_data[x].bus_id = 0xff; /* clear IO APIC INT table */ - for (x = 0; x < NINTR; ++x) + for (x = 0; x < NINTR; ++x) { io_apic_ints[x].int_type = 0xff; + io_apic_ints[x].int_vector = 0xff; + } /* setup the cpu/apic mapping arrays */ boot_cpu_id = -1; @@ -966,6 +973,29 @@ mptable_pass2(void) } +static void +assign_apic_irq(int apic, int intpin, int irq) +{ + int x; + + if (int_to_apicintpin[irq].ioapic != -1) + panic("assign_apic_irq: inconsistent table"); + + int_to_apicintpin[irq].ioapic = apic; + int_to_apicintpin[irq].int_pin = intpin; + int_to_apicintpin[irq].apic_address = ioapic[apic]; + int_to_apicintpin[irq].redirindex = IOAPIC_REDTBL + 2 * intpin; + + 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(apic) && + io_apic_ints[x].dst_apic_int == intpin) + io_apic_ints[x].int_vector = irq; + } +} + /* * parse an Intel MP specification table */ @@ -1041,6 +1071,50 @@ fix_mp_table(void) } +static void +setup_apic_irq_mapping(void) +{ + int x; + int int_vector; + + /* Assign low level interrupt handlers */ + 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; + } + for (x = 0; x < nintrs; x++) { + if (io_apic_ints[x].dst_apic_int <= APIC_INTMAPSIZE && + io_apic_ints[x].dst_apic_id == IO_TO_ID(0) && + io_apic_ints[x].int_vector == 0xff && + (io_apic_ints[x].int_type == 0 || + io_apic_ints[x].int_type == 3)) { + assign_apic_irq(0, + io_apic_ints[x].dst_apic_int, + io_apic_ints[x].dst_apic_int); + } + } + 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_vector == 0xff) { + assign_apic_irq(ID_TO_IO(io_apic_ints[x].dst_apic_id), + io_apic_ints[x].dst_apic_int, + int_vector); + int_vector++; + while (int_vector < APIC_INTMAPSIZE && + int_to_apicintpin[int_vector].ioapic != -1) + int_vector++; + } + } +} + + static int processor_entry(proc_entry_ptr entry, int cpu) { @@ -1164,7 +1238,7 @@ isa_apic_mask(u_int isa_mask) return 0; --isa_irq; /* make it zero based */ - apic_pin = isa_apic_pin(isa_irq); /* look for APIC connection */ + apic_pin = isa_apic_irq(isa_irq); /* look for APIC connection */ if (apic_pin == -1) return 0; @@ -1177,10 +1251,12 @@ isa_apic_mask(u_int isa_mask) */ #define INTTYPE(I) (io_apic_ints[(I)].int_type) #define INTPIN(I) (io_apic_ints[(I)].dst_apic_int) +#define INTIRQ(I) (io_apic_ints[(I)].int_vector) +#define INTAPIC(I) (ID_TO_IO(io_apic_ints[(I)].dst_apic_id)) #define SRCBUSIRQ(I) (io_apic_ints[(I)].src_bus_irq) int -isa_apic_pin(int isa_irq) +isa_apic_irq(int isa_irq) { int intr; @@ -1189,7 +1265,7 @@ isa_apic_pin(int isa_irq) if (SRCBUSIRQ(intr) == isa_irq) { if (apic_int_is_bus_type(intr, ISA) || apic_int_is_bus_type(intr, EISA)) - return INTPIN(intr); /* found */ + return INTIRQ(intr); /* found */ } } } @@ -1204,7 +1280,7 @@ isa_apic_pin(int isa_irq) #define SRCBUSDEVICE(I) ((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f) #define SRCBUSLINE(I) (io_apic_ints[(I)].src_bus_irq & 0x03) int -pci_apic_pin(int pciBus, int pciDevice, int pciInt) +pci_apic_irq(int pciBus, int pciDevice, int pciInt) { int intr; @@ -1216,13 +1292,13 @@ pci_apic_pin(int pciBus, int pciDevice, int pciInt) && (SRCBUSDEVICE(intr) == pciDevice) && (SRCBUSLINE(intr) == pciInt)) /* a candidate IRQ */ if (apic_int_is_bus_type(intr, PCI)) - return INTPIN(intr); /* exact match */ + return INTIRQ(intr); /* exact match */ return -1; /* NOT found */ } int -next_apic_pin(int pin) +next_apic_irq(int irq) { int intr, ointr; int bus, bustype; @@ -1230,7 +1306,7 @@ next_apic_pin(int pin) bus = 0; bustype = 0; for (intr = 0; intr < nintrs; intr++) { - if (INTPIN(intr) != pin || INTTYPE(intr) != 0) + if (INTIRQ(intr) != irq || INTTYPE(intr) != 0) continue; bus = SRCBUSID(intr); bustype = apic_bus_type(bus); @@ -1265,7 +1341,7 @@ next_apic_pin(int pin) if (ointr >= nintrs) { return -1; } - return INTPIN(ointr); + return INTIRQ(ointr); } #undef SRCBUSLINE #undef SRCBUSDEVICE @@ -1273,6 +1349,8 @@ next_apic_pin(int pin) #undef SRCBUSIRQ #undef INTPIN +#undef INTIRQ +#undef INTAPIC #undef INTTYPE @@ -1397,6 +1475,27 @@ apic_int_type(int apic, int pin) return -1; /* NOT found */ } +int +apic_irq(int apic, int pin) +{ + int x; + int res; + + for (x = 0; x < nintrs; ++x) + if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) && + (pin == io_apic_ints[x].dst_apic_int)) { + res = io_apic_ints[x].int_vector; + if (res == 0xff) + return -1; + if (apic != int_to_apicintpin[res].ioapic) + panic("apic_irq: inconsistent table"); + if (pin != int_to_apicintpin[res].int_pin) + panic("apic_irq inconsistent table (2)"); + return res; + } + return -1; +} + /* * given a LOGICAL APIC# and pin#, return: @@ -2127,9 +2226,11 @@ ap_init() * quite correct yet. We should have a bitfield for cpus willing * to accept TLB flush IPI's or something and sync them. */ - invltlb_ok = 1; - smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ - smp_active = 1; /* historic */ + if (smp_cpus == mp_ncpus) { + invltlb_ok = 1; + smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ + smp_active = 1; /* historic */ + } curproc = NULL; /* make sure */ } diff --git a/sys/pci/pci.c b/sys/pci/pci.c index 2dac6de36177..fceb2205e5d1 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci.c,v 1.84 1998/07/22 08:40:46 dfr Exp $ + * $Id: pci.c,v 1.85 1998/08/13 19:12:20 gibbs Exp $ * */ @@ -343,7 +343,7 @@ pci_readcfg(pcicfgregs *probe) if (cfg->intpin != 0) { int airq; - airq = pci_apic_pin(cfg->bus, cfg->slot, cfg->intpin); + airq = pci_apic_irq(cfg->bus, cfg->slot, cfg->intpin); if (airq >= 0) { /* PCI specific entry found in MP table */ if (airq != cfg->intline) { @@ -357,7 +357,7 @@ pci_readcfg(pcicfgregs *probe) * same methods as used by the ISA devices * devices to find the proper IOAPIC int pin. */ - airq = isa_apic_pin(cfg->intline); + airq = isa_apic_irq(cfg->intline); if ((airq >= 0) && (airq != cfg->intline)) { /* XXX: undirect_pci_irq() ? */ undirect_isa_irq(cfg->intline); diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c index 51e450e9651c..4dfe6fdd1317 100644 --- a/sys/pci/pci_compat.c +++ b/sys/pci/pci_compat.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci_compat.c,v 1.8 1998/07/22 08:39:08 dfr Exp $ + * $Id: pci_compat.c,v 1.9 1998/08/07 08:20:36 dfr Exp $ * */ @@ -182,7 +182,7 @@ pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr) if (error != 0) return 0; #ifdef APIC_IO - nextpin = next_apic_pin(irq); + nextpin = next_apic_irq(irq); if (nextpin < 0) return 1; @@ -196,10 +196,10 @@ pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr) */ muxcnt = 2; - nextpin = next_apic_pin(nextpin); + nextpin = next_apic_irq(nextpin); while (muxcnt < 5 && nextpin >= 0) { muxcnt++; - nextpin = next_apic_pin(nextpin); + nextpin = next_apic_irq(nextpin); } if (muxcnt >= 5) { printf("bogus MP table, more than 4 IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n"); @@ -208,7 +208,7 @@ pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr) printf("bogus MP table, %d IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n", muxcnt); - nextpin = next_apic_pin(irq); + nextpin = next_apic_irq(irq); while (nextpin >= 0) { idesc = intr_create(dev_instance, nextpin, func, arg, maskptr, 0); @@ -216,7 +216,7 @@ pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr) if (error != 0) return 0; printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq); - nextpin = next_apic_pin(nextpin); + nextpin = next_apic_irq(nextpin); } #endif } diff --git a/sys/sys/smp.h b/sys/sys/smp.h index f2586304524c..0f4f915366b6 100644 --- a/sys/sys/smp.h +++ b/sys/sys/smp.h @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: smp.h,v 1.42 1998/04/01 21:07:36 tegge Exp $ + * $Id: smp.h,v 1.43 1998/05/17 22:12:05 tegge Exp $ * */ @@ -103,6 +103,14 @@ extern u_int32_t io_apic_versions[]; extern int cpu_num_to_apic_id[]; extern int io_num_to_apic_id[]; extern int apic_id_to_logical[]; +#define APIC_INTMAPSIZE 24 +struct apic_intmapinfo { + int ioapic; + int int_pin; + volatile void *apic_address; + int redirindex; +}; +extern struct apic_intmapinfo int_to_apicintpin[]; extern u_int all_cpus; extern u_char SMP_ioapic[]; extern struct pcb stoppcbs[]; @@ -113,9 +121,10 @@ int mp_probe __P((void)); void mp_start __P((void)); void mp_announce __P((void)); u_int isa_apic_mask __P((u_int)); -int isa_apic_pin __P((int)); -int pci_apic_pin __P((int, int, int)); -int next_apic_pin __P((int)); +int isa_apic_irq __P((int)); +int pci_apic_irq __P((int, int, int)); +int apic_irq __P((int, int)); +int next_apic_irq __P((int)); int undirect_isa_irq __P((int)); int undirect_pci_irq __P((int)); int apic_bus_type __P((int)); @@ -141,12 +150,7 @@ void set_lapic_isrloc __P((int, int)); /* global data in mpapic.c */ extern volatile lapic_t lapic; - -#if defined(MULTIPLE_IOAPICS) -#error MULTIPLE_IOAPICSXXX -#else extern volatile ioapic_t *ioapic[]; -#endif /* MULTIPLE_IOAPICS */ /* functions in mpapic.c */ void apic_dump __P((char*));