Skip to content

Commit c8f8082

Browse files
committed
x86/xen/smp_pv: Count number of vCPUs early
XEN/PV has a completely broken vCPU enumeration scheme, which just works by chance and provides zero topology information. Each vCPU ends up being a single core package. Dom0 provides MADT which can be used for topology information, but that table is the unmodified host table, which means that there can be more CPUs registered than the number of vCPUs XEN provides for the dom0 guest. DomU does not have ACPI and both rely on counting the possible vCPUs via an hypercall. To prepare for using CPUID topology information either via MADT or via fake APIC IDs count the number of possible CPUs during early boot and adjust nr_cpu_ids() accordingly. 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.571795063@linutronix.de
1 parent ea2dd8a commit c8f8082

3 files changed

Lines changed: 19 additions & 0 deletions

File tree

arch/x86/xen/enlighten_pv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ static void __init xen_pv_init_platform(void)
200200
xen_set_mtrr_data();
201201
else
202202
mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK);
203+
204+
/* Adjust nr_cpu_ids before "enumeration" happens */
205+
xen_smp_count_cpus();
203206
}
204207

205208
static void __init xen_pv_guest_late_init(void)

arch/x86/xen/smp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern void xen_smp_intr_free(unsigned int cpu);
1919
int xen_smp_intr_init_pv(unsigned int cpu);
2020
void xen_smp_intr_free_pv(unsigned int cpu);
2121

22+
void xen_smp_count_cpus(void);
2223
void xen_smp_cpus_done(unsigned int max_cpus);
2324

2425
void xen_smp_send_reschedule(int cpu);
@@ -44,6 +45,7 @@ static inline int xen_smp_intr_init_pv(unsigned int cpu)
4445
return 0;
4546
}
4647
static inline void xen_smp_intr_free_pv(unsigned int cpu) {}
48+
static inline void xen_smp_count_cpus(void) { }
4749
#endif /* CONFIG_SMP */
4850

4951
#endif

arch/x86/xen/smp_pv.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,20 @@ static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
411411
return IRQ_HANDLED;
412412
}
413413

414+
void __init xen_smp_count_cpus(void)
415+
{
416+
unsigned int cpus;
417+
418+
for (cpus = 0; cpus < nr_cpu_ids; cpus++) {
419+
if (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpus, NULL) < 0)
420+
break;
421+
}
422+
423+
pr_info("Xen PV: Detected %u vCPUS\n", cpus);
424+
if (cpus < nr_cpu_ids)
425+
set_nr_cpu_ids(cpus);
426+
}
427+
414428
static const struct smp_ops xen_smp_ops __initconst = {
415429
.smp_prepare_boot_cpu = xen_pv_smp_prepare_boot_cpu,
416430
.smp_prepare_cpus = xen_pv_smp_prepare_cpus,

0 commit comments

Comments
 (0)