diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index 77364fd728..08261edf17 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -415,6 +415,22 @@ void __init early_cpu_init(bool verbose) initialize_cpu_data(0); } +void reset_cpuinfo(struct cpuinfo_x86 *c, bool keep_basic) +{ + if ( !keep_basic ) + { + c->x86_vendor = 0; + c->x86 = 0; + c->x86_model = 0; + c->x86_mask = 0; + memset(&c->x86_capability, 0, sizeof(c->x86_capability)); + memset(&c->x86_vendor_id, 0, sizeof(c->x86_vendor_id)); + memset(&c->x86_model_id, 0, sizeof(c->x86_model_id)); + } + + CPU_DATA_INIT((*c)); +} + static void generic_identify(struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx, tmp; @@ -522,16 +538,7 @@ void identify_cpu(struct cpuinfo_x86 *c) { int i; - c->x86_cache_size = -1; - c->x86_model = c->x86_mask = 0; /* So far unknown... */ - c->x86_model_id[0] = '\0'; /* Unset */ - c->x86_max_cores = 1; - c->x86_num_siblings = 1; - c->x86_clflush_size = 0; - c->cpu_core_id = XEN_INVALID_CORE_ID; - c->compute_unit_id = INVALID_CUID; - memset(&c->x86_capability, 0, sizeof c->x86_capability); - + reset_cpuinfo(c, false); generic_identify(c); #ifdef NOISY_CAPS diff --git a/xen/arch/x86/include/asm/cpufeature.h b/xen/arch/x86/include/asm/cpufeature.h index 3c2ac964e4..56d6ed1a87 100644 --- a/xen/arch/x86/include/asm/cpufeature.h +++ b/xen/arch/x86/include/asm/cpufeature.h @@ -41,6 +41,24 @@ struct cpuinfo_x86 { unsigned short x86_clflush_size; } __cacheline_aligned; +#define CPU_DATA_INIT(what...) \ + what.cpuid_level = 1, \ + what.extended_cpuid_level = 0, \ + what.x86_cache_size = -1, \ + what.x86_max_cores = 1, \ + what.x86_num_siblings = 1, \ + what.apicid = BAD_APICID, \ + what.phys_proc_id = XEN_INVALID_SOCKET_ID, \ + what.cpu_core_id = XEN_INVALID_CORE_ID, \ + what.compute_unit_id = INVALID_CUID + +/* + * @keep_basic set to true retains data firmly assumed to be symmetric + * across all CPUs. With it set to false only CPU_DATA_INIT() will be + * invoked on the passed structure. + */ +void reset_cpuinfo(struct cpuinfo_x86 *c, bool keep_basic); + extern struct cpuinfo_x86 boot_cpu_data; static inline bool cpu_has(const struct cpuinfo_x86 *info, unsigned int feat) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 24e4f5ac7f..c6890669b9 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -178,7 +178,7 @@ void *stack_start = cpu0_stack + STACK_SIZE - sizeof(struct cpu_info); /* Used by the boot asm and EFI to stash the multiboot_info paddr. */ unsigned int __initdata multiboot_ptr; -struct cpuinfo_x86 __read_mostly boot_cpu_data = { 0, 0, 0, 0, -1 }; +struct cpuinfo_x86 __read_mostly boot_cpu_data = { CPU_DATA_INIT() }; unsigned long __read_mostly mmu_cr4_features = XEN_MINIMAL_CR4; diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index a90caf45a5..25bdd98fcf 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -69,7 +69,8 @@ unsigned int __read_mostly nr_sockets; cpumask_t **__read_mostly socket_cpumask; static cpumask_t *secondary_socket_cpumask; -struct cpuinfo_x86 cpu_data[NR_CPUS]; +struct cpuinfo_x86 __read_mostly cpu_data[NR_CPUS] = + { [0 ... NR_CPUS - 1] = { CPU_DATA_INIT() } }; u32 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; @@ -89,7 +90,12 @@ void *stack_base[NR_CPUS]; void initialize_cpu_data(unsigned int cpu) { - cpu_data[cpu] = boot_cpu_data; + struct cpuinfo_x86 c = boot_cpu_data; + + /* Must not partially clear the BSP's collected data. */ + if ( cpu || system_state > SYS_STATE_smp_boot ) + reset_cpuinfo(&c, true); + cpu_data[cpu] = c; } static bool smp_store_cpu_info(unsigned int id) @@ -968,9 +974,7 @@ static void cpu_smpboot_free(unsigned int cpu, bool remove) if ( remove ) { - c[cpu].phys_proc_id = XEN_INVALID_SOCKET_ID; - c[cpu].cpu_core_id = XEN_INVALID_CORE_ID; - c[cpu].compute_unit_id = INVALID_CUID; + reset_cpuinfo(&c[cpu], false); FREE_CPUMASK_VAR(per_cpu(cpu_sibling_mask, cpu)); FREE_CPUMASK_VAR(per_cpu(cpu_core_mask, cpu));