diff options
author | jhb <jhb@FreeBSD.org> | 2007-10-05 15:22:37 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2007-10-05 15:22:37 +0000 |
commit | 8d5360c01e372e48a8004e309467602ab4c55eca (patch) | |
tree | a1ca8a840d896e746e8d566df3ec4f4b681bac8e /sys/amd64 | |
parent | 818361dec31495e88061ffe2312c04e835d973d5 (diff) | |
download | FreeBSD-src-8d5360c01e372e48a8004e309467602ab4c55eca.zip FreeBSD-src-8d5360c01e372e48a8004e309467602ab4c55eca.tar.gz |
MFC: Handle CPUs with APIC IDs higher than 32.
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/acpica/madt.c | 17 | ||||
-rw-r--r-- | sys/amd64/amd64/local_apic.c | 11 | ||||
-rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 87 | ||||
-rw-r--r-- | sys/amd64/amd64/mptable.c | 28 | ||||
-rw-r--r-- | sys/amd64/include/apicvar.h | 1 |
5 files changed, 82 insertions, 62 deletions
diff --git a/sys/amd64/acpica/madt.c b/sys/amd64/acpica/madt.c index db77b74..f125cba 100644 --- a/sys/amd64/acpica/madt.c +++ b/sys/amd64/acpica/madt.c @@ -53,21 +53,18 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> #include <dev/pci/pcivar.h> -#define NIOAPICS 32 /* Max number of I/O APICs */ -#define NLAPICS 32 /* Max number of local APICs */ - typedef void madt_entry_handler(APIC_HEADER *entry, void *arg); /* These two arrays are indexed by APIC IDs. */ struct ioapic_info { void *io_apic; UINT32 io_vector; -} ioapics[NIOAPICS]; +} ioapics[MAX_APIC_ID + 1]; struct lapic_info { u_int la_enabled:1; u_int la_acpi_id:8; -} lapics[NLAPICS]; +} lapics[MAX_APIC_ID + 1]; static int madt_found_sci_override; static MULTIPLE_APIC_TABLE *madt; @@ -391,7 +388,7 @@ madt_setup_io(void) } /* Third, we register all the I/O APIC's. */ - for (i = 0; i < NIOAPICS; i++) + for (i = 0; i <= MAX_APIC_ID; i++) if (ioapics[i].io_apic != NULL) ioapic_register(ioapics[i].io_apic); @@ -447,7 +444,7 @@ madt_probe_cpus_handler(APIC_HEADER *entry, void *arg) proc->ProcessorEnabled ? "enabled" : "disabled"); if (!proc->ProcessorEnabled) break; - if (proc->LocalApicId >= NLAPICS) + if (proc->LocalApicId > MAX_APIC_ID) panic("%s: CPU ID %d too high", __func__, proc->LocalApicId); la = &lapics[proc->LocalApicId]; @@ -476,7 +473,7 @@ madt_parse_apics(APIC_HEADER *entry, void *arg __unused) printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n", apic->IoApicId, apic->Interrupt, (void *)(uintptr_t)apic->Address); - if (apic->IoApicId >= NIOAPICS) + if (apic->IoApicId > MAX_APIC_ID) panic("%s: I/O APIC ID %d too high", __func__, apic->IoApicId); if (ioapics[apic->IoApicId].io_apic != NULL) @@ -544,7 +541,7 @@ madt_find_cpu(u_int acpi_id, u_int *apic_id) { int i; - for (i = 0; i < NLAPICS; i++) { + for (i = 0; i <= MAX_APIC_ID; i++) { if (!lapics[i].la_enabled) continue; if (lapics[i].la_acpi_id != acpi_id) @@ -565,7 +562,7 @@ madt_find_interrupt(int intr, void **apic, u_int *pin) int i, best; best = -1; - for (i = 0; i < NIOAPICS; i++) { + for (i = 0; i <= MAX_APIC_ID; i++) { if (ioapics[i].io_apic == NULL || ioapics[i].io_vector > intr) continue; diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c index 7818d56..be471b0 100644 --- a/sys/amd64/amd64/local_apic.c +++ b/sys/amd64/amd64/local_apic.c @@ -65,13 +65,6 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #endif -/* - * We can handle up to 60 APICs via our logical cluster IDs, but currently - * the physical IDs on Intel processors up to the Pentium 4 are limited to - * 16. - */ -#define MAX_APICID 16 - /* Sanity checks on IDT vectors. */ CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT); CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS); @@ -114,7 +107,7 @@ struct lapic { u_long la_hard_ticks; u_long la_stat_ticks; u_long la_prof_ticks; -} static lapics[MAX_APICID]; +} static lapics[MAX_APIC_ID + 1]; /* XXX: should thermal be an NMI? */ @@ -237,7 +230,7 @@ lapic_create(u_int apic_id, int boot_cpu) { int i; - if (apic_id >= MAX_APICID) { + if (apic_id > MAX_APIC_ID) { printf("APIC: Ignoring local APIC with ID %d\n", apic_id); if (boot_cpu) panic("Can't ignore BSP"); diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 624aa3f..3aa93a7 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -133,7 +133,7 @@ struct cpu_info { int cpu_present:1; int cpu_bsp:1; int cpu_disabled:1; -} static cpu_info[MAXCPU]; +} static cpu_info[MAX_APIC_ID + 1]; static int cpu_apic_ids[MAXCPU]; /* Holds pending bitmap based IPIs per CPU */ @@ -141,6 +141,7 @@ static volatile u_int cpu_ipi_pending[MAXCPU]; static u_int boot_address; +static void assign_cpu_ids(void); static void set_interrupt_apic_ids(void); static int start_all_aps(void); static int start_ap(int apic_id); @@ -178,7 +179,7 @@ mp_topology(void) return; group = &mp_groups[0]; groups = 1; - for (cpu = 0, apic_id = 0; apic_id < MAXCPU; apic_id++) { + for (cpu = 0, apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) { if (!cpu_info[apic_id].cpu_present) continue; /* @@ -225,9 +226,8 @@ void cpu_add(u_int apic_id, char boot_cpu) { - if (apic_id >= MAXCPU) { - printf("SMP: CPU %d exceeds maximum CPU %d, ignoring\n", - apic_id, MAXCPU - 1); + if (apic_id > MAX_APIC_ID) { + panic("SMP: APIC ID %d too high", apic_id); return; } KASSERT(cpu_info[apic_id].cpu_present == 0, ("CPU %d added twice", @@ -240,13 +240,13 @@ cpu_add(u_int apic_id, char boot_cpu) boot_cpu_id = apic_id; cpu_info[apic_id].cpu_bsp = 1; } - mp_ncpus++; - if (apic_id > mp_maxid) - mp_maxid = apic_id; + if (mp_ncpus < MAXCPU) { + mp_ncpus++; + mp_maxid = mp_ncpus -1; + } if (bootverbose) printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" : "AP"); - } void @@ -265,8 +265,7 @@ cpu_mp_setmaxid(void) else KASSERT(mp_maxid >= mp_ncpus - 1, ("%s: counters out of sync: max %d, count %d", __func__, - mp_maxid, mp_ncpus)); - + mp_maxid, mp_ncpus)); } int @@ -344,6 +343,8 @@ cpu_mp_start(void) ("BSP's APIC ID doesn't match boot_cpu_id")); cpu_apic_ids[0] = boot_cpu_id; + assign_cpu_ids(); + /* Start each Application Processor */ start_all_aps(); @@ -408,7 +409,7 @@ cpu_mp_announce(void) /* List CPUs */ printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id); - for (i = 1, x = 0; x < MAXCPU; x++) { + for (i = 1, x = 0; x <= MAX_APIC_ID; x++) { if (!cpu_info[x].cpu_present || cpu_info[x].cpu_bsp) continue; if (cpu_info[x].cpu_disabled) @@ -624,6 +625,48 @@ set_interrupt_apic_ids(void) } /* + * Assign logical CPU IDs to local APICs. + */ +static void +assign_cpu_ids(void) +{ + u_int i; + + /* Check for explicitly disabled CPUs. */ + for (i = 0; i <= MAX_APIC_ID; i++) { + if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp) + continue; + + /* Don't use this CPU if it has been disabled by a tunable. */ + if (resource_disabled("lapic", i)) { + cpu_info[i].cpu_disabled = 1; + continue; + } + } + + /* + * Assign CPU IDs to local APIC IDs and disable any CPUs + * beyond MAXCPU. CPU 0 has already been assigned to the BSP, + * so we only have to assign IDs for APs. + */ + mp_ncpus = 1; + for (i = 0; i <= MAX_APIC_ID; i++) { + if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp || + cpu_info[i].cpu_disabled) + continue; + + if (mp_ncpus < MAXCPU) { + cpu_apic_ids[mp_ncpus] = i; + mp_ncpus++; + } else + cpu_info[i].cpu_disabled = 1; + } + KASSERT(mp_maxid >= mp_ncpus - 1, + ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid, + mp_ncpus)); +} + +/* * start each AP in our list */ static int @@ -674,24 +717,8 @@ start_all_aps(void) outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */ /* start each AP */ - for (cpu = 0, apic_id = 0; apic_id < MAXCPU; apic_id++) { - - /* Ignore non-existent CPUs and the BSP. */ - if (!cpu_info[apic_id].cpu_present || - cpu_info[apic_id].cpu_bsp) - continue; - - /* Don't use this CPU if it has been disabled by a tunable. */ - if (resource_disabled("lapic", apic_id)) { - cpu_info[apic_id].cpu_disabled = 1; - mp_ncpus--; - continue; - } - - cpu++; - - /* save APIC ID for this logical ID */ - cpu_apic_ids[cpu] = apic_id; + for (cpu = 1; cpu < mp_ncpus; cpu++) { + apic_id = cpu_apic_ids[cpu]; /* allocate and set up an idle stack data page */ bootstacks[cpu] = (void *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE); diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c index 5ce5c79..9b8c176 100644 --- a/sys/amd64/amd64/mptable.c +++ b/sys/amd64/amd64/mptable.c @@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$"); /* string defined by the Intel MP Spec as identifying the MP table */ #define MP_SIG 0x5f504d5f /* _MP_ */ -#define NAPICID 32 /* Max number of APIC's */ +#define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */ #define BIOS_BASE (0xf0000) #define BIOS_SIZE (0x10000) @@ -136,7 +136,7 @@ struct pci_route_interrupt_args { static mpfps_t mpfps; static mpcth_t mpct; -static void *ioapics[NAPICID]; +static void *ioapics[MAX_APIC_ID + 1]; static bus_datum *busses; static int mptable_nioapics, mptable_nbusses, mptable_maxbusid; static int pci0 = -1; @@ -152,7 +152,7 @@ static int lookup_bus_type(char *name); static void mptable_count_items(void); static void mptable_count_items_handler(u_char *entry, void *arg); #ifdef MPTABLE_FORCE_HTT -static void mptable_hyperthread_fixup(u_int id_mask); +static void mptable_hyperthread_fixup(u_long id_mask); #endif static void mptable_parse_apics_and_busses(void); static void mptable_parse_apics_and_busses_handler(u_char *entry, @@ -294,7 +294,7 @@ found: static int mptable_probe_cpus(void) { - u_int cpu_mask; + u_long cpu_mask; /* Is this a pre-defined config? */ if (mpfps->config_type != 0) { @@ -354,7 +354,7 @@ mptable_setup_io(void) mptable_parse_ints(); /* Fourth, we register all the I/O APIC's. */ - for (i = 0; i < NAPICID; i++) + for (i = 0; i <= MAX_APIC_ID; i++) if (ioapics[i] != NULL) ioapic_register(ioapics[i]); @@ -412,7 +412,7 @@ static void mptable_probe_cpus_handler(u_char *entry, void *arg) { proc_entry_ptr proc; - u_int *cpu_mask; + u_long *cpu_mask; switch (*entry) { case MPCT_ENTRY_PROCESSOR: @@ -420,8 +420,10 @@ mptable_probe_cpus_handler(u_char *entry, void *arg) if (proc->cpu_flags & PROCENTRY_FLAG_EN) { lapic_create(proc->apic_id, proc->cpu_flags & PROCENTRY_FLAG_BP); - cpu_mask = (u_int *)arg; - *cpu_mask |= (1 << proc->apic_id); + if (proc->apic_id < MAX_LAPIC_ID) { + cpu_mask = (u_long *)arg; + *cpu_mask |= (1ul << proc->apic_id); + } } break; } @@ -508,7 +510,7 @@ mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused) apic = (io_apic_entry_ptr)entry; if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN)) break; - if (apic->apic_id >= NAPICID) + if (apic->apic_id > MAX_APIC_ID) panic("%s: I/O APIC ID %d too high", __func__, apic->apic_id); if (ioapics[apic->apic_id] != NULL) @@ -653,7 +655,7 @@ mptable_parse_io_int(int_entry_ptr intr) return; } } - if (apic_id >= NAPICID) { + if (apic_id > MAX_APIC_ID) { printf("MPTable: Ignoring interrupt entry for ioapic%d\n", intr->dst_apic_id); return; @@ -866,7 +868,7 @@ mptable_parse_ints(void) * with the number of logical CPU's in the processor. */ static void -mptable_hyperthread_fixup(u_int id_mask) +mptable_hyperthread_fixup(u_long id_mask) { u_int i, id, logical_cpus; @@ -883,7 +885,7 @@ mptable_hyperthread_fixup(u_int id_mask) * physical processor. If any of those ID's are * already in the table, then kill the fixup. */ - for (id = 0; id < NAPICID; id++) { + for (id = 0; id <= MAX_LAPIC_ID; id++) { if ((id_mask & 1 << id) == 0) continue; /* First, make sure we are on a logical_cpus boundary. */ @@ -898,7 +900,7 @@ mptable_hyperthread_fixup(u_int id_mask) * Ok, the ID's checked out, so perform the fixup by * adding the logical CPUs. */ - while ((id = ffs(id_mask)) != 0) { + while ((id = ffsl(id_mask)) != 0) { id--; for (i = id + 1; i < id + logical_cpus; i++) { if (bootverbose) diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 624415c..24ecdb5 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -79,6 +79,7 @@ * I/O device! */ +#define MAX_APIC_ID 0xfe #define APIC_ID_ALL 0xff /* I/O Interrupts are used for external devices such as ISA, PCI, etc. */ |