Skip to content

Commit ec9aedb

Browse files
zhang-ruiKAGA-KOKO
authored andcommitted
x86/acpi: Ignore invalid x2APIC entries
Currently, the kernel enumerates the possible CPUs by parsing both ACPI MADT Local APIC entries and x2APIC entries. So CPUs with "valid" APIC IDs, even if they have duplicated APIC IDs in Local APIC and x2APIC, are always enumerated. Below is what ACPI MADT Local APIC and x2APIC describes on an Ivebridge-EP system, [02Ch 0044 1] Subtable Type : 00 [Processor Local APIC] [02Fh 0047 1] Local Apic ID : 00 ... [164h 0356 1] Subtable Type : 00 [Processor Local APIC] [167h 0359 1] Local Apic ID : 39 [16Ch 0364 1] Subtable Type : 00 [Processor Local APIC] [16Fh 0367 1] Local Apic ID : FF ... [3ECh 1004 1] Subtable Type : 09 [Processor Local x2APIC] [3F0h 1008 4] Processor x2Apic ID : 00000000 ... [B5Ch 2908 1] Subtable Type : 09 [Processor Local x2APIC] [B60h 2912 4] Processor x2Apic ID : 00000077 As a result, kernel shows "smpboot: Allowing 168 CPUs, 120 hotplug CPUs". And this wastes significant amount of memory for the per-cpu data. Plus this also breaks https://lore.kernel.org/all/87edm36qqb.ffs@tglx/, because __max_logical_packages is over-estimated by the APIC IDs in the x2APIC entries. According to https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#processor-local-x2apic-structure: "[Compatibility note] On some legacy OSes, Logical processors with APIC ID values less than 255 (whether in XAPIC or X2APIC mode) must use the Processor Local APIC structure to convey their APIC information to OSPM, and those processors must be declared in the DSDT using the Processor() keyword. Logical processors with APIC ID values 255 and greater must use the Processor Local x2APIC structure and be declared using the Device() keyword." Therefore prevent the registration of x2APIC entries with an APIC ID less than 255 if the local APIC table enumerates valid APIC IDs. [ tglx: Simplify the logic ] Signed-off-by: Zhang Rui <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Peter Zijlstra <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 31255e0 commit ec9aedb

File tree

1 file changed

+15
-19
lines changed

1 file changed

+15
-19
lines changed

arch/x86/kernel/acpi/boot.c

+15-19
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ int acpi_fix_pin2_polarity __initdata;
6363

6464
#ifdef CONFIG_X86_LOCAL_APIC
6565
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
66+
static bool has_lapic_cpus __initdata;
6667
static bool acpi_support_online_capable;
6768
#endif
6869

@@ -232,6 +233,14 @@ acpi_parse_x2apic(union acpi_subtable_headers *header, const unsigned long end)
232233
if (!acpi_is_processor_usable(processor->lapic_flags))
233234
return 0;
234235

236+
/*
237+
* According to https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#processor-local-x2apic-structure
238+
* when MADT provides both valid LAPIC and x2APIC entries, the APIC ID
239+
* in x2APIC must be equal or greater than 0xff.
240+
*/
241+
if (has_lapic_cpus && apic_id < 0xff)
242+
return 0;
243+
235244
/*
236245
* We need to register disabled CPU as well to permit
237246
* counting disabled CPUs. This allows us to size
@@ -1114,10 +1123,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
11141123

11151124
static int __init acpi_parse_madt_lapic_entries(void)
11161125
{
1117-
int count;
1118-
int x2count = 0;
1119-
int ret;
1120-
struct acpi_subtable_proc madt_proc[2];
1126+
int count, x2count = 0;
11211127

11221128
if (!boot_cpu_has(X86_FEATURE_APIC))
11231129
return -ENODEV;
@@ -1126,21 +1132,11 @@ static int __init acpi_parse_madt_lapic_entries(void)
11261132
acpi_parse_sapic, MAX_LOCAL_APIC);
11271133

11281134
if (!count) {
1129-
memset(madt_proc, 0, sizeof(madt_proc));
1130-
madt_proc[0].id = ACPI_MADT_TYPE_LOCAL_APIC;
1131-
madt_proc[0].handler = acpi_parse_lapic;
1132-
madt_proc[1].id = ACPI_MADT_TYPE_LOCAL_X2APIC;
1133-
madt_proc[1].handler = acpi_parse_x2apic;
1134-
ret = acpi_table_parse_entries_array(ACPI_SIG_MADT,
1135-
sizeof(struct acpi_table_madt),
1136-
madt_proc, ARRAY_SIZE(madt_proc), MAX_LOCAL_APIC);
1137-
if (ret < 0) {
1138-
pr_err("Error parsing LAPIC/X2APIC entries\n");
1139-
return ret;
1140-
}
1141-
1142-
count = madt_proc[0].count;
1143-
x2count = madt_proc[1].count;
1135+
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
1136+
acpi_parse_lapic, MAX_LOCAL_APIC);
1137+
has_lapic_cpus = count > 0;
1138+
x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
1139+
acpi_parse_x2apic, MAX_LOCAL_APIC);
11441140
}
11451141
if (!count && !x2count) {
11461142
pr_err("No LAPIC entries present\n");

0 commit comments

Comments
 (0)