Skip to content

Commit d1744a4

Browse files
committed
x86/microcode/AMD: Pay attention to the stepping dynamically
Commit in Fixes changed how a microcode patch is loaded on Zen and newer but the patch matching needs to happen with different rigidity, depending on what is being done: 1) When the patch is added to the patches cache, the stepping must be ignored because the driver still supports different steppings per system 2) When the patch is matched for loading, then the stepping must be taken into account because each CPU needs the patch matching its exact stepping Take care of that by making the matching smarter. Fixes: 94838d2 ("x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID") Reported-by: Jens Axboe <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Tested-by: Jens Axboe <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3267cb6 commit d1744a4

File tree

1 file changed

+18
-8
lines changed
  • arch/x86/kernel/cpu/microcode

1 file changed

+18
-8
lines changed

arch/x86/kernel/cpu/microcode/amd.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -613,16 +613,19 @@ static int __init save_microcode_in_initrd(void)
613613
}
614614
early_initcall(save_microcode_in_initrd);
615615

616-
static inline bool patch_cpus_equivalent(struct ucode_patch *p, struct ucode_patch *n)
616+
static inline bool patch_cpus_equivalent(struct ucode_patch *p,
617+
struct ucode_patch *n,
618+
bool ignore_stepping)
617619
{
618620
/* Zen and newer hardcode the f/m/s in the patch ID */
619621
if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
620622
union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id);
621623
union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id);
622624

623-
/* Zap stepping */
624-
p_cid.stepping = 0;
625-
n_cid.stepping = 0;
625+
if (ignore_stepping) {
626+
p_cid.stepping = 0;
627+
n_cid.stepping = 0;
628+
}
626629

627630
return p_cid.full == n_cid.full;
628631
} else {
@@ -644,13 +647,13 @@ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equi
644647
WARN_ON_ONCE(!n.patch_id);
645648

646649
list_for_each_entry(p, &microcode_cache, plist)
647-
if (patch_cpus_equivalent(p, &n))
650+
if (patch_cpus_equivalent(p, &n, false))
648651
return p;
649652

650653
return NULL;
651654
}
652655

653-
static inline bool patch_newer(struct ucode_patch *p, struct ucode_patch *n)
656+
static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n)
654657
{
655658
/* Zen and newer hardcode the f/m/s in the patch ID */
656659
if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
@@ -659,6 +662,9 @@ static inline bool patch_newer(struct ucode_patch *p, struct ucode_patch *n)
659662
zp.ucode_rev = p->patch_id;
660663
zn.ucode_rev = n->patch_id;
661664

665+
if (zn.stepping != zp.stepping)
666+
return -1;
667+
662668
return zn.rev > zp.rev;
663669
} else {
664670
return n->patch_id > p->patch_id;
@@ -668,10 +674,14 @@ static inline bool patch_newer(struct ucode_patch *p, struct ucode_patch *n)
668674
static void update_cache(struct ucode_patch *new_patch)
669675
{
670676
struct ucode_patch *p;
677+
int ret;
671678

672679
list_for_each_entry(p, &microcode_cache, plist) {
673-
if (patch_cpus_equivalent(p, new_patch)) {
674-
if (!patch_newer(p, new_patch)) {
680+
if (patch_cpus_equivalent(p, new_patch, true)) {
681+
ret = patch_newer(p, new_patch);
682+
if (ret < 0)
683+
continue;
684+
else if (!ret) {
675685
/* we already have the latest patch */
676686
kfree(new_patch->data);
677687
kfree(new_patch);

0 commit comments

Comments
 (0)