提交 84516098 编写于 作者: T Torsten Kaiser 提交者: Borislav Petkov

x86, microcode, AMD: Fix early microcode loading

load_microcode_amd() (and the helper it is using) should not have an
cpu parameter. The microcode loading does not depend on the CPU wrt the
patches loaded since they will end up in a global list for all CPUs
anyway.

The change from cpu to x86family in load_microcode_amd()
now allows to drop the code messing with cpu_data(cpu) from
collect_cpu_info_amd_early(), which is wrong anyway because at that
point the per-cpu cpu_info is not yet setup (These values would later be
overwritten by smp_store_boot_cpu_info() / smp_store_cpu_info()).

Fold the rest of collect_cpu_info_amd_early() into load_ucode_amd_ap(),
because its only used at one place and without the cpuinfo_x86 accesses
it was not much left.
Signed-off-by: NTorsten Kaiser <just.for.lkml@googlemail.com>
[ Fengguang: build fix ]
Signed-off-by: NFengguang Wu <fengguang.wu@intel.com>
[ Boris: adapt it to current tree. ]
Signed-off-by: NBorislav Petkov <bp@suse.de>
上级 8c6b79bb
...@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table, ...@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
extern int __apply_microcode_amd(struct microcode_amd *mc_amd); extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
extern int apply_microcode_amd(int cpu); extern int apply_microcode_amd(int cpu);
extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size); extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
#ifdef CONFIG_MICROCODE_AMD_EARLY #ifdef CONFIG_MICROCODE_AMD_EARLY
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
......
...@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) ...@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
return 0; return 0;
} }
static unsigned int verify_patch_size(int cpu, u32 patch_size, static unsigned int verify_patch_size(u8 family, u32 patch_size,
unsigned int size) unsigned int size)
{ {
struct cpuinfo_x86 *c = &cpu_data(cpu);
u32 max_size; u32 max_size;
#define F1XH_MPB_MAX_SIZE 2048 #define F1XH_MPB_MAX_SIZE 2048
...@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, ...@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
#define F15H_MPB_MAX_SIZE 4096 #define F15H_MPB_MAX_SIZE 4096
#define F16H_MPB_MAX_SIZE 3458 #define F16H_MPB_MAX_SIZE 3458
switch (c->x86) { switch (family) {
case 0x14: case 0x14:
max_size = F14H_MPB_MAX_SIZE; max_size = F14H_MPB_MAX_SIZE;
break; break;
...@@ -277,9 +276,8 @@ static void cleanup(void) ...@@ -277,9 +276,8 @@ static void cleanup(void)
* driver cannot continue functioning normally. In such cases, we tear * driver cannot continue functioning normally. In such cases, we tear
* down everything we've used up so far and exit. * down everything we've used up so far and exit.
*/ */
static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
{ {
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct microcode_header_amd *mc_hdr; struct microcode_header_amd *mc_hdr;
struct ucode_patch *patch; struct ucode_patch *patch;
unsigned int patch_size, crnt_size, ret; unsigned int patch_size, crnt_size, ret;
...@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) ...@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
/* check if patch is for the current family */ /* check if patch is for the current family */
proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
if (proc_fam != c->x86) if (proc_fam != family)
return crnt_size; return crnt_size;
if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
...@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) ...@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
return crnt_size; return crnt_size;
} }
ret = verify_patch_size(cpu, patch_size, leftover); ret = verify_patch_size(family, patch_size, leftover);
if (!ret) { if (!ret) {
pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
return crnt_size; return crnt_size;
...@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) ...@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
return crnt_size; return crnt_size;
} }
static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size) static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
size_t size)
{ {
enum ucode_state ret = UCODE_ERROR; enum ucode_state ret = UCODE_ERROR;
unsigned int leftover; unsigned int leftover;
...@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz ...@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
} }
while (leftover) { while (leftover) {
crnt_size = verify_and_add_patch(cpu, fw, leftover); crnt_size = verify_and_add_patch(family, fw, leftover);
if (crnt_size < 0) if (crnt_size < 0)
return ret; return ret;
...@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz ...@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
return UCODE_OK; return UCODE_OK;
} }
enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
{ {
enum ucode_state ret; enum ucode_state ret;
/* free old equiv table */ /* free old equiv table */
free_equiv_cpu_table(); free_equiv_cpu_table();
ret = __load_microcode_amd(cpu, data, size); ret = __load_microcode_amd(family, data, size);
if (ret != UCODE_OK) if (ret != UCODE_OK)
cleanup(); cleanup();
#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
/* save BSP's matching patch for early load */ /* save BSP's matching patch for early load */
if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) { if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
struct ucode_patch *p = find_patch(cpu); struct ucode_patch *p = find_patch(smp_processor_id());
if (p) { if (p) {
memset(amd_bsp_mpb, 0, MPB_MAX_SIZE); memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data), memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
...@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, ...@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
goto fw_release; goto fw_release;
} }
ret = load_microcode_amd(cpu, fw->data, fw->size); ret = load_microcode_amd(c->x86, fw->data, fw->size);
fw_release: fw_release:
release_firmware(fw); release_firmware(fw);
......
...@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg) ...@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
uci->cpu_sig.sig = cpuid_eax(0x00000001); uci->cpu_sig.sig = cpuid_eax(0x00000001);
} }
#else #else
static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c, void load_ucode_amd_ap(void)
struct ucode_cpu_info *uci)
{ {
unsigned int cpu = smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
u32 rev, eax; u32 rev, eax;
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
eax = cpuid_eax(0x00000001); eax = cpuid_eax(0x00000001);
uci->cpu_sig.sig = eax;
uci->cpu_sig.rev = rev; uci->cpu_sig.rev = rev;
c->microcode = rev; uci->cpu_sig.sig = eax;
c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
}
void load_ucode_amd_ap(void)
{
unsigned int cpu = smp_processor_id();
collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
if (cpu && !ucode_loaded) { if (cpu && !ucode_loaded) {
void *ucode; void *ucode;
...@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void) ...@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
return; return;
ucode = (void *)(initrd_start + ucode_offset); ucode = (void *)(initrd_start + ucode_offset);
if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK) eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
return; return;
ucode_loaded = true; ucode_loaded = true;
} }
...@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void) ...@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
{ {
enum ucode_state ret; enum ucode_state ret;
void *ucode; void *ucode;
u32 eax;
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
unsigned int bsp = boot_cpu_data.cpu_index; unsigned int bsp = boot_cpu_data.cpu_index;
struct ucode_cpu_info *uci = ucode_cpu_info + bsp; struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
...@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void) ...@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
return 0; return 0;
ucode = (void *)(initrd_start + ucode_offset); ucode = (void *)(initrd_start + ucode_offset);
ret = load_microcode_amd(0, ucode, ucode_size); eax = cpuid_eax(0x00000001);
eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
ret = load_microcode_amd(eax, ucode, ucode_size);
if (ret != UCODE_OK) if (ret != UCODE_OK)
return -EINVAL; return -EINVAL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册