Skip to content

Commit 354da4c

Browse files
committed
x86/cpu/topology: Let XEN/PV use topology from CPUID/MADT
It turns out that XEN/PV Dom0 has halfways usable CPUID/MADT enumeration except that it cannot deal with CPUs which are enumerated as disabled in MADT. DomU has no MADT and provides at least rudimentary topology information in CPUID leaves 1 and 4. For both it's important that there are not more possible Linux CPUs than vCPUs provided by the hypervisor. As this is ensured by counting the vCPUs before enumeration happens: - lift the restrictions in the CPUID evaluation and the MADT parser - Utilize MADT registration for Dom0 - Keep the fake APIC ID registration for DomU - Fix the XEN APIC fake so the readout of the local APIC ID works for Dom0 via the hypercall and for DomU by returning the registered fake APIC IDs. With that the XEN/PV fake approximates usefulness. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Michael Kelley <mhklinux@outlook.com> Tested-by: Sohil Mehta <sohil.mehta@intel.com> Link: https://lore.kernel.org/r/20240213210252.626195405@linutronix.de
1 parent c8f8082 commit 354da4c

4 files changed

Lines changed: 24 additions & 30 deletions

File tree

arch/x86/kernel/acpi/boot.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
#include <linux/serial_core.h>
2424
#include <linux/pgtable.h>
2525

26-
#include <xen/xen.h>
27-
2826
#include <asm/e820/api.h>
2927
#include <asm/irqdomain.h>
3028
#include <asm/pci_x86.h>
@@ -166,12 +164,6 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
166164
return 0;
167165
}
168166

169-
static __init void acpi_register_lapic(u32 apic_id, u32 acpi_id, bool present)
170-
{
171-
if (!xen_pv_domain())
172-
topology_register_apic(apic_id, acpi_id, present);
173-
}
174-
175167
static bool __init acpi_is_processor_usable(u32 lapic_flags)
176168
{
177169
if (lapic_flags & ACPI_MADT_ENABLED)
@@ -233,7 +225,7 @@ acpi_parse_x2apic(union acpi_subtable_headers *header, const unsigned long end)
233225
return 0;
234226
}
235227

236-
acpi_register_lapic(apic_id, processor->uid, enabled);
228+
topology_register_apic(apic_id, processor->uid, enabled);
237229
#else
238230
pr_warn("x2apic entry ignored\n");
239231
#endif
@@ -268,9 +260,9 @@ acpi_parse_lapic(union acpi_subtable_headers * header, const unsigned long end)
268260
* to not preallocating memory for all NR_CPUS
269261
* when we use CPU hotplug.
270262
*/
271-
acpi_register_lapic(processor->id, /* APIC ID */
272-
processor->processor_id, /* ACPI ID */
273-
processor->lapic_flags & ACPI_MADT_ENABLED);
263+
topology_register_apic(processor->id, /* APIC ID */
264+
processor->processor_id, /* ACPI ID */
265+
processor->lapic_flags & ACPI_MADT_ENABLED);
274266

275267
has_lapic_cpus = true;
276268
return 0;
@@ -288,9 +280,9 @@ acpi_parse_sapic(union acpi_subtable_headers *header, const unsigned long end)
288280

289281
acpi_table_print_madt_entry(&header->common);
290282

291-
acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
292-
processor->processor_id, /* ACPI ID */
293-
processor->lapic_flags & ACPI_MADT_ENABLED);
283+
topology_register_apic((processor->id << 8) | processor->eid,/* APIC ID */
284+
processor->processor_id, /* ACPI ID */
285+
processor->lapic_flags & ACPI_MADT_ENABLED);
294286

295287
return 0;
296288
}
@@ -1090,8 +1082,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
10901082
return count;
10911083
}
10921084

1093-
if (!xen_pv_domain())
1094-
register_lapic_address(acpi_lapic_addr);
1085+
register_lapic_address(acpi_lapic_addr);
10951086

10961087
return count;
10971088
}

arch/x86/kernel/cpu/topology_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static bool fake_topology(struct topo_scan *tscan)
7777
topology_set_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
7878
topology_set_dom(tscan, TOPO_CORE_DOMAIN, 0, 1);
7979

80-
return tscan->c->cpuid_level < 1 || xen_pv_domain();
80+
return tscan->c->cpuid_level < 1;
8181
}
8282

8383
static void parse_topology(struct topo_scan *tscan, bool early)

arch/x86/xen/apic.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,20 @@ static u32 xen_apic_read(u32 reg)
4343
struct xen_platform_op op = {
4444
.cmd = XENPF_get_cpuinfo,
4545
.interface_version = XENPF_INTERFACE_VERSION,
46-
.u.pcpu_info.xen_cpuid = 0,
4746
};
48-
int ret;
49-
50-
/* Shouldn't need this as APIC is turned off for PV, and we only
51-
* get called on the bootup processor. But just in case. */
52-
if (!xen_initial_domain() || smp_processor_id())
53-
return 0;
47+
int ret, cpu;
5448

5549
if (reg == APIC_LVR)
5650
return 0x14;
5751
if (reg != APIC_ID)
5852
return 0;
5953

54+
cpu = smp_processor_id();
55+
if (!xen_initial_domain())
56+
return cpu ? cpuid_to_apicid[cpu] << 24 : 0;
57+
58+
op.u.pcpu_info.xen_cpuid = cpu;
59+
6060
ret = HYPERVISOR_platform_op(&op);
6161
if (ret)
6262
op.u.pcpu_info.apic_id = BAD_APICID;

arch/x86/xen/smp_pv.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,9 @@ static void __init xen_pv_smp_config(void)
156156

157157
topology_register_boot_apic(apicid++);
158158

159-
for (i = 1; i < nr_cpu_ids; i++) {
160-
if (HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL) < 0)
161-
break;
159+
for (i = 1; i < nr_cpu_ids; i++)
162160
topology_register_apic(apicid++, CPU_ACPIID_INVALID, true);
163-
}
161+
164162
/* Pretend to be a proper enumerated system */
165163
smp_found_config = 1;
166164
}
@@ -451,5 +449,10 @@ void __init xen_smp_init(void)
451449
/* Avoid searching for BIOS MP tables */
452450
x86_init.mpparse.find_mptable = x86_init_noop;
453451
x86_init.mpparse.early_parse_smp_cfg = x86_init_noop;
454-
x86_init.mpparse.parse_smp_cfg = xen_pv_smp_config;
452+
453+
/* XEN/PV Dom0 has halfways sane topology information via CPUID/MADT */
454+
if (xen_initial_domain())
455+
x86_init.mpparse.parse_smp_cfg = x86_init_noop;
456+
else
457+
x86_init.mpparse.parse_smp_cfg = xen_pv_smp_config;
455458
}

0 commit comments

Comments
 (0)