Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:ALP:Source:Standard:0.1
xen
63f4d045-x86-ucode-AMD-apply-early-on-all-threa...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 63f4d045-x86-ucode-AMD-apply-early-on-all-threads.patch of Package xen
# Commit f4ef8a41b80831db2136bdaff9f946a1a4b051e7 # Date 2023-02-21 15:08:05 +0100 # Author Sergey Dyasli <sergey.dyasli@citrix.com> # Committer Jan Beulich <jbeulich@suse.com> 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> --- 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 compa 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(cons 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) ) --- 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_he * 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); --- 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 compa 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(cons 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(); --- 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 */ };
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor