Skip to content

Commit efebca0

Browse files
committed
Merge tag 'x86_microcode_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode loader updates from Borislav Petkov: - Fix mixed steppings support on AMD which got broken somewhere along the way - Improve revision reporting - Properly check CPUID capabilities after late microcode upgrade to avoid false positives - A garden variety of other small fixes * tag 'x86_microcode_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/microcode/core: Return an error only when necessary x86/microcode/AMD: Fix mixed steppings support x86/microcode/AMD: Add a @cpu parameter to the reloading functions x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter x86/microcode: Allow only "1" as a late reload trigger value x86/microcode/intel: Print old and new revision during early boot x86/microcode/intel: Pass the microcode revision to print_ucode_info() directly x86/microcode: Adjust late loading result reporting message x86/microcode: Check CPU capabilities after late microcode update correctly x86/microcode: Add a parameter to microcode_check() to store CPU capabilities x86/microcode: Use the DEVICE_ATTR_RO() macro x86/microcode/AMD: Handle multiple glued containers properly x86/microcode/AMD: Rename a couple of functions
2 parents aa8c3db + f33e0c8 commit efebca0

File tree

7 files changed

+117
-104
lines changed

7 files changed

+117
-104
lines changed

arch/x86/include/asm/microcode.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,13 @@ static inline unsigned int x86_cpuid_family(void)
125125
#ifdef CONFIG_MICROCODE
126126
extern void __init load_ucode_bsp(void);
127127
extern void load_ucode_ap(void);
128-
void reload_early_microcode(void);
128+
void reload_early_microcode(unsigned int cpu);
129129
extern bool initrd_gone;
130130
void microcode_bsp_resume(void);
131131
#else
132132
static inline void __init load_ucode_bsp(void) { }
133133
static inline void load_ucode_ap(void) { }
134-
static inline void reload_early_microcode(void) { }
134+
static inline void reload_early_microcode(unsigned int cpu) { }
135135
static inline void microcode_bsp_resume(void) { }
136136
#endif
137137

arch/x86/include/asm/microcode_amd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ struct microcode_amd {
4747
extern void __init load_ucode_amd_bsp(unsigned int family);
4848
extern void load_ucode_amd_ap(unsigned int family);
4949
extern int __init save_microcode_in_initrd_amd(unsigned int family);
50-
void reload_ucode_amd(void);
50+
void reload_ucode_amd(unsigned int cpu);
5151
#else
5252
static inline void __init load_ucode_amd_bsp(unsigned int family) {}
5353
static inline void load_ucode_amd_ap(unsigned int family) {}
5454
static inline int __init
5555
save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
56-
static inline void reload_ucode_amd(void) {}
56+
static inline void reload_ucode_amd(unsigned int cpu) {}
5757
#endif
5858
#endif /* _ASM_X86_MICROCODE_AMD_H */

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,8 @@ bool xen_set_default_idle(void);
697697
#endif
698698

699699
void __noreturn stop_this_cpu(void *dummy);
700-
void microcode_check(void);
700+
void microcode_check(struct cpuinfo_x86 *prev_info);
701+
void store_cpu_caps(struct cpuinfo_x86 *info);
701702

702703
enum l1tf_mitigations {
703704
L1TF_MITIGATION_OFF,

arch/x86/kernel/cpu/common.c

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,30 +2302,45 @@ void cpu_init_secondary(void)
23022302
#endif
23032303

23042304
#ifdef CONFIG_MICROCODE_LATE_LOADING
2305-
/*
2305+
/**
2306+
* store_cpu_caps() - Store a snapshot of CPU capabilities
2307+
* @curr_info: Pointer where to store it
2308+
*
2309+
* Returns: None
2310+
*/
2311+
void store_cpu_caps(struct cpuinfo_x86 *curr_info)
2312+
{
2313+
/* Reload CPUID max function as it might've changed. */
2314+
curr_info->cpuid_level = cpuid_eax(0);
2315+
2316+
/* Copy all capability leafs and pick up the synthetic ones. */
2317+
memcpy(&curr_info->x86_capability, &boot_cpu_data.x86_capability,
2318+
sizeof(curr_info->x86_capability));
2319+
2320+
/* Get the hardware CPUID leafs */
2321+
get_cpu_cap(curr_info);
2322+
}
2323+
2324+
/**
2325+
* microcode_check() - Check if any CPU capabilities changed after an update.
2326+
* @prev_info: CPU capabilities stored before an update.
2327+
*
23062328
* The microcode loader calls this upon late microcode load to recheck features,
23072329
* only when microcode has been updated. Caller holds microcode_mutex and CPU
23082330
* hotplug lock.
2331+
*
2332+
* Return: None
23092333
*/
2310-
void microcode_check(void)
2334+
void microcode_check(struct cpuinfo_x86 *prev_info)
23112335
{
2312-
struct cpuinfo_x86 info;
2336+
struct cpuinfo_x86 curr_info;
23132337

23142338
perf_check_microcode();
23152339

2316-
/* Reload CPUID max function as it might've changed. */
2317-
info.cpuid_level = cpuid_eax(0);
2318-
2319-
/*
2320-
* Copy all capability leafs to pick up the synthetic ones so that
2321-
* memcmp() below doesn't fail on that. The ones coming from CPUID will
2322-
* get overwritten in get_cpu_cap().
2323-
*/
2324-
memcpy(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability));
2325-
2326-
get_cpu_cap(&info);
2340+
store_cpu_caps(&curr_info);
23272341

2328-
if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)))
2342+
if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
2343+
sizeof(prev_info->x86_capability)))
23292344
return;
23302345

23312346
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");

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

Lines changed: 37 additions & 39 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
@@ -330,8 +332,9 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
330332
ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size, true);
331333
if (ret < 0) {
332334
/*
333-
* Patch verification failed, skip to the next
334-
* container, if there's one:
335+
* Patch verification failed, skip to the next container, if
336+
* there is one. Before exit, check whether that container has
337+
* found a patch already. If so, use it.
335338
*/
336339
goto out;
337340
} else if (ret > 0) {
@@ -350,6 +353,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
350353
size -= patch_size + SECTION_HDR_SIZE;
351354
}
352355

356+
out:
353357
/*
354358
* If we have found a patch (desc->mc), it means we're looking at the
355359
* container which has a patch for this CPU so return 0 to mean, @ucode
@@ -364,7 +368,6 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
364368
return 0;
365369
}
366370

367-
out:
368371
return orig_size - size;
369372
}
370373

@@ -414,8 +417,7 @@ static int __apply_microcode_amd(struct microcode_amd *mc)
414417
*
415418
* Returns true if container found (sets @desc), false otherwise.
416419
*/
417-
static bool
418-
apply_microcode_early_amd(u32 cpuid_1_eax, void *ucode, size_t size, bool save_patch)
420+
static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size, bool save_patch)
419421
{
420422
struct cont_desc desc = { 0 };
421423
u8 (*patch)[PATCH_MAX_SIZE];
@@ -428,7 +430,7 @@ apply_microcode_early_amd(u32 cpuid_1_eax, void *ucode, size_t size, bool save_p
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;
@@ -481,7 +483,7 @@ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
481483
return false;
482484
}
483485

484-
static void __load_ucode_amd(unsigned int cpuid_1_eax, struct cpio_data *ret)
486+
static void find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
485487
{
486488
struct ucode_cpu_info *uci;
487489
struct cpio_data cp;
@@ -511,11 +513,11 @@ void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
511513
{
512514
struct cpio_data cp = { };
513515

514-
__load_ucode_amd(cpuid_1_eax, &cp);
516+
find_blobs_in_containers(cpuid_1_eax, &cp);
515517
if (!(cp.data && cp.size))
516518
return;
517519

518-
apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, true);
520+
early_apply_microcode(cpuid_1_eax, cp.data, cp.size, true);
519521
}
520522

521523
void load_ucode_amd_ap(unsigned int cpuid_1_eax)
@@ -546,15 +548,14 @@ void load_ucode_amd_ap(unsigned int cpuid_1_eax)
546548
}
547549
}
548550

549-
__load_ucode_amd(cpuid_1_eax, &cp);
551+
find_blobs_in_containers(cpuid_1_eax, &cp);
550552
if (!(cp.data && cp.size))
551553
return;
552554

553-
apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, false);
555+
early_apply_microcode(cpuid_1_eax, cp.data, cp.size, false);
554556
}
555557

556-
static enum ucode_state
557-
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);
558+
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
558559

559560
int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
560561
{
@@ -572,19 +573,19 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
572573
if (!desc.mc)
573574
return -EINVAL;
574575

575-
ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
576+
ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
576577
if (ret > UCODE_UPDATED)
577578
return -EINVAL;
578579

579580
return 0;
580581
}
581582

582-
void reload_ucode_amd(void)
583+
void reload_ucode_amd(unsigned int cpu)
583584
{
584-
struct microcode_amd *mc;
585585
u32 rev, dummy __always_unused;
586+
struct microcode_amd *mc;
586587

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

589590
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
590591

@@ -816,6 +817,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
816817
return 0;
817818
}
818819

820+
/* Scan the blob in @data and add microcode patches to the cache. */
819821
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
820822
size_t size)
821823
{
@@ -850,9 +852,10 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
850852
return UCODE_OK;
851853
}
852854

853-
static enum ucode_state
854-
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
855+
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
855856
{
857+
struct cpuinfo_x86 *c;
858+
unsigned int nid, cpu;
856859
struct ucode_patch *p;
857860
enum ucode_state ret;
858861

@@ -865,22 +868,22 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
865868
return ret;
866869
}
867870

868-
p = find_patch(0);
869-
if (!p) {
870-
return ret;
871-
} else {
872-
if (boot_cpu_data.microcode >= p->patch_id)
873-
return ret;
871+
for_each_node(nid) {
872+
cpu = cpumask_first(cpumask_of_node(nid));
873+
c = &cpu_data(cpu);
874874

875-
ret = UCODE_NEW;
876-
}
875+
p = find_patch(cpu);
876+
if (!p)
877+
continue;
877878

878-
/* save BSP's matching patch for early load */
879-
if (!save)
880-
return ret;
879+
if (c->microcode >= p->patch_id)
880+
continue;
881881

882-
memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
883-
memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
882+
ret = UCODE_NEW;
883+
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+
}
884887

885888
return ret;
886889
}
@@ -905,14 +908,9 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
905908
{
906909
char fw_name[36] = "amd-ucode/microcode_amd.bin";
907910
struct cpuinfo_x86 *c = &cpu_data(cpu);
908-
bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
909911
enum ucode_state ret = UCODE_NFOUND;
910912
const struct firmware *fw;
911913

912-
/* reload ucode container only on the boot cpu */
913-
if (!bsp)
914-
return UCODE_OK;
915-
916914
if (c->x86 >= 0x15)
917915
snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
918916

@@ -925,7 +923,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
925923
if (!verify_container(fw->data, fw->size, false))
926924
goto fw_release;
927925

928-
ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
926+
ret = load_microcode_amd(c->x86, fw->data, fw->size);
929927

930928
fw_release:
931929
release_firmware(fw);

0 commit comments

Comments
 (0)