Extract Local APIC IDs directly from the CPUs, and instead of check for "i < CountCPUs", check if the APIC ID was present on boot, when building ACPI tables and the MP-Table.
This keeps ACPI Processor ID == APIC ID, but allows the hardware<->Seabios interface be completely APIC-ID based, and Seabios may change the way ACPI Processor IDs are chosen in the future.
As we currently Seabios support only xAPIC and not x2APIC, the list of present-on-boot APIC IDs is a 256-bit bitmap. If one day Seabios starts to support x2APIC, the data structure used to enumerate the APIC IDs will have to be changed.
Signed-off-by: Eduardo Habkost ehabkost@redhat.com --- src/acpi-dsdt.dsl | 4 +++- src/acpi.c | 9 +++++---- src/mptable.c | 2 +- src/smp.c | 17 +++++++++++++++++ src/util.h | 1 + 5 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl index 2060686..72dc7d8 100644 --- a/src/acpi-dsdt.dsl +++ b/src/acpi-dsdt.dsl @@ -676,6 +676,7 @@ DefinitionBlock ( /* Methods called by run-time generated SSDT Processor objects */ Method (CPMA, 1, NotSerialized) { // _MAT method - create an madt apic buffer + // Arg0 = Processor ID = Local APIC ID // Local0 = CPON flag for this cpu Store(DerefOf(Index(CPON, Arg0)), Local0) // Local1 = Buffer (in madt apic form) to return @@ -688,6 +689,7 @@ DefinitionBlock ( } Method (CPST, 1, NotSerialized) { // _STA method - return ON status of cpu + // Arg0 = Processor ID = Local APIC ID // Local0 = CPON flag for this cpu Store(DerefOf(Index(CPON, Arg0)), Local0) If (Local0) { Return(0xF) } Else { Return(0x0) } @@ -708,7 +710,7 @@ DefinitionBlock ( Store (PRS, Local5) // Local2 = last read byte from bitmap Store (Zero, Local2) - // Local0 = cpuid iterator + // Local0 = Processor ID / APIC ID iterator Store (Zero, Local0) While (LLess(Local0, SizeOf(CPON))) { // Local1 = CPON flag for this cpu diff --git a/src/acpi.c b/src/acpi.c index 3f55de9..d79a1e9 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -326,7 +326,7 @@ build_madt(void) apic->length = sizeof(*apic); apic->processor_id = i; apic->local_apic_id = i; - if (i < CountCPUs) + if (apic_id_is_present(apic->local_apic_id)) apic->flags = cpu_to_le32(1); else apic->flags = cpu_to_le32(0); @@ -444,6 +444,7 @@ build_ssdt(void) }
// build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" + // Arg0 = Processor ID = APIC ID *(ssdt_ptr++) = 0x14; // MethodOp ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2); *(ssdt_ptr++) = 'N'; @@ -476,7 +477,7 @@ build_ssdt(void) ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2); *(ssdt_ptr++) = acpi_cpus; for (i=0; i<acpi_cpus; i++) - *(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00; + *(ssdt_ptr++) = (apic_id_is_present(i)) ? 0x01 : 0x00;
// store pci io windows: start, end, length // this way we don't have to do the math in the dsdt @@ -655,10 +656,10 @@ build_srat(void) core->proximity_lo = curnode; memset(core->proximity_hi, 0, 3); core->local_sapic_eid = 0; - if (i < CountCPUs) + if (apic_id_is_present(i)) core->flags = cpu_to_le32(1); else - core->flags = 0; + core->flags = cpu_to_le32(0); core++; }
diff --git a/src/mptable.c b/src/mptable.c index 103f462..9406f98 100644 --- a/src/mptable.c +++ b/src/mptable.c @@ -59,7 +59,7 @@ mptable_init(void) cpu->apicid = i; cpu->apicver = apic_version; /* cpu flags: enabled, bootstrap cpu */ - cpu->cpuflag = ((i<CountCPUs) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00); + cpu->cpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00); cpu->cpusignature = cpuid_signature; cpu->featureflag = cpuid_features; cpu++; diff --git a/src/smp.c b/src/smp.c index 8c077a1..af92e4a 100644 --- a/src/smp.c +++ b/src/smp.c @@ -36,6 +36,8 @@ wrmsr_smp(u32 index, u64 val)
u32 CountCPUs VAR16VISIBLE; u32 MaxCountCPUs VAR16VISIBLE; +// 256 bits for the found APIC IDs +u32 FoundAPICIDs[256/32] VAR16VISIBLE; extern void smp_ap_boot_code(void); ASM16( " .global smp_ap_boot_code\n" @@ -59,6 +61,12 @@ ASM16( " jmp 1b\n" "2:\n"
+ // get apic ID on EBX, set bit on FoundAPICIDs + " mov $1, %eax\n" + " cpuid\n" + " shrl $24, %ebx\n" + " lock bts %ebx, FoundAPICIDs\n" + // Increment the cpu counter " lock incl CountCPUs\n"
@@ -67,6 +75,11 @@ ASM16( " jmp 1b\n" );
+int apic_id_is_present(u8 apic_id) +{ + return FoundAPICIDs[apic_id/32] & (1 << (apic_id % 32)); +} + // find and initialize the CPUs by launching a SIPI to them void smp_probe(void) @@ -82,6 +95,10 @@ smp_probe(void) return; }
+ // mark the BSP initial APIC ID as found, too: + u8 apic_id = ebx>>24; + FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32)); + // Init the counter. writel(&CountCPUs, 1);
diff --git a/src/util.h b/src/util.h index ef8ec7c..89e928c 100644 --- a/src/util.h +++ b/src/util.h @@ -355,6 +355,7 @@ extern u32 CountCPUs; extern u32 MaxCountCPUs; void wrmsr_smp(u32 index, u64 val); void smp_probe(void); +int apic_id_is_present(u8 apic_id);
// coreboot.c extern const char *CBvendor, *CBpart;