@@ -300,7 +300,7 @@ static int scan_equiv_cpu_table(const struct container_equiv_table *et)
}
static struct microcode_patch *cf_check cpu_request_microcode(
- const void *buf, size_t size)
+ const void *buf, size_t size, bool make_copy)
{
const struct microcode_patch *saved = NULL;
struct microcode_patch *patch = NULL;
@@ -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 = (struct microcode_patch *)saved;
}
if ( error && !patch )
@@ -244,7 +244,7 @@ static 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)
@@ -324,7 +324,7 @@ static int cf_check apply_microcode(const struct microcode_patch *patch)
}
static struct microcode_patch *cf_check cpu_request_microcode(
- const void *buf, size_t size)
+ const void *buf, size_t size, bool make_copy)
{
int error = 0;
const struct microcode_patch *saved = NULL;
@@ -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 = (struct microcode_patch *)saved;
}
if ( error && !patch )
@@ -23,15 +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);
+ size_t size,
+ bool make_copy);
/*
* Obtain microcode-relevant details for the current CPU. Results in
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. Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> --- v1 --> v2: - Don't add extra consts --- xen/arch/x86/cpu/microcode/amd.c | 13 +++++++++---- xen/arch/x86/cpu/microcode/core.c | 2 +- xen/arch/x86/cpu/microcode/intel.c | 13 +++++++++---- xen/arch/x86/cpu/microcode/private.h | 15 +++++++++++---- 4 files changed, 30 insertions(+), 13 deletions(-)