Message ID | 20221208132639.29942-1-sergey.dyasli@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] x86/ucode: allow cpu_request_microcode() to skip memory allocation | expand |
On 08/12/2022 13:26, Sergey Dyasli wrote: > 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); This hunk demonstrates why the hook wants to return a non-const pointer. Keeping it non-const will shrink this patch quite a bit. Given that make_copy=false is a special case for the BSP, it can cope with knowing that it shouldn't mutate the pointer it gets given back. I do have a plan for the future to reduce the complexity here, but it depends on getting a few more details out of AMD first. (All of this mess is because their ucode doesn't have an embedded length field.) In the short term, handing the BSP a non-const pointer to a const buffer for early loading is going to be a lesser evil than in the common case giving the caller a const pointer that they're expected to call xfree() on. If this is the only issue, then I'm happy to adjust on commit. ~Andrew
On 08.12.2022 14:59, Andrew Cooper wrote: > On 08/12/2022 13:26, Sergey Dyasli wrote: >> @@ -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); > > This hunk demonstrates why the hook wants to return a non-const > pointer. Keeping it non-const will shrink this patch quite a bit. Alternatively it demonstrates why xfree() should take const void *, just like e.g. unmap_domain_page() or vunmap() already do. We've talked about this before, and the argument hasn't changed: Neither unmapping nor freeing really alters the contents of the pointed to area from the perspective of the caller, as the contents simply disappears altogether. Jan
On Thu, Dec 8, 2022 at 3:34 PM Jan Beulich <jbeulich@suse.com> wrote: > > On 08.12.2022 14:59, Andrew Cooper wrote: > > On 08/12/2022 13:26, Sergey Dyasli wrote: > >> @@ -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); > > > > This hunk demonstrates why the hook wants to return a non-const > > pointer. Keeping it non-const will shrink this patch quite a bit. > > Alternatively it demonstrates why xfree() should take const void *, > just like e.g. unmap_domain_page() or vunmap() already do. We've > talked about this before, and the argument hasn't changed: Neither > unmapping nor freeing really alters the contents of the pointed to > area from the perspective of the caller, as the contents simply > disappears altogether. Despite my love of const, const correctness in C is quite a pain. I've tried to make xfree() take a const pointer but then issues began with add/strip_padding() functions and I couldn't overcome those without further (void *) casts which just takes the problem to a different layer. I think I'll have to go with Andrew's suggestion and continue to return non-const pointers from cpu_request_microcode(). This will include a cast though: patch = (struct microcode_patch *)saved; Sergey
On 12.12.2022 15:27, Sergey Dyasli wrote: > On Thu, Dec 8, 2022 at 3:34 PM Jan Beulich <jbeulich@suse.com> wrote: >> On 08.12.2022 14:59, Andrew Cooper wrote: >>> On 08/12/2022 13:26, Sergey Dyasli wrote: >>>> @@ -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); >>> >>> This hunk demonstrates why the hook wants to return a non-const >>> pointer. Keeping it non-const will shrink this patch quite a bit. >> >> Alternatively it demonstrates why xfree() should take const void *, >> just like e.g. unmap_domain_page() or vunmap() already do. We've >> talked about this before, and the argument hasn't changed: Neither >> unmapping nor freeing really alters the contents of the pointed to >> area from the perspective of the caller, as the contents simply >> disappears altogether. > > Despite my love of const, const correctness in C is quite a pain. I've > tried to make xfree() take a const pointer but then issues began with > add/strip_padding() functions and I couldn't overcome those without > further (void *) casts which just takes the problem to a different > layer. There is exactly one such cast needed according to my attempt, and that's in an internal (static) helper function. See below (and feel free to use). Jan mm: make a couple of freeing functions take const void* freeing functions, from the perspective of their callers, don't alter contents of the freed block; the block simply disappears. Plus it is not uncommon that some piece of memory is allocated, filled, and henceforth supposed to only be read from. In such cases, with the parameters of the freeing functions not being pointer-to-const, callers have to either omit the use of const where it would be indicated or add risky casts. The goal being to make xfree() fit the intended pattern, alter other functions at the same time to limit the number of casts needed to just one. strip_padding() necessarily has to have a such a cast, as it's effectively strchr()- or memchr()-like: Input may be pointer-to-const, bot for its output to also be usable when the input isn't, const needs to be cast away. Note that the risk with such a cast is quite a bit lower when it's an internal (static) function wich is affected. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -2231,7 +2231,7 @@ void *alloc_xenheap_pages(unsigned int o } -void free_xenheap_pages(void *v, unsigned int order) +void free_xenheap_pages(const void *v, unsigned int order) { ASSERT_ALLOC_CONTEXT(); @@ -2279,7 +2279,7 @@ void *alloc_xenheap_pages(unsigned int o return page_to_virt(pg); } -void free_xenheap_pages(void *v, unsigned int order) +void free_xenheap_pages(const void *v, unsigned int order) { struct page_info *pg; unsigned int i; --- a/xen/common/xmalloc_tlsf.c +++ b/xen/common/xmalloc_tlsf.c @@ -453,7 +453,7 @@ void *xmem_pool_alloc(unsigned long size return NULL; } -void xmem_pool_free(void *ptr, struct xmem_pool *pool) +void xmem_pool_free(const void *ptr, struct xmem_pool *pool) { struct bhdr *b, *tmp_b; int fl = 0, sl = 0; @@ -563,7 +563,7 @@ static void tlsf_init(void) * xmalloc() */ -static void *strip_padding(void *p) +static void *strip_padding(const void *p) { const struct bhdr *b = p - BHDR_OVERHEAD; @@ -574,7 +574,7 @@ static void *strip_padding(void *p) ASSERT(!(b->size & FREE_BLOCK)); } - return p; + return (void *)p; } static void *add_padding(void *p, unsigned long align) @@ -699,7 +699,7 @@ void *_xrealloc(void *ptr, unsigned long return p; } -void xfree(void *p) +void xfree(const void *p) { ASSERT_ALLOC_CONTEXT(); --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -73,7 +73,7 @@ void end_boot_allocator(void); void init_xenheap_pages(paddr_t ps, paddr_t pe); void xenheap_max_mfn(unsigned long mfn); void *alloc_xenheap_pages(unsigned int order, unsigned int memflags); -void free_xenheap_pages(void *v, unsigned int order); +void free_xenheap_pages(const void *v, unsigned int order); bool scrub_free_pages(void); #define alloc_xenheap_page() (alloc_xenheap_pages(0,0)) #define free_xenheap_page(v) (free_xenheap_pages(v,0)) --- a/xen/include/xen/xmalloc.h +++ b/xen/include/xen/xmalloc.h @@ -63,7 +63,7 @@ }) /* Free any of the above. */ -extern void xfree(void *); +extern void xfree(const void *); /* Free an allocation, and zero the pointer to it. */ #define XFREE(p) do { \ @@ -148,7 +148,7 @@ int xmem_pool_maxalloc(struct xmem_pool * @ptr: address of memory to be freed * @mem_pool: pool to free from */ -void xmem_pool_free(void *ptr, struct xmem_pool *pool); +void xmem_pool_free(const void *ptr, struct xmem_pool *pool); /** * xmem_pool_get_used_size - get memory currently used by given pool
On 12/12/2022 14:59, Jan Beulich wrote: > On 12.12.2022 15:27, Sergey Dyasli wrote: >> On Thu, Dec 8, 2022 at 3:34 PM Jan Beulich <jbeulich@suse.com> wrote: >>> On 08.12.2022 14:59, Andrew Cooper wrote: >>>> On 08/12/2022 13:26, Sergey Dyasli wrote: >>>>> @@ -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); >>>> This hunk demonstrates why the hook wants to return a non-const >>>> pointer. Keeping it non-const will shrink this patch quite a bit. >>> Alternatively it demonstrates why xfree() should take const void *, >>> just like e.g. unmap_domain_page() or vunmap() already do. We've >>> talked about this before, and the argument hasn't changed: Neither >>> unmapping nor freeing really alters the contents of the pointed to >>> area from the perspective of the caller, as the contents simply >>> disappears altogether. >> Despite my love of const, const correctness in C is quite a pain. I've >> tried to make xfree() take a const pointer but then issues began with >> add/strip_padding() functions and I couldn't overcome those without >> further (void *) casts which just takes the problem to a different >> layer. > There is exactly one such cast needed according to my attempt, and that's > in an internal (static) helper function. See below (and feel free to use). > > Jan > > mm: make a couple of freeing functions take const void* > > freeing functions, from the perspective of their callers, don't alter > contents of the freed block; the block simply disappears. Plus it is not > uncommon that some piece of memory is allocated, filled, and henceforth > supposed to only be read from. In such cases, with the parameters of the > freeing functions not being pointer-to-const, callers have to either > omit the use of const where it would be indicated or add risky casts. > > The goal being to make xfree() fit the intended pattern, alter other > functions at the same time to limit the number of casts needed to just > one. strip_padding() necessarily has to have a such a cast, as it's > effectively strchr()- or memchr()-like: Input may be pointer-to-const, > bot for its output to also be usable when the input isn't, const needs > to be cast away. Note that the risk with such a cast is quite a bit > lower when it's an internal (static) function wich is affected. > > Signed-off-by: Jan Beulich <jbeulich@suse.com> If you can persuade the C standards committee that your interpretation of how to use const is more correct than theirs, and get them to change free() to take const void, then we can continue discussing this patch. Until then, there's a damn good reason why free() takes a non-const pointer (nothing handed out by a memory allocator can ever be const, and it is never acceptable to free via a const alias), and contorted arguments about how its "technically fine" are missing the point. ~Andrew
On 08.12.2022 14:26, Sergey Dyasli wrote: > @@ -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); Just as a remark - callback function arguments like this one also would be nice to be allowed to be pointer-to-const, but I guess we'd need to introduce some trickery to allow such despite the lack of function templates (and even if we had such, also to limit duplication of binary code). Jan
On 12.12.2022 16:18, Andrew Cooper wrote: > On 12/12/2022 14:59, Jan Beulich wrote: >> On 12.12.2022 15:27, Sergey Dyasli wrote: >>> On Thu, Dec 8, 2022 at 3:34 PM Jan Beulich <jbeulich@suse.com> wrote: >>>> On 08.12.2022 14:59, Andrew Cooper wrote: >>>>> On 08/12/2022 13:26, Sergey Dyasli wrote: >>>>>> @@ -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); >>>>> This hunk demonstrates why the hook wants to return a non-const >>>>> pointer. Keeping it non-const will shrink this patch quite a bit. >>>> Alternatively it demonstrates why xfree() should take const void *, >>>> just like e.g. unmap_domain_page() or vunmap() already do. We've >>>> talked about this before, and the argument hasn't changed: Neither >>>> unmapping nor freeing really alters the contents of the pointed to >>>> area from the perspective of the caller, as the contents simply >>>> disappears altogether. >>> Despite my love of const, const correctness in C is quite a pain. I've >>> tried to make xfree() take a const pointer but then issues began with >>> add/strip_padding() functions and I couldn't overcome those without >>> further (void *) casts which just takes the problem to a different >>> layer. >> There is exactly one such cast needed according to my attempt, and that's >> in an internal (static) helper function. See below (and feel free to use). >> >> Jan >> >> mm: make a couple of freeing functions take const void* >> >> freeing functions, from the perspective of their callers, don't alter >> contents of the freed block; the block simply disappears. Plus it is not >> uncommon that some piece of memory is allocated, filled, and henceforth >> supposed to only be read from. In such cases, with the parameters of the >> freeing functions not being pointer-to-const, callers have to either >> omit the use of const where it would be indicated or add risky casts. >> >> The goal being to make xfree() fit the intended pattern, alter other >> functions at the same time to limit the number of casts needed to just >> one. strip_padding() necessarily has to have a such a cast, as it's >> effectively strchr()- or memchr()-like: Input may be pointer-to-const, >> bot for its output to also be usable when the input isn't, const needs >> to be cast away. Note that the risk with such a cast is quite a bit >> lower when it's an internal (static) function wich is affected. >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > If you can persuade the C standards committee that your interpretation > of how to use const is more correct than theirs, and get them to change > free() to take const void, then we can continue discussing this patch. > > Until then, there's a damn good reason why free() takes a non-const > pointer (nothing handed out by a memory allocator can ever be const, and > it is never acceptable to free via a const alias), and contorted > arguments about how its "technically fine" are missing the point. "damn good" and "never acceptable" are strong statements, which will want accompanying by actual technical content. It's not like I've invented this "interpretation". But when I saw it elsewhere (I don't recall which project(s) this was) I found it very reasonable, and hence I picked it up to at least consider for stuff I'm working on. Jan
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).
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.dyasli@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(-)