The number of available APIC IDs depends on chosen topology, because core/smt choices different from a power of two waste some IDs.
Signed-off-by: Radim Krčmář <rkrc...@redhat.com> --- target-i386/cpu.c | 16 ++++++++++++++++ target-i386/cpu.h | 1 + 2 files changed, 17 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e194601..c77ec76 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2815,6 +2815,22 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } +/* The number of useable APIC IDs based on current topology. + * + * id_limit is the highest possible APIC ID + 1. + */ +unsigned x86_cpu_nr_apic_ids(unsigned id_limit) +{ + unsigned package_width; + + if (compat_apic_id_mode) + return id_limit; + + package_width = apicid_pkg_width(smp_cores, smp_threads, id_limit); + + return MIN(id_limit, (1 << package_width) * smp_cores * smp_threads); +} + static void x86_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 9f01831..367968d 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1372,6 +1372,7 @@ void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features); const char *get_register_name_32(unsigned int reg); uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index); +unsigned x86_cpu_nr_apic_ids(unsigned id_limit); void enable_compat_apic_id_mode(void); #define APIC_DEFAULT_ADDRESS 0xfee00000 -- 2.1.0