[SeaBIOS] [seabios PATCH 2/2] allow CPUs to have non-contiguous Local APIC IDs
Eduardo Habkost
ehabkost at redhat.com
Thu Jul 19 22:52:42 CEST 2012
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 at 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;
--
1.7.10.4
More information about the SeaBIOS
mailing list