Skip to content

Commit 7ff6edf

Browse files
committed
x86/microcode/AMD: Fix mixed steppings support
The AMD side of the loader has always claimed to support mixed steppings. But somewhere along the way, it broke that by assuming that the cached patch blob is a single one instead of it being one per *node*. So turn it into a per-node one so that each node can stash the blob relevant for it. [ NB: Fixes tag is not really the exactly correct one but it is good enough. ] Fixes: fe05589 ("x86/microcode: Merge the early microcode loader") Signed-off-by: Borislav Petkov (AMD) <[email protected]> Cc: <[email protected]> # 2355370 ("x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter") Cc: <[email protected]> # a5ad921 ("x86/microcode/AMD: Add a @cpu parameter to the reloading functions") Link: https://lore.kernel.org/r/[email protected]
1 parent a5ad921 commit 7ff6edf

File tree

1 file changed

+21
-13
lines changed
  • arch/x86/kernel/cpu/microcode

1 file changed

+21
-13
lines changed

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

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ struct cont_desc {
5555
};
5656

5757
static u32 ucode_new_rev;
58-
static u8 amd_ucode_patch[PATCH_MAX_SIZE];
58+
59+
/* One blob per node. */
60+
static u8 amd_ucode_patch[MAX_NUMNODES][PATCH_MAX_SIZE];
5961

6062
/*
6163
* Microcode patch container file is prepended to the initrd in cpio
@@ -428,7 +430,7 @@ static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size, boo
428430
patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
429431
#else
430432
new_rev = &ucode_new_rev;
431-
patch = &amd_ucode_patch;
433+
patch = &amd_ucode_patch[0];
432434
#endif
433435

434436
desc.cpuid_1_eax = cpuid_1_eax;
@@ -580,10 +582,10 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
580582

581583
void reload_ucode_amd(unsigned int cpu)
582584
{
583-
struct microcode_amd *mc;
584585
u32 rev, dummy __always_unused;
586+
struct microcode_amd *mc;
585587

586-
mc = (struct microcode_amd *)amd_ucode_patch;
588+
mc = (struct microcode_amd *)amd_ucode_patch[cpu_to_node(cpu)];
587589

588590
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
589591

@@ -852,6 +854,8 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
852854

853855
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
854856
{
857+
struct cpuinfo_x86 *c;
858+
unsigned int nid, cpu;
855859
struct ucode_patch *p;
856860
enum ucode_state ret;
857861

@@ -864,18 +868,22 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz
864868
return ret;
865869
}
866870

867-
p = find_patch(0);
868-
if (!p) {
869-
return ret;
870-
} else {
871-
if (boot_cpu_data.microcode >= p->patch_id)
872-
return ret;
871+
for_each_node(nid) {
872+
cpu = cpumask_first(cpumask_of_node(nid));
873+
c = &cpu_data(cpu);
874+
875+
p = find_patch(cpu);
876+
if (!p)
877+
continue;
878+
879+
if (c->microcode >= p->patch_id)
880+
continue;
873881

874882
ret = UCODE_NEW;
875-
}
876883

877-
memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
878-
memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
884+
memset(&amd_ucode_patch[nid], 0, PATCH_MAX_SIZE);
885+
memcpy(&amd_ucode_patch[nid], p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
886+
}
879887

880888
return ret;
881889
}

0 commit comments

Comments
 (0)