summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-10-05 15:22:37 +0000
committerjhb <jhb@FreeBSD.org>2007-10-05 15:22:37 +0000
commit8d5360c01e372e48a8004e309467602ab4c55eca (patch)
treea1ca8a840d896e746e8d566df3ec4f4b681bac8e /sys/amd64
parent818361dec31495e88061ffe2312c04e835d973d5 (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/amd64/amd64/local_apic.c11
-rw-r--r--sys/amd64/amd64/mp_machdep.c87
-rw-r--r--sys/amd64/amd64/mptable.c28
-rw-r--r--sys/amd64/include/apicvar.h1
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. */
OpenPOWER on IntegriCloud