From 2eff73c0a11f19ff082a566e3429fbaaca7b8e7b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 12 Oct 2015 11:22:41 +0200 Subject: [PATCH] x86/microcode/amd: Extract current patch level read to a function Pave the way for checking the current patch level of the microcode in a core. We want to be able to do stuff depending on the patch level - in this case decide whether to update or not. But that will be added in a later patch. Drop unused local var uci assignment, while at it. Integrate a fix for 32-bit and CONFIG_PARAVIRT from Takashi Iwai: Use native_rdmsr() in check_current_patch_level() because with CONFIG_PARAVIRT enabled and on 32-bit, where we run before paging has been enabled, we cannot deref pv_info yet. Or we could, but we'd need to access its physical address. This way of fixing it is simpler. See: https://bugzilla.suse.com/show_bug.cgi?id=943179 for the background. Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Takashi Iwai : Cc: Thomas Gleixner Cc: Tony Luck Link: http://lkml.kernel.org/r/1444641762-9437-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/microcode_amd.h | 1 + arch/x86/kernel/cpu/microcode/amd.c | 24 +++++++++++++++++++++-- arch/x86/kernel/cpu/microcode/amd_early.c | 17 +++++++--------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index ac6d328977a6..9b214e10d499 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h @@ -76,4 +76,5 @@ static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } void reload_ucode_amd(void) {} #endif +extern bool check_current_patch_level(u32 *rev); #endif /* _ASM_X86_MICROCODE_AMD_H */ diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 12829c3ced3c..2d630138bf3e 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -177,6 +177,25 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size, return patch_size; } +/* + * Check the current patch level on this CPU. + * + * @rev: Use it to return the patch level. It is set to 0 in the case of + * error. + * + * Returns: + * - true: if update should stop + * - false: otherwise + */ +bool check_current_patch_level(u32 *rev) +{ + u32 dummy; + + native_rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy); + + return false; +} + int __apply_microcode_amd(struct microcode_amd *mc_amd) { u32 rev, dummy; @@ -197,7 +216,7 @@ int apply_microcode_amd(int cpu) struct microcode_amd *mc_amd; struct ucode_cpu_info *uci; struct ucode_patch *p; - u32 rev, dummy; + u32 rev; BUG_ON(raw_smp_processor_id() != cpu); @@ -210,7 +229,8 @@ int apply_microcode_amd(int cpu) mc_amd = p->data; uci->mc = p->data; - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + if (check_current_patch_level(&rev)) + return -1; /* need to apply patch? */ if (rev >= mc_amd->hdr.patch_id) { diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index e8a215a9a345..abb90097582f 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c @@ -196,9 +196,8 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) return; } - /* find ucode and update if needed */ - - native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); + if (check_current_patch_level(&rev)) + return; while (left > 0) { struct microcode_amd *mc; @@ -319,7 +318,6 @@ static void __init get_bsp_sig(void) void load_ucode_amd_ap(void) { unsigned int cpu = smp_processor_id(); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct equiv_cpu_entry *eq; struct microcode_amd *mc; u32 rev, eax; @@ -332,10 +330,8 @@ void load_ucode_amd_ap(void) if (!container) return; - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); - - uci->cpu_sig.rev = rev; - uci->cpu_sig.sig = eax; + if (check_current_patch_level(&rev)) + return; eax = cpuid_eax(0x00000001); eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ); @@ -424,9 +420,10 @@ int __init save_microcode_in_initrd_amd(void) void reload_ucode_amd(void) { struct microcode_amd *mc; - u32 rev, eax; + u32 rev; - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); + if (check_current_patch_level(&rev)) + return; mc = (struct microcode_amd *)amd_ucode_patch; -- 2.20.1