Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:Update
xen
58f78b61-x86-move-ucode-loading-earlier.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 58f78b61-x86-move-ucode-loading-earlier.patch of Package xen
# Commit f97838bbd980a0104e16c4a12fbf514f9fa805f1 # Date 2017-04-19 17:08:01 +0100 # Author Ross Lagerwall <ross.lagerwall@citrix.com> # Committer Andrew Cooper <andrew.cooper3@citrix.com> x86: Move microcode loading earlier Move microcode loading earlier for the boot CPU and secondary CPUs so that it takes place before identify_cpu() is called for each CPU. Without this, the detected features may be wrong if the new microcode loading adjusts the feature bits. That could mean that some fixes (e.g. d6e9f8d4f35d ("x86/vmx: fix vmentry failure with TSX bits in LBR")) don't work as expected. Previously during boot, the microcode loader was invoked for each secondary CPU started and then again for each CPU as part of an initcall. Simplify the code so that it is invoked exactly once for each CPU during boot. Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Tested-by: Andrew Cooper <andrew.cooper3@citrix.com> --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -32,7 +32,6 @@ obj-y += ioport_emulate.o obj-y += irq.o obj-y += microcode_amd.o obj-y += microcode_intel.o -# This must come after the vendor specific files. obj-y += microcode.o obj-y += mm.o obj-y += mpparse.o --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -192,6 +192,8 @@ static void __init early_cpu_detect(void /* Leaf 0x1 capabilities filled in early for Xen. */ c->x86_capability[0] = cap0; c->x86_capability[4] = cap4; + + initialize_cpu_data(0); } static void __cpuinit generic_identify(struct cpuinfo_x86 *c) --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -44,7 +44,6 @@ static module_t __initdata ucode_mod; static void *(*__initdata ucode_mod_map)(const module_t *); static signed int __initdata ucode_mod_idx; static bool_t __initdata ucode_mod_forced; -static cpumask_t __initdata init_mask; /* * If we scan the initramfs.cpio for the early microcode code @@ -342,50 +341,23 @@ int microcode_update(XEN_GUEST_HANDLE_PA return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); } -static void __init _do_microcode_update(unsigned long data) -{ - void *_data = (void *)data; - size_t len = ucode_blob.size ? ucode_blob.size : ucode_mod.mod_end; - - microcode_update_cpu(_data, len); - cpumask_set_cpu(smp_processor_id(), &init_mask); -} - static int __init microcode_init(void) { - void *data; - static struct tasklet __initdata tasklet; - unsigned int cpu; - - if ( !microcode_ops ) - return 0; - - if ( !ucode_mod.mod_end && !ucode_blob.size ) - return 0; - - data = ucode_blob.size ? ucode_blob.data : ucode_mod_map(&ucode_mod); - - if ( !data ) - return -ENOMEM; - - if ( microcode_ops->start_update && microcode_ops->start_update() != 0 ) - goto out; - - softirq_tasklet_init(&tasklet, _do_microcode_update, (unsigned long)data); - - for_each_online_cpu ( cpu ) + /* + * At this point, all CPUs should have updated their microcode + * via the early_microcode_* paths so free the microcode blob. + */ + if ( ucode_blob.size ) { - tasklet_schedule_on_cpu(&tasklet, cpu); - do { - process_pending_softirqs(); - } while ( !cpumask_test_cpu(cpu, &init_mask) ); + xfree(ucode_blob.data); + ucode_blob.size = 0; + ucode_blob.data = NULL; } - -out: - if ( ucode_blob.size ) - xfree(data); - else + else if ( ucode_mod.mod_end ) + { ucode_mod_map(NULL); + ucode_mod.mod_end = 0; + } return 0; } @@ -410,50 +382,55 @@ static struct notifier_block microcode_p .notifier_call = microcode_percpu_callback, }; -static int __init microcode_presmp_init(void) +int __init early_microcode_update_cpu(bool_t start_update) +{ + int rc = 0; + void *data = NULL; + size_t len; + + if ( ucode_blob.size ) + { + len = ucode_blob.size; + data = ucode_blob.data; + } + else if ( ucode_mod.mod_end ) + { + len = ucode_mod.mod_end; + data = ucode_mod_map(&ucode_mod); + } + if ( data ) + { + if ( start_update && microcode_ops->start_update ) + rc = microcode_ops->start_update(); + + if ( rc ) + return rc; + + return microcode_update_cpu(data, len); + } + else + return -ENOMEM; +} + +int __init early_microcode_init(void) { + int rc; + + rc = microcode_init_intel(); + if ( rc ) + return rc; + + rc = microcode_init_amd(); + if ( rc ) + return rc; + if ( microcode_ops ) { if ( ucode_mod.mod_end || ucode_blob.size ) - { - void *data; - size_t len; - int rc = 0; - - if ( ucode_blob.size ) - { - len = ucode_blob.size; - data = ucode_blob.data; - } - else - { - len = ucode_mod.mod_end; - data = ucode_mod_map(&ucode_mod); - } - if ( data ) - rc = microcode_update_cpu(data, len); - else - rc = -ENOMEM; - - if ( !ucode_blob.size ) - ucode_mod_map(NULL); - - if ( rc ) - { - if ( ucode_blob.size ) - { - xfree(ucode_blob.data); - ucode_blob.size = 0; - ucode_blob.data = NULL; - } - else - ucode_mod.mod_end = 0; - } - } + rc = early_microcode_update_cpu(1); register_cpu_notifier(µcode_percpu_nfb); } return 0; } -presmp_initcall(microcode_presmp_init); --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -480,10 +480,9 @@ static const struct microcode_ops microc .start_update = start_update, }; -static __init int microcode_init_amd(void) +int __init microcode_init_amd(void) { if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) microcode_ops = µcode_amd_ops; return 0; } -presmp_initcall(microcode_init_amd); --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -403,10 +403,9 @@ static const struct microcode_ops microc .apply_microcode = apply_microcode, }; -static __init int microcode_init_intel(void) +int __init microcode_init_intel(void) { if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) microcode_ops = µcode_intel_ops; return 0; } -presmp_initcall(microcode_init_intel); --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1293,6 +1293,8 @@ void __init __start_xen(unsigned long mb arch_init_memory(); + early_microcode_init(); + identify_cpu(&boot_cpu_data); if ( cpu_has_fxsr ) --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -77,13 +77,16 @@ static enum cpu_state { void *stack_base[NR_CPUS]; +void initialize_cpu_data(unsigned int cpu) +{ + cpu_data[cpu] = boot_cpu_data; +} + static void smp_store_cpu_info(int id) { struct cpuinfo_x86 *c = cpu_data + id; - *c = boot_cpu_data; - if ( id != 0 ) - identify_cpu(c); + identify_cpu(&cpu_data[id]); /* * Certain Athlons might work (for various values of 'work') in SMP @@ -349,6 +352,13 @@ void start_secondary(void *unused) cpu_init(); + initialize_cpu_data(cpu); + + if ( system_state <= SYS_STATE_boot ) + early_microcode_update_cpu(0); + else + microcode_resume_cpu(cpu); + smp_callin(); init_percpu_time(); @@ -387,8 +397,6 @@ void start_secondary(void *unused) local_irq_enable(); mtrr_ap_init(); - microcode_resume_cpu(cpu); - wmb(); startup_cpu_idle_loop(); } @@ -725,7 +733,7 @@ void __init smp_prepare_cpus(unsigned in mtrr_aps_sync_begin(); /* Setup boot CPU information */ - smp_store_cpu_info(0); /* Final full version of the data */ + initialize_cpu_data(0); /* Final full version of the data */ print_cpu_info(0); boot_cpu_physical_apicid = get_apic_id(); --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -572,6 +572,10 @@ int wrmsr_hypervisor_regs(uint32_t idx, void microcode_set_module(unsigned int); int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void), unsigned long len); int microcode_resume_cpu(int cpu); +int early_microcode_update_cpu(bool_t start_update); +int early_microcode_init(void); +int microcode_init_intel(void); +int microcode_init_amd(void); void pv_cpuid(struct cpu_user_regs *regs); --- a/xen/include/xen/smp.h +++ b/xen/include/xen/smp.h @@ -71,4 +71,6 @@ int alloc_cpu_id(void); extern void *stack_base[NR_CPUS]; +void initialize_cpu_data(unsigned int cpu); + #endif /* __XEN_SMP_H__ */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor