This is a preparatory step in order to do earlier microcode loading on the boot CPU when the domain heap has not been initialized yet and xmalloc still unavailable.
Add make_copy argument which will allow to load microcode directly from the blob bypassing microcode_cache. Add const qualifiers where required. Signed-off-by: Sergey Dyasli <sergey.dya...@citrix.com> --- xen/arch/x86/cpu/microcode/amd.c | 17 +++++++++++------ xen/arch/x86/cpu/microcode/core.c | 18 +++++++++--------- xen/arch/x86/cpu/microcode/intel.c | 17 +++++++++++------ xen/arch/x86/cpu/microcode/private.h | 18 ++++++++++++------ 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c index 8195707ee1..d4df3c4806 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -299,11 +299,11 @@ static int scan_equiv_cpu_table(const struct container_equiv_table *et) return -ESRCH; } -static struct microcode_patch *cf_check cpu_request_microcode( - const void *buf, size_t size) +static const struct microcode_patch *cf_check cpu_request_microcode( + const void *buf, size_t size, bool make_copy) { const struct microcode_patch *saved = NULL; - struct microcode_patch *patch = NULL; + const struct microcode_patch *patch = NULL; size_t saved_size = 0; int error = 0; @@ -411,9 +411,14 @@ static struct microcode_patch *cf_check cpu_request_microcode( if ( saved ) { - patch = xmemdup_bytes(saved, saved_size); - if ( !patch ) - error = -ENOMEM; + if ( make_copy ) + { + patch = xmemdup_bytes(saved, saved_size); + if ( !patch ) + error = -ENOMEM; + } + else + patch = saved; } if ( error && !patch ) diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index 452a7ca773..924a2bd7b5 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -99,7 +99,7 @@ static bool ucode_in_nmi = true; bool __read_mostly opt_ucode_allow_same; /* Protected by microcode_mutex */ -static struct microcode_patch *microcode_cache; +static const struct microcode_patch *microcode_cache; void __init microcode_set_module(unsigned int idx) { @@ -240,20 +240,20 @@ static const struct microcode_patch *nmi_patch = ZERO_BLOCK_PTR; * patch is found and an error occurs during the parsing process. Otherwise * return NULL. */ -static struct microcode_patch *parse_blob(const char *buf, size_t len) +static const struct microcode_patch *parse_blob(const char *buf, size_t len) { alternative_vcall(ucode_ops.collect_cpu_info); - return alternative_call(ucode_ops.cpu_request_microcode, buf, len); + return alternative_call(ucode_ops.cpu_request_microcode, buf, len, true); } -static void microcode_free_patch(struct microcode_patch *patch) +static void microcode_free_patch(const struct microcode_patch *patch) { - xfree(patch); + xfree((void *)patch); } /* Return true if cache gets updated. Otherwise, return false */ -static bool microcode_update_cache(struct microcode_patch *patch) +static bool microcode_update_cache(const struct microcode_patch *patch) { ASSERT(spin_is_locked(µcode_mutex)); @@ -565,7 +565,7 @@ static long cf_check microcode_update_helper(void *data) int ret; struct ucode_buf *buffer = data; unsigned int cpu, updated; - struct microcode_patch *patch; + const struct microcode_patch *patch; /* cpu_online_map must not change during update */ if ( !get_cpu_maps() ) @@ -648,7 +648,7 @@ static long cf_check microcode_update_helper(void *data) * this requirement can be relaxed in the future. Right now, this is * conservative and good. */ - ret = stop_machine_run(do_microcode_update, patch, NR_CPUS); + ret = stop_machine_run(do_microcode_update, (void *)patch, NR_CPUS); updated = atomic_read(&cpu_updated); if ( updated > 0 ) @@ -738,7 +738,7 @@ static int __init early_microcode_update_cpu(void) int rc = 0; const void *data = NULL; size_t len; - struct microcode_patch *patch; + const struct microcode_patch *patch; if ( ucode_blob.size ) { diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c index f5ba6d76d7..017f37e43d 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -323,12 +323,12 @@ static int cf_check apply_microcode(const struct microcode_patch *patch) return 0; } -static struct microcode_patch *cf_check cpu_request_microcode( - const void *buf, size_t size) +static const struct microcode_patch *cf_check cpu_request_microcode( + const void *buf, size_t size, bool make_copy) { int error = 0; const struct microcode_patch *saved = NULL; - struct microcode_patch *patch = NULL; + const struct microcode_patch *patch = NULL; while ( size ) { @@ -364,10 +364,15 @@ static struct microcode_patch *cf_check cpu_request_microcode( if ( saved ) { - patch = xmemdup_bytes(saved, get_totalsize(saved)); + if ( make_copy ) + { + patch = xmemdup_bytes(saved, get_totalsize(saved)); - if ( !patch ) - error = -ENOMEM; + if ( !patch ) + error = -ENOMEM; + } + else + patch = saved; } if ( error && !patch ) diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h index c085a10268..98657d39c3 100644 --- a/xen/arch/x86/cpu/microcode/private.h +++ b/xen/arch/x86/cpu/microcode/private.h @@ -23,16 +23,22 @@ struct microcode_ops { * older that what is running in the CPU. This is a feature, to better * cope with corner cases from buggy firmware.) * - * If one is found, allocate and return a struct microcode_patch - * encapsulating the appropriate microcode patch. Does not alias the - * original buffer. Must be suitable to be freed with a single xfree(). + * If one is found, behaviour depends on the make_copy argument: + * + * true: allocate and return a struct microcode_patch encapsulating + * the appropriate microcode patch. Does not alias the original + * buffer. Must be suitable to be freed with a single xfree(). + * + * false: return a pointer to the patch within the original buffer. + * This is useful for early microcode loading when xmalloc might + * not be available yet. * * If one is not found, (nothing matches the current CPU), return NULL. * Also may return ERR_PTR(-err), e.g. bad container, out of memory. */ - struct microcode_patch *(*cpu_request_microcode)(const void *buf, - size_t size); - + const struct microcode_patch *(*cpu_request_microcode)(const void *buf, + size_t size, + bool make_copy); /* * Obtain microcode-relevant details for the current CPU. Results in * per_cpu(cpu_sig). -- 2.17.1