diff options
Diffstat (limited to '0052-x86-ucode-AMD-apply-the-patch-early-on-every-logical.patch')
-rw-r--r-- | 0052-x86-ucode-AMD-apply-the-patch-early-on-every-logical.patch | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/0052-x86-ucode-AMD-apply-the-patch-early-on-every-logical.patch b/0052-x86-ucode-AMD-apply-the-patch-early-on-every-logical.patch new file mode 100644 index 0000000..22a214b --- /dev/null +++ b/0052-x86-ucode-AMD-apply-the-patch-early-on-every-logical.patch @@ -0,0 +1,154 @@ +From e9a7942f6c1638c668605fbf6d6e02bc7bff2582 Mon Sep 17 00:00:00 2001 +From: Sergey Dyasli <sergey.dyasli@citrix.com> +Date: Fri, 3 Mar 2023 07:58:35 +0100 +Subject: [PATCH 52/89] x86/ucode/AMD: apply the patch early on every logical + thread + +The original issue has been reported on AMD Bulldozer-based CPUs where +ucode loading loses the LWP feature bit in order to gain the IBPB bit. +LWP disabling is per-SMT/CMT core modification and needs to happen on +each sibling thread despite the shared microcode engine. Otherwise, +logical CPUs will end up with different cpuid capabilities. +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216211 + +Guests running under Xen happen to be not affected because of levelling +logic for the feature masking/override MSRs which causes the LWP bit to +fall out and hides the issue. The latest recommendation from AMD, after +discussing this bug, is to load ucode on every logical CPU. + +In Linux kernel this issue has been addressed by e7ad18d1169c +("x86/microcode/AMD: Apply the patch early on every logical thread"). +Follow the same approach in Xen. + +Introduce SAME_UCODE match result and use it for early AMD ucode +loading. Take this opportunity and move opt_ucode_allow_same out of +compare_revisions() to the relevant callers and also modify the warning +message based on it. Intel's side of things is modified for consistency +but provides no functional change. + +Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> +master commit: f4ef8a41b80831db2136bdaff9f946a1a4b051e7 +master date: 2023-02-21 15:08:05 +0100 +--- + xen/arch/x86/cpu/microcode/amd.c | 11 ++++++++--- + xen/arch/x86/cpu/microcode/core.c | 26 +++++++++++++++++--------- + xen/arch/x86/cpu/microcode/intel.c | 10 +++++++--- + xen/arch/x86/cpu/microcode/private.h | 3 ++- + 4 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c +index 8195707ee1..ded8fe90e6 100644 +--- a/xen/arch/x86/cpu/microcode/amd.c ++++ b/xen/arch/x86/cpu/microcode/amd.c +@@ -176,8 +176,8 @@ static enum microcode_match_result compare_revisions( + if ( new_rev > old_rev ) + return NEW_UCODE; + +- if ( opt_ucode_allow_same && new_rev == old_rev ) +- return NEW_UCODE; ++ if ( new_rev == old_rev ) ++ return SAME_UCODE; + + return OLD_UCODE; + } +@@ -220,8 +220,13 @@ static int cf_check apply_microcode(const struct microcode_patch *patch) + unsigned int cpu = smp_processor_id(); + struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + uint32_t rev, old_rev = sig->rev; ++ enum microcode_match_result result = microcode_fits(patch); + +- if ( microcode_fits(patch) != NEW_UCODE ) ++ /* ++ * Allow application of the same revision to pick up SMT-specific changes ++ * even if the revision of the other SMT thread is already up-to-date. ++ */ ++ if ( result != NEW_UCODE && result != SAME_UCODE ) + return -EINVAL; + + if ( check_final_patch_levels(sig) ) +diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c +index 452a7ca773..57ecc5358b 100644 +--- a/xen/arch/x86/cpu/microcode/core.c ++++ b/xen/arch/x86/cpu/microcode/core.c +@@ -610,17 +610,25 @@ static long cf_check microcode_update_helper(void *data) + * that ucode revision. + */ + spin_lock(µcode_mutex); +- if ( microcode_cache && +- alternative_call(ucode_ops.compare_patch, +- patch, microcode_cache) != NEW_UCODE ) ++ if ( microcode_cache ) + { +- spin_unlock(µcode_mutex); +- printk(XENLOG_WARNING "microcode: couldn't find any newer revision " +- "in the provided blob!\n"); +- microcode_free_patch(patch); +- ret = -ENOENT; ++ enum microcode_match_result result; + +- goto put; ++ result = alternative_call(ucode_ops.compare_patch, patch, ++ microcode_cache); ++ ++ if ( result != NEW_UCODE && ++ !(opt_ucode_allow_same && result == SAME_UCODE) ) ++ { ++ spin_unlock(µcode_mutex); ++ printk(XENLOG_WARNING ++ "microcode: couldn't find any newer%s revision in the provided blob!\n", ++ opt_ucode_allow_same ? " (or the same)" : ""); ++ microcode_free_patch(patch); ++ ret = -ENOENT; ++ ++ goto put; ++ } + } + spin_unlock(µcode_mutex); + +diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c +index f5ba6d76d7..cb08f63d2e 100644 +--- a/xen/arch/x86/cpu/microcode/intel.c ++++ b/xen/arch/x86/cpu/microcode/intel.c +@@ -232,8 +232,8 @@ static enum microcode_match_result compare_revisions( + if ( new_rev > old_rev ) + return NEW_UCODE; + +- if ( opt_ucode_allow_same && new_rev == old_rev ) +- return NEW_UCODE; ++ if ( new_rev == old_rev ) ++ return SAME_UCODE; + + /* + * Treat pre-production as always applicable - anyone using pre-production +@@ -290,8 +290,12 @@ static int cf_check apply_microcode(const struct microcode_patch *patch) + unsigned int cpu = smp_processor_id(); + struct cpu_signature *sig = &this_cpu(cpu_sig); + uint32_t rev, old_rev = sig->rev; ++ enum microcode_match_result result; ++ ++ result = microcode_update_match(patch); + +- if ( microcode_update_match(patch) != NEW_UCODE ) ++ if ( result != NEW_UCODE && ++ !(opt_ucode_allow_same && result == SAME_UCODE) ) + return -EINVAL; + + wbinvd(); +diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h +index c085a10268..feafab0677 100644 +--- a/xen/arch/x86/cpu/microcode/private.h ++++ b/xen/arch/x86/cpu/microcode/private.h +@@ -6,7 +6,8 @@ + extern bool opt_ucode_allow_same; + + enum microcode_match_result { +- OLD_UCODE, /* signature matched, but revision id is older or equal */ ++ OLD_UCODE, /* signature matched, but revision id is older */ ++ SAME_UCODE, /* signature matched, but revision id is the same */ + NEW_UCODE, /* signature matched, but revision id is newer */ + MIS_UCODE, /* signature mismatched */ + }; +-- +2.40.0 + |