[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v5 5/8] microcode: split out apply_microcode() from cpu_request_microcode()
On Mon, Jan 28, 2019 at 03:06:47PM +0800, Chao Gao wrote: > 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 also moved to the > end of apply_microcode(). > > Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> > --- > xen/arch/x86/microcode.c | 80 > +++++++++++++++++++++++++----------------- > xen/arch/x86/microcode_amd.c | 23 +++++++----- > xen/arch/x86/microcode_intel.c | 20 ++--------- > 3 files changed, 64 insertions(+), 59 deletions(-) > > diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c > index 0c77e90..936f0b8 100644 > --- a/xen/arch/x86/microcode.c > +++ b/xen/arch/x86/microcode.c > @@ -254,47 +254,42 @@ struct microcode_patch *find_patch(unsigned int cpu) > return NULL; > } > > -int microcode_resume_cpu(unsigned int cpu) > +/* > + * Return the number of ucode patch inserted to the global cache. > + * Return negtive value on error. > + */ > +static int parse_microcode_blob(const void *buffer, size_t len) > { > - int err; > + unsigned int cpu = smp_processor_id(); > struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); > - > - if ( !microcode_ops ) > - return 0; > + int ret; > > spin_lock(µcode_mutex); > - > - err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); > - if ( err ) > - { > + ret = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); > + if ( likely(!ret) ) > + ret = microcode_ops->cpu_request_microcode(cpu, buffer, len); > + else > microcode_fini_cpu(cpu); > - spin_unlock(µcode_mutex); > - return err; > - } > - > - err = microcode_ops->apply_microcode(cpu); > 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 ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); > + int ret; > > spin_lock(µcode_mutex); > - > - err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); > - if ( likely(!err) ) > - err = microcode_ops->cpu_request_microcode(cpu, buf, size); > - else > - microcode_fini_cpu(cpu); > - > + ret = microcode_ops->apply_microcode(smp_processor_id()); I've realized that most of this helpers take a cpu id parameter (apply_microcode, collect_cpu_info and cpu_request_microcode), but that at least on Intel they are required to be called on the current CPU, at which point I wonder about their purpose. IMO they just make the interface more messy, without adding any functionality. > spin_unlock(µcode_mutex); > > - return err; > + return ret; > +} > + > +int microcode_resume_cpu(unsigned int cpu) > +{ > + BUG_ON(cpu != smp_processor_id()); Same here, what's the point of passing a cpu id as parameter when there's only one valid value? > + return microcode_ops ? microcode_update_cpu() : 0; > } > > static long do_microcode_update(void *_info) > @@ -304,7 +299,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; > > @@ -339,10 +334,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(); > @@ -353,6 +344,18 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) > buf, unsigned long len) > } > } > > + ret = parse_microcode_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); It looks like you can also get rid of the cpu field in microcode_info, since it's always smp_processor_id? > + > return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); > } > > @@ -396,13 +399,24 @@ int __init early_microcode_update_cpu(bool start_update) > } > if ( data ) > { > + static bool parsed = false; > + > if ( start_update && microcode_ops->start_update ) > rc = microcode_ops->start_update(); > > if ( rc ) > return rc; > > - return microcode_update_cpu(data, len); > + if ( !parsed ) > + { > + rc = parse_microcode_blob(data, len); > + parsed = true; > + > + if ( rc <= 0 ) > + return -EINVAL; > + } > + > + return microcode_update_cpu(); Hm, the usage of parsed here is kind of dangerous. I assume this works fine because early_microcode_update_cpu is called from the BSP in early_microcode_init, and then concurrent calls done by the APs always see parsed as true. I would however recommend that you move the parsing to early_microcode_init, and that early_microcode_update_cpu always assume the blob has been parsed. If that doesn't work for some reason, I would then recommend that you gate the parsing based on cpu_id, so "smp_processor_id() == 0" > } > else > return -ENOMEM; > diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c > index d86a596..80e274e 100644 > --- a/xen/arch/x86/microcode_amd.c > +++ b/xen/arch/x86/microcode_amd.c > @@ -297,6 +297,10 @@ static int apply_microcode(unsigned int cpu) > > uci->cpu_sig.rev = rev; > > +#if CONFIG_HVM > + svm_host_osvw_init(); > +#endif > + > return 0; > } > > @@ -463,6 +467,7 @@ static int cpu_request_microcode(unsigned int cpu, const > void *buf, > struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); > unsigned int current_cpu_id; > unsigned int equiv_cpu_id; > + unsigned int matched_cnt = 0; > > /* We should bind the task to the CPU */ > BUG_ON(cpu != raw_smp_processor_id()); > @@ -564,11 +569,15 @@ static int cpu_request_microcode(unsigned int cpu, > const void *buf, > * this ucode patch before checking whether it matches with > * current CPU. > */ > - if ( save_patch(microcode_patch) && microcode_fits(mc_amd, cpu) ) > + if ( save_patch(microcode_patch) ) > { > - error = apply_microcode(cpu); > - if ( error ) > - break; > + matched_cnt++; > + if ( microcode_fits(mc_amd, cpu) ) > + { > + error = apply_microcode(cpu); > + if ( error ) > + break; > + } In the commit message you mention that apply_microcode won't be called by cpu_request_microcode, yet it seems it's called? Thanks, Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |