From: Borislav Petkov <[email protected]> Having tracepoints to the MSR accessors makes them unsuitable for early microcode loading: think 32-bit before paging is enabled and us chasing pointers to test whether a tracepoint is enabled or not. Results in a reliable triple fault.
Thus, define microcode loader-specific MSR accessors which do the bare minimum of reading or writing an MSR and nothing more. Signed-off-by: Borislav Petkov <[email protected]> --- arch/x86/include/asm/microcode.h | 29 +++++++++++++++++++++-------- arch/x86/include/asm/microcode_intel.h | 4 ++-- arch/x86/kernel/cpu/microcode/amd.c | 6 +++--- arch/x86/kernel/cpu/microcode/intel.c | 4 ++-- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 38711df3bcb5..fbecea6e46e2 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -5,20 +5,33 @@ #include <linux/earlycpio.h> #include <linux/initrd.h> -#define native_rdmsr(msr, val1, val2) \ +static inline unsigned long long __rdmsr(unsigned int msr) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("1: rdmsr\n" + "2:\n" + : EAX_EDX_RET(val, low, high) : "c" (msr)); + return EAX_EDX_VAL(val, low, high); +} + +#define microcode_rdmsr(msr, val1, val2) \ do { \ - u64 __val = native_read_msr((msr)); \ + u64 __val = __rdmsr((msr)); \ (void)((val1) = (u32)__val); \ (void)((val2) = (u32)(__val >> 32)); \ } while (0) -#define native_wrmsr(msr, low, high) \ - native_write_msr(msr, low, high) +static inline void microcode_wrmsr(unsigned int msr, u64 val) +{ + u32 low, high; + + low = (u32)val; + high = (u32)(val >> 32); -#define native_wrmsrl(msr, val) \ - native_write_msr((msr), \ - (u32)((u64)(val)), \ - (u32)((u64)(val) >> 32)) + asm volatile("wrmsr\n" + :: "c" (msr), "a"(low), "d" (high) : "memory"); +} struct ucode_patch { struct list_head plist; diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index e793fc9a9b20..7330b2b79484 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -56,13 +56,13 @@ static inline u32 intel_get_microcode_revision(void) { u32 rev, dummy; - native_wrmsrl(MSR_IA32_UCODE_REV, 0); + microcode_wrmsr(MSR_IA32_UCODE_REV, 0); /* As documented in the SDM: Do a CPUID 1 here */ native_cpuid_eax(1); /* get the current revision from MSR 0x8B */ - native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev); + microcode_rdmsr(MSR_IA32_UCODE_REV, dummy, rev); return rev; } diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 6a31e2691f3a..3f89e6712afe 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -198,10 +198,10 @@ static int __apply_microcode_amd(struct microcode_amd *mc_amd) { u32 rev, dummy; - native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); + microcode_wrmsr(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); /* verify patch application was successful */ - native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + microcode_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); if (rev != mc_amd->hdr.patch_id) return -1; @@ -656,7 +656,7 @@ bool check_current_patch_level(u32 *rev, bool early) bool ret = false; u32 *levels; - native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy); + microcode_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy); if (IS_ENABLED(CONFIG_X86_32) && early) levels = (u32 *)__pa_nodebug(&final_levels); diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 8325d8a09ab0..1c6f12fa3108 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -387,7 +387,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) if ((model >= 5) || (family > 6)) { /* get processor flags from MSR 0x17 */ - native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); + microcode_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); csig.pf = 1 << ((val[1] >> 18) & 7); } @@ -582,7 +582,7 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) return 0; /* write microcode via MSR 0x79 */ - native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); + microcode_wrmsr(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); rev = intel_get_microcode_revision(); if (rev != mc->hdr.rev) -- 2.11.0

