Handle CPUs with APIC IDs higher than 32 (at least one IBM server uses
an APIC ID of 38 for its second CPU): - Add a new MAX_APIC_ID constant for the highest valid APIC ID for modern systems. - Size the various arrays in the MADT, MP Table, and SMP code that are indexed by APIC IDs to allow for up to MAX_APIC_ID. - Explicitly go through and assign logical cpu ids to local APICs before starting any of the APs up rather than doing it while starting up the APs. This step is now where we honor MAXCPU. MFC after: 1 week
This commit is contained in:
parent
7b6b99abf6
commit
255387b6b7
@ -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(ACPI_SUBTABLE_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 ACPI_TABLE_MADT *madt;
|
||||
@ -393,7 +390,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);
|
||||
|
||||
@ -450,7 +447,7 @@ madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
|
||||
"enabled" : "disabled");
|
||||
if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
|
||||
break;
|
||||
if (proc->Id >= NLAPICS)
|
||||
if (proc->Id > MAX_APIC_ID)
|
||||
panic("%s: CPU ID %u too high", __func__, proc->Id);
|
||||
la = &lapics[proc->Id];
|
||||
KASSERT(la->la_enabled == 0,
|
||||
@ -479,7 +476,7 @@ madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
|
||||
"MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
|
||||
apic->Id, apic->GlobalIrqBase,
|
||||
(void *)(uintptr_t)apic->Address);
|
||||
if (apic->Id >= NIOAPICS)
|
||||
if (apic->Id > MAX_APIC_ID)
|
||||
panic("%s: I/O APIC ID %u too high", __func__,
|
||||
apic->Id);
|
||||
if (ioapics[apic->Id].io_apic != NULL)
|
||||
@ -545,7 +542,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)
|
||||
@ -566,7 +563,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;
|
||||
|
@ -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? */
|
||||
|
||||
@ -240,7 +233,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");
|
||||
|
@ -151,7 +151,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];
|
||||
int cpu_apic_ids[MAXCPU];
|
||||
|
||||
/* Holds pending bitmap based IPIs per CPU */
|
||||
@ -159,6 +159,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);
|
||||
@ -204,7 +205,7 @@ mp_topology(void)
|
||||
}
|
||||
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;
|
||||
/*
|
||||
@ -246,9 +247,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",
|
||||
@ -261,13 +261,13 @@ cpu_add(u_int apic_id, char boot_cpu)
|
||||
boot_cpu_id = apic_id;
|
||||
cpu_info[apic_id].cpu_bsp = 1;
|
||||
}
|
||||
if (mp_ncpus < MAXCPU) {
|
||||
mp_ncpus++;
|
||||
if (apic_id > mp_maxid)
|
||||
mp_maxid = apic_id;
|
||||
mp_maxid = mp_ncpus -1;
|
||||
}
|
||||
if (bootverbose)
|
||||
printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
|
||||
"AP");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -287,7 +287,6 @@ cpu_mp_setmaxid(void)
|
||||
KASSERT(mp_maxid >= mp_ncpus - 1,
|
||||
("%s: counters out of sync: max %d, count %d", __func__,
|
||||
mp_maxid, mp_ncpus));
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -365,6 +364,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();
|
||||
|
||||
@ -429,7 +430,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)
|
||||
@ -645,6 +646,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
|
||||
*/
|
||||
@ -696,24 +739,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);
|
||||
|
@ -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) {
|
||||
@ -356,7 +356,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]);
|
||||
|
||||
@ -414,7 +414,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:
|
||||
@ -422,8 +422,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;
|
||||
}
|
||||
@ -510,7 +512,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)
|
||||
@ -655,7 +657,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;
|
||||
@ -868,7 +870,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;
|
||||
|
||||
@ -885,7 +887,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. */
|
||||
@ -900,7 +902,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)
|
||||
|
@ -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. */
|
||||
|
@ -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(ACPI_SUBTABLE_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 ACPI_TABLE_MADT *madt;
|
||||
@ -393,7 +390,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);
|
||||
|
||||
@ -449,7 +446,7 @@ madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
|
||||
"enabled" : "disabled");
|
||||
if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
|
||||
break;
|
||||
if (proc->Id >= NLAPICS)
|
||||
if (proc->Id > MAX_APIC_ID)
|
||||
panic("%s: CPU ID %u too high", __func__, proc->Id);
|
||||
la = &lapics[proc->Id];
|
||||
KASSERT(la->la_enabled == 0,
|
||||
@ -478,7 +475,7 @@ madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
|
||||
"MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
|
||||
apic->Id, apic->GlobalIrqBase,
|
||||
(void *)(uintptr_t)apic->Address);
|
||||
if (apic->Id >= NIOAPICS)
|
||||
if (apic->Id > MAX_APIC_ID)
|
||||
panic("%s: I/O APIC ID %u too high", __func__,
|
||||
apic->Id);
|
||||
if (ioapics[apic->Id].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;
|
||||
|
@ -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? */
|
||||
|
||||
@ -242,7 +235,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");
|
||||
|
@ -208,7 +208,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];
|
||||
int cpu_apic_ids[MAXCPU];
|
||||
|
||||
/* Holds pending bitmap based IPIs per CPU */
|
||||
@ -216,9 +216,10 @@ static volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
static u_int boot_address;
|
||||
|
||||
static void assign_cpu_ids(void);
|
||||
static void install_ap_tramp(void);
|
||||
static void set_interrupt_apic_ids(void);
|
||||
static int start_all_aps(void);
|
||||
static void install_ap_tramp(void);
|
||||
static int start_ap(int apic_id);
|
||||
static void release_aps(void *dummy);
|
||||
|
||||
@ -261,7 +262,7 @@ mp_topology(void)
|
||||
}
|
||||
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;
|
||||
/*
|
||||
@ -301,9 +302,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",
|
||||
@ -316,11 +316,11 @@ cpu_add(u_int apic_id, char boot_cpu)
|
||||
boot_cpu_id = apic_id;
|
||||
cpu_info[apic_id].cpu_bsp = 1;
|
||||
}
|
||||
if (mp_ncpus < MAXCPU)
|
||||
mp_ncpus++;
|
||||
if (bootverbose)
|
||||
printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
|
||||
"AP");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -415,6 +415,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();
|
||||
|
||||
@ -479,7 +481,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)
|
||||
@ -698,6 +700,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
|
||||
*/
|
||||
@ -734,24 +778,8 @@ start_all_aps(void)
|
||||
invltlb();
|
||||
|
||||
/* 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];
|
||||
|
||||
/* first page of AP's private space */
|
||||
pg = cpu * i386_btop(sizeof(struct privatespace));
|
||||
|
@ -51,7 +51,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 31 /* Max local APIC ID for HTT fixup */
|
||||
|
||||
#ifdef PC98
|
||||
#define BIOS_BASE (0xe8000)
|
||||
@ -142,7 +142,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;
|
||||
@ -361,7 +361,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]);
|
||||
|
||||
@ -427,8 +427,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);
|
||||
if (proc->apic_id < MAX_LAPIC_ID) {
|
||||
cpu_mask = (u_int *)arg;
|
||||
*cpu_mask |= (1 << proc->apic_id);
|
||||
*cpu_mask |= (1ul << proc->apic_id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -515,7 +517,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)
|
||||
@ -664,7 +666,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;
|
||||
@ -894,7 +896,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. */
|
||||
|
@ -77,6 +77,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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user