[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 1/7] x86/ucode: Remove unnecessary indirection in struct microcode_patch
Currently, each cpu_request_microcode() allocates a struct microcode_patch, which is a single pointer to a separate allocated structure. This is wasteful. Fixing this is complicated because the common microcode_free_patch() code is responsible for freeing struct microcode_patch, despite this being asymmetric with how it is allocated. Make struct microcode_patch fully opaque to the common logic. This involves moving the responsibility for freeing struct microcode_patch fully into the free_patch() hook. In each vendor logic, use some temporary ifdef-ary (cleaned up in subsequent changes) to reduce the churn as much as possible, and forgo allocating the intermediate pointer in cpu_request_microcode(). Suggested-by: Jan Beulich <jbeulich@xxxxxxxx> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wl@xxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> v2: * New --- xen/arch/x86/cpu/microcode/amd.c | 30 ++++++++++++------------------ xen/arch/x86/cpu/microcode/core.c | 3 +-- xen/arch/x86/cpu/microcode/intel.c | 31 ++++++++++++------------------- xen/arch/x86/cpu/microcode/private.h | 11 +++-------- 4 files changed, 28 insertions(+), 47 deletions(-) diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c index 122b8309af..1b9373f0d9 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -60,13 +60,16 @@ struct __packed microcode_header_amd { #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 #define UCODE_UCODE_TYPE 0x00000001 -struct microcode_amd { +struct microcode_patch { void *mpb; size_t mpb_size; struct equiv_cpu_entry *equiv_cpu_table; size_t equiv_cpu_table_size; }; +/* Temporary, until the microcode_* structure are disentangled. */ +#define microcode_amd microcode_patch + struct mpbhdr { uint32_t type; uint32_t len; @@ -177,13 +180,11 @@ static enum microcode_match_result microcode_fits( static bool match_cpu(const struct microcode_patch *patch) { - return patch && (microcode_fits(patch->mc_amd) == NEW_UCODE); + return patch && (microcode_fits(patch) == NEW_UCODE); } -static void free_patch(void *mc) +static void free_patch(struct microcode_patch *mc_amd) { - struct microcode_amd *mc_amd = mc; - if ( mc_amd ) { xfree(mc_amd->equiv_cpu_table); @@ -206,12 +207,12 @@ static enum microcode_match_result compare_header( static enum microcode_match_result compare_patch( const struct microcode_patch *new, const struct microcode_patch *old) { - const struct microcode_header_amd *new_header = new->mc_amd->mpb; - const struct microcode_header_amd *old_header = old->mc_amd->mpb; + const struct microcode_header_amd *new_header = new->mpb; + const struct microcode_header_amd *old_header = old->mpb; /* Both patches to compare are supposed to be applicable to local CPU. */ - ASSERT(microcode_fits(new->mc_amd) != MIS_UCODE); - ASSERT(microcode_fits(old->mc_amd) != MIS_UCODE); + ASSERT(microcode_fits(new) != MIS_UCODE); + ASSERT(microcode_fits(old) != MIS_UCODE); return compare_header(new_header, old_header); } @@ -230,7 +231,7 @@ static int apply_microcode(const struct microcode_patch *patch) if ( !match_cpu(patch) ) return -EINVAL; - hdr = patch->mc_amd->mpb; + hdr = patch->mpb; BUG_ON(local_irq_is_enabled()); @@ -554,14 +555,7 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, { mc_amd->mpb = saved; mc_amd->mpb_size = saved_size; - patch = xmalloc(struct microcode_patch); - if ( patch ) - patch->mc_amd = mc_amd; - else - { - free_patch(mc_amd); - error = -ENOMEM; - } + patch = mc_amd; } else free_patch(mc_amd); diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index 61150e04c8..b3e5913d49 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -245,8 +245,7 @@ static struct microcode_patch *parse_blob(const char *buf, size_t len) static void microcode_free_patch(struct microcode_patch *microcode_patch) { - microcode_ops->free_patch(microcode_patch->mc); - xfree(microcode_patch); + microcode_ops->free_patch(microcode_patch); } /* Return true if cache gets updated. Otherwise, return false */ diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c index 78455aa0ae..a69f7fe1de 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -52,11 +52,14 @@ struct microcode_header_intel { unsigned int reserved[3]; }; -struct microcode_intel { +struct microcode_patch { struct microcode_header_intel hdr; unsigned int bits[0]; }; +/* Temporary, until the microcode_* structure are disentangled. */ +#define microcode_intel microcode_patch + /* microcode format is extended from prescott processors */ struct extended_signature { unsigned int sig; @@ -245,12 +248,12 @@ static bool match_cpu(const struct microcode_patch *patch) if ( !patch ) return false; - return microcode_update_match(&patch->mc_intel->hdr) == NEW_UCODE; + return microcode_update_match(&patch->hdr) == NEW_UCODE; } -static void free_patch(void *mc) +static void free_patch(struct microcode_patch *patch) { - xfree(mc); + xfree(patch); } static enum microcode_match_result compare_patch( @@ -260,11 +263,10 @@ static enum microcode_match_result compare_patch( * Both patches to compare are supposed to be applicable to local CPU. * Just compare the revision number. */ - ASSERT(microcode_update_match(&old->mc_intel->hdr) != MIS_UCODE); - ASSERT(microcode_update_match(&new->mc_intel->hdr) != MIS_UCODE); + ASSERT(microcode_update_match(&old->hdr) != MIS_UCODE); + ASSERT(microcode_update_match(&new->hdr) != MIS_UCODE); - return (new->mc_intel->hdr.rev > old->mc_intel->hdr.rev) ? NEW_UCODE - : OLD_UCODE; + return (new->hdr.rev > old->hdr.rev) ? NEW_UCODE : OLD_UCODE; } static int apply_microcode(const struct microcode_patch *patch) @@ -281,7 +283,7 @@ static int apply_microcode(const struct microcode_patch *patch) if ( !match_cpu(patch) ) return -EINVAL; - mc_intel = patch->mc_intel; + mc_intel = patch; BUG_ON(local_irq_is_enabled()); @@ -372,16 +374,7 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, error = offset; if ( saved ) - { - patch = xmalloc(struct microcode_patch); - if ( patch ) - patch->mc_intel = saved; - else - { - xfree(saved); - error = -ENOMEM; - } - } + patch = saved; if ( error && !patch ) patch = ERR_PTR(error); diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h index 230b935c94..df0d0852cd 100644 --- a/xen/arch/x86/cpu/microcode/private.h +++ b/xen/arch/x86/cpu/microcode/private.h @@ -11,13 +11,8 @@ enum microcode_match_result { MIS_UCODE, /* signature mismatched */ }; -struct microcode_patch { - union { - struct microcode_intel *mc_intel; - struct microcode_amd *mc_amd; - void *mc; - }; -}; +/* Opaque. Internals are vendor-specific. */ +struct microcode_patch; struct microcode_ops { /* @@ -62,7 +57,7 @@ struct microcode_ops { void (*end_update_percpu)(void); /* Free a patch previously allocated by cpu_request_microcode(). */ - void (*free_patch)(void *mc); + void (*free_patch)(struct microcode_patch *patch); /* * Is the microcode patch applicable for the current CPU, and newer than -- 2.11.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |