Commit e913b8cd authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'microcode_fixes_for_3.19' of...

Merge tag 'microcode_fixes_for_3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp into x86/microcode

Pull x86 microcode fixes from Borislav Petkov:

  "Reload microcode when resuming and the case when only the early loader
   has been utilized.

   Also, do not load the driver on paravirt guests, from Boris Ostrovsky."
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 2ef84b3b fbae4ba8
...@@ -78,6 +78,7 @@ static inline void __exit exit_amd_microcode(void) {} ...@@ -78,6 +78,7 @@ static inline void __exit exit_amd_microcode(void) {}
extern void __init load_ucode_bsp(void); extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void); extern void load_ucode_ap(void);
extern int __init save_microcode_in_initrd(void); extern int __init save_microcode_in_initrd(void);
void reload_early_microcode(void);
#else #else
static inline void __init load_ucode_bsp(void) {} static inline void __init load_ucode_bsp(void) {}
static inline void load_ucode_ap(void) {} static inline void load_ucode_ap(void) {}
...@@ -85,6 +86,7 @@ static inline int __init save_microcode_in_initrd(void) ...@@ -85,6 +86,7 @@ static inline int __init save_microcode_in_initrd(void)
{ {
return 0; return 0;
} }
static inline void reload_early_microcode(void) {}
#endif #endif
#endif /* _ASM_X86_MICROCODE_H */ #endif /* _ASM_X86_MICROCODE_H */
...@@ -68,10 +68,12 @@ extern u8 amd_ucode_patch[PATCH_MAX_SIZE]; ...@@ -68,10 +68,12 @@ extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
extern void __init load_ucode_amd_bsp(void); extern void __init load_ucode_amd_bsp(void);
extern void load_ucode_amd_ap(void); extern void load_ucode_amd_ap(void);
extern int __init save_microcode_in_initrd_amd(void); extern int __init save_microcode_in_initrd_amd(void);
void reload_ucode_amd(void);
#else #else
static inline void __init load_ucode_amd_bsp(void) {} static inline void __init load_ucode_amd_bsp(void) {}
static inline void load_ucode_amd_ap(void) {} static inline void load_ucode_amd_ap(void) {}
static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
void reload_ucode_amd(void) {}
#endif #endif
#endif /* _ASM_X86_MICROCODE_AMD_H */ #endif /* _ASM_X86_MICROCODE_AMD_H */
...@@ -68,11 +68,13 @@ extern void __init load_ucode_intel_bsp(void); ...@@ -68,11 +68,13 @@ extern void __init load_ucode_intel_bsp(void);
extern void load_ucode_intel_ap(void); extern void load_ucode_intel_ap(void);
extern void show_ucode_info_early(void); extern void show_ucode_info_early(void);
extern int __init save_microcode_in_initrd_intel(void); extern int __init save_microcode_in_initrd_intel(void);
void reload_ucode_intel(void);
#else #else
static inline __init void load_ucode_intel_bsp(void) {} static inline __init void load_ucode_intel_bsp(void) {}
static inline void load_ucode_intel_ap(void) {} static inline void load_ucode_intel_ap(void) {}
static inline void show_ucode_info_early(void) {} static inline void show_ucode_info_early(void) {}
static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; }
static inline void reload_ucode_intel(void) {}
#endif #endif
#if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
......
...@@ -402,3 +402,21 @@ int __init save_microcode_in_initrd_amd(void) ...@@ -402,3 +402,21 @@ int __init save_microcode_in_initrd_amd(void)
return retval; return retval;
} }
void reload_ucode_amd(void)
{
struct microcode_amd *mc;
u32 rev, eax;
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
mc = (struct microcode_amd *)amd_ucode_patch;
if (mc && rev < mc->hdr.patch_id) {
if (!__apply_microcode_amd(mc)) {
ucode_new_rev = mc->hdr.patch_id;
pr_info("microcode: reload patch_level=0x%08x\n",
ucode_new_rev);
}
}
}
...@@ -466,13 +466,7 @@ static void mc_bp_resume(void) ...@@ -466,13 +466,7 @@ static void mc_bp_resume(void)
if (uci->valid && uci->mc) if (uci->valid && uci->mc)
microcode_ops->apply_microcode(cpu); microcode_ops->apply_microcode(cpu);
else if (!uci->mc) else if (!uci->mc)
/* reload_early_microcode();
* We might resume and not have applied late microcode but still
* have a newer patch stashed from the early loader. We don't
* have it in uci->mc so we have to load it the same way we're
* applying patches early on the APs.
*/
load_ucode_ap();
} }
static struct syscore_ops mc_syscore_ops = { static struct syscore_ops mc_syscore_ops = {
...@@ -557,7 +551,7 @@ static int __init microcode_init(void) ...@@ -557,7 +551,7 @@ static int __init microcode_init(void)
struct cpuinfo_x86 *c = &cpu_data(0); struct cpuinfo_x86 *c = &cpu_data(0);
int error; int error;
if (dis_ucode_ldr) if (paravirt_enabled() || dis_ucode_ldr)
return 0; return 0;
if (c->x86_vendor == X86_VENDOR_INTEL) if (c->x86_vendor == X86_VENDOR_INTEL)
......
...@@ -176,3 +176,24 @@ int __init save_microcode_in_initrd(void) ...@@ -176,3 +176,24 @@ int __init save_microcode_in_initrd(void)
return 0; return 0;
} }
void reload_early_microcode(void)
{
int vendor, x86;
vendor = x86_vendor();
x86 = x86_family();
switch (vendor) {
case X86_VENDOR_INTEL:
if (x86 >= 6)
reload_ucode_intel();
break;
case X86_VENDOR_AMD:
if (x86 >= 0x10)
reload_ucode_amd();
break;
default:
break;
}
}
...@@ -34,6 +34,8 @@ static struct mc_saved_data { ...@@ -34,6 +34,8 @@ static struct mc_saved_data {
struct microcode_intel **mc_saved; struct microcode_intel **mc_saved;
} mc_saved_data; } mc_saved_data;
static struct microcode_intel bsp_patch;
static enum ucode_state static enum ucode_state
generic_load_microcode_early(struct microcode_intel **mc_saved_p, generic_load_microcode_early(struct microcode_intel **mc_saved_p,
unsigned int mc_saved_count, unsigned int mc_saved_count,
...@@ -650,8 +652,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci) ...@@ -650,8 +652,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
} }
#endif #endif
static int apply_microcode_early(struct mc_saved_data *mc_saved_data, static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
struct ucode_cpu_info *uci)
{ {
struct microcode_intel *mc_intel; struct microcode_intel *mc_intel;
unsigned int val[2]; unsigned int val[2];
...@@ -680,7 +681,10 @@ static int apply_microcode_early(struct mc_saved_data *mc_saved_data, ...@@ -680,7 +681,10 @@ static int apply_microcode_early(struct mc_saved_data *mc_saved_data,
#endif #endif
uci->cpu_sig.rev = val[1]; uci->cpu_sig.rev = val[1];
print_ucode(uci); if (early)
print_ucode(uci);
else
print_ucode_info(uci, mc_intel->hdr.date);
return 0; return 0;
} }
...@@ -713,14 +717,22 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, ...@@ -713,14 +717,22 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
unsigned long *mc_saved_in_initrd, unsigned long *mc_saved_in_initrd,
unsigned long initrd_start_early, unsigned long initrd_start_early,
unsigned long initrd_end_early, unsigned long initrd_end_early,
struct ucode_cpu_info *uci) struct ucode_cpu_info *uci,
struct microcode_intel *bsp)
{ {
enum ucode_state ret;
collect_cpu_info_early(uci); collect_cpu_info_early(uci);
scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data,
mc_saved_in_initrd, uci); mc_saved_in_initrd, uci);
load_microcode(mc_saved_data, mc_saved_in_initrd,
initrd_start_early, uci); ret = load_microcode(mc_saved_data, mc_saved_in_initrd,
apply_microcode_early(mc_saved_data, uci); initrd_start_early, uci);
if (ret == UCODE_OK) {
apply_microcode_early(uci, true);
memcpy(bsp, uci->mc, sizeof(*bsp));
}
} }
void __init void __init
...@@ -729,10 +741,12 @@ load_ucode_intel_bsp(void) ...@@ -729,10 +741,12 @@ load_ucode_intel_bsp(void)
u64 ramdisk_image, ramdisk_size; u64 ramdisk_image, ramdisk_size;
unsigned long initrd_start_early, initrd_end_early; unsigned long initrd_start_early, initrd_end_early;
struct ucode_cpu_info uci; struct ucode_cpu_info uci;
struct microcode_intel *bsp_p;
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
struct boot_params *boot_params_p; struct boot_params *boot_params_p;
boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params);
bsp_p = (struct microcode_intel *)__pa_nodebug(&bsp_patch);
ramdisk_image = boot_params_p->hdr.ramdisk_image; ramdisk_image = boot_params_p->hdr.ramdisk_image;
ramdisk_size = boot_params_p->hdr.ramdisk_size; ramdisk_size = boot_params_p->hdr.ramdisk_size;
initrd_start_early = ramdisk_image; initrd_start_early = ramdisk_image;
...@@ -741,15 +755,17 @@ load_ucode_intel_bsp(void) ...@@ -741,15 +755,17 @@ load_ucode_intel_bsp(void)
_load_ucode_intel_bsp( _load_ucode_intel_bsp(
(struct mc_saved_data *)__pa_nodebug(&mc_saved_data), (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
(unsigned long *)__pa_nodebug(&mc_saved_in_initrd), (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
initrd_start_early, initrd_end_early, &uci); initrd_start_early, initrd_end_early, &uci, bsp_p);
#else #else
bsp_p = &bsp_patch;
ramdisk_image = boot_params.hdr.ramdisk_image; ramdisk_image = boot_params.hdr.ramdisk_image;
ramdisk_size = boot_params.hdr.ramdisk_size; ramdisk_size = boot_params.hdr.ramdisk_size;
initrd_start_early = ramdisk_image + PAGE_OFFSET; initrd_start_early = ramdisk_image + PAGE_OFFSET;
initrd_end_early = initrd_start_early + ramdisk_size; initrd_end_early = initrd_start_early + ramdisk_size;
_load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd,
initrd_start_early, initrd_end_early, &uci); initrd_start_early, initrd_end_early,
&uci, bsp_p);
#endif #endif
} }
...@@ -783,5 +799,17 @@ void load_ucode_intel_ap(void) ...@@ -783,5 +799,17 @@ void load_ucode_intel_ap(void)
collect_cpu_info_early(&uci); collect_cpu_info_early(&uci);
load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
initrd_start_addr, &uci); initrd_start_addr, &uci);
apply_microcode_early(mc_saved_data_p, &uci); apply_microcode_early(&uci, true);
}
void reload_ucode_intel(void)
{
struct ucode_cpu_info uci;
if (!bsp_patch.hdr.rev)
return;
uci.mc = &bsp_patch;
apply_microcode_early(&uci, false);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment