[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 08/12] microcode: split out apply_microcode() from cpu_request_microcode()
During late microcode update, apply_microcode() is invoked in cpu_request_microcode(). To make late microcode update more reliable, we want to put the apply_microcode() into stop_machine context. So we split out it from cpu_request_microcode(). As a consequence, apply_microcode() should be invoked explicitly in the common code. Also with the global ucode cache, microcode parsing only needs to be done once; cpu_request_microcode() is also moved out of microcode_update_cpu(). On AMD side, svm_host_osvw_init() is supposed to be called after microcode update. As apply_micrcode() won't be called by cpu_request_microcode() now, svm_host_osvw_init() is moved to the end of apply_microcode(). Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> --- Changes in v6: - during early microcode update, BSP and APs call different functions. Thus AP can bypass parsing microcode blob. --- xen/arch/x86/acpi/power.c | 2 +- xen/arch/x86/microcode.c | 77 +++++++++++++++++++++++++---------------- xen/arch/x86/microcode_amd.c | 19 +++++----- xen/arch/x86/microcode_intel.c | 19 ++-------- xen/arch/x86/smpboot.c | 5 +-- xen/include/asm-x86/processor.h | 3 +- 6 files changed, 62 insertions(+), 63 deletions(-) diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index b4c3669..aeacb57 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -253,7 +253,7 @@ static int enter_state(u32 state) console_end_sync(); - microcode_resume_cpu(); + early_microcode_update_cpu(); if ( !recheck_cpu_features(0) ) panic("Missing previously available feature(s)\n"); diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 8bfdf95..e4e2e74 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -261,38 +261,34 @@ const struct microcode_patch *microcode_find_patch(void) return NULL; } -int microcode_resume_cpu(void) +/* + * Return the number of ucode patch inserted to the global cache. + * Return a negtive value on error. + */ +static int microcode_parse_blob(char *buf, uint32_t len) { - int err; - struct cpu_signature *sig = &this_cpu(cpu_sig); - - if ( !microcode_ops ) - return 0; + int ret; spin_lock(µcode_mutex); - - err = microcode_ops->collect_cpu_info(sig); - if ( likely(!err) ) - err = microcode_ops->apply_microcode(); + ret = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); + if ( likely(!ret) ) + ret = microcode_ops->cpu_request_microcode(buf, len); spin_unlock(µcode_mutex); - return err; + return ret; } -static int microcode_update_cpu(const void *buf, size_t size) +static int microcode_update_cpu(void) { - int err; - unsigned int cpu = smp_processor_id(); - struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + int ret; spin_lock(µcode_mutex); - - err = microcode_ops->collect_cpu_info(sig); - if ( likely(!err) ) - err = microcode_ops->cpu_request_microcode(buf, size); + ret = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); + if ( likely(!ret) ) + ret = microcode_ops->apply_microcode(); spin_unlock(µcode_mutex); - return err; + return ret; } static long do_microcode_update(void *_info) @@ -302,7 +298,7 @@ static long do_microcode_update(void *_info) BUG_ON(info->cpu != smp_processor_id()); - error = microcode_update_cpu(info->buffer, info->buffer_size); + error = microcode_update_cpu(); if ( error ) info->error = error; @@ -337,10 +333,6 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) return ret; } - info->buffer_size = len; - info->error = 0; - info->cpu = cpumask_first(&cpu_online_map); - if ( microcode_ops->start_update ) { ret = microcode_ops->start_update(); @@ -351,6 +343,18 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) } } + ret = microcode_parse_blob(info->buffer, len); + if ( ret <= 0 ) + { + printk(XENLOG_ERR "No valid or newer ucode found. Update abort!\n"); + xfree(info); + return -EINVAL; + } + + info->buffer_size = len; + info->error = 0; + info->cpu = cpumask_first(&cpu_online_map); + return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); } @@ -376,7 +380,16 @@ static int __init microcode_init(void) } __initcall(microcode_init); -int __init early_microcode_update_cpu(bool start_update) +int early_microcode_update_cpu(void) +{ + return microcode_ops ? microcode_update_cpu() : 0; +} + +/* + * BSP needs to parse the ucode blob and then apply an update. + * APs just apply an update by calling early_microcode_update_cpu(). + */ +static int __init early_microcode_parse_and_update_cpu(void) { int rc = 0; void *data = NULL; @@ -394,13 +407,17 @@ int __init early_microcode_update_cpu(bool start_update) } if ( data ) { - if ( start_update && microcode_ops->start_update ) + if ( microcode_ops->start_update ) rc = microcode_ops->start_update(); if ( rc ) return rc; - return microcode_update_cpu(data, len); + rc = microcode_parse_blob(data, len); + if ( rc <= 0 ) + return -EINVAL; + + return early_microcode_update_cpu(); } else return -ENOMEM; @@ -419,8 +436,10 @@ int __init early_microcode_init(void) return rc; if ( microcode_ops ) + { if ( ucode_mod.mod_end || ucode_blob.size ) - rc = early_microcode_update_cpu(true); + rc = early_microcode_parse_and_update_cpu(); + } return rc; } diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 25935dd..5c25ff2 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -293,6 +293,10 @@ static int apply_microcode(void) sig->rev = rev; +#ifdef CONFIG_HVM + svm_host_osvw_init(); +#endif + return 0; } @@ -459,6 +463,7 @@ static int cpu_request_microcode(const void *buf, size_t bufsize) unsigned int equiv_cpu_id; unsigned int cpu = smp_processor_id(); const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + unsigned int matched_cnt = 0; current_cpu_id = cpuid_eax(0x00000001); @@ -557,12 +562,8 @@ static int cpu_request_microcode(const void *buf, size_t bufsize) * this ucode patch before checking whether it matches with * current CPU. */ - if ( microcode_save_patch(microcode_patch) && microcode_fits(mc_amd) ) - { - error = apply_microcode(); - if ( error ) - break; - } + if ( microcode_save_patch(microcode_patch) ) + matched_cnt++; if ( offset >= bufsize ) break; @@ -593,17 +594,13 @@ static int cpu_request_microcode(const void *buf, size_t bufsize) } out: -#if CONFIG_HVM - svm_host_osvw_init(); -#endif - /* * In some cases we may return an error even if processor's microcode has * been updated. For example, the first patch in a container file is loaded * successfully but subsequent container file processing encounters a * failure. */ - return error; + return error ?: matched_cnt; } static int start_update(void) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index 18c833f..c921ea9 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -310,7 +310,6 @@ static enum microcode_match_result compare_patch( */ static int get_matching_microcode(const void *mc, unsigned int cpu) { - const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_intel *mc_header = mc; unsigned long total_size = get_totalsize(mc_header); void *new_mc = xmalloc_bytes(total_size); @@ -328,18 +327,9 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) /* * In order to support a system with mixed stepping CPUs, save this ucode - * patch before checking whether it matches with current CPU. + * patch without checking whether it matches with current CPU. */ - if ( !microcode_save_patch(microcode_patch) ) - return 0; - - if ( microcode_update_match(mc, sig->sig, sig->pf, sig->rev) != NEW_UCODE ) - return 0; - - pr_debug("microcode: CPU%d found a matching microcode update with" - " version %#x (current=%#x)\n", - cpu, mc_header->rev, sig->rev); - return 1; + return microcode_save_patch(microcode_patch); } static int apply_microcode(void) @@ -451,10 +441,7 @@ static int cpu_request_microcode(const void *buf, size_t size) if ( offset < 0 ) error = offset; - if ( !error && matching_count ) - error = apply_microcode(); - - return error; + return error ?: matching_count; } static const struct microcode_ops microcode_intel_ops = { diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 763b0bd..2a7f30e 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -363,10 +363,7 @@ void start_secondary(void *unused) initialize_cpu_data(cpu); - if ( system_state <= SYS_STATE_smp_boot ) - early_microcode_update_cpu(false); - else - microcode_resume_cpu(); + early_microcode_update_cpu(); /* * If MSR_SPEC_CTRL is available, apply Xen's default setting and discard diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 186eb8b..9925916 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -573,8 +573,7 @@ int guest_wrmsr_xen(struct vcpu *v, uint32_t idx, uint64_t val); void microcode_set_module(unsigned int); int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void), unsigned long len); -int microcode_resume_cpu(void); -int early_microcode_update_cpu(bool start_update); +int early_microcode_update_cpu(void); int early_microcode_init(void); int microcode_init_intel(void); int microcode_init_amd(void); -- 1.8.3.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |