From 8335c8aedacd9a50b4796afb533dc8205f2129e4 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Wed, 14 Feb 2018 12:42:31 +0100 Subject: [PATCH] x86/amd: Try to set lfence as being Dispatch Serialising This property is required for the AMD's recommended mitigation for Branch Target Injection, but Xen needs to cope with being unable to detect or modify the MSR. This is part of XSA-254. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich master commit: fe3ee5530a8d0d0b6a478167125d00c40f294a86 master date: 2018-01-16 17:45:50 +0000 --- xen/arch/x86/cpu/amd.c | 32 ++++++++++++++++++++++++++++++++ xen/include/asm-x86/cpufeature.h | 2 ++ xen/include/asm-x86/msr-index.h | 1 + 3 files changed, 35 insertions(+) diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c index 7c2b241624..9d27e2afcb 100644 --- a/xen/arch/x86/cpu/amd.c +++ b/xen/arch/x86/cpu/amd.c @@ -464,6 +464,38 @@ static void __devinit init_amd(struct cpuinfo_x86 *c) wrmsr_amd_safe(0xc001100d, l, h & ~1); } + /* + * Attempt to set lfence to be Dispatch Serialising. This MSR almost + * certainly isn't virtualised (and Xen at least will leak the real + * value in but silently discard writes), as well as being per-core + * rather than per-thread, so do a full safe read/write/readback cycle + * in the worst case. + */ + if (c->x86 == 0x0f || c->x86 == 0x11) + /* Always dispatch serialising on this hardare. */ + __set_bit(X86_FEATURE_LFENCE_DISPATCH, c->x86_capability); + else /* Implicily "== 0x10 || >= 0x12" by being 64bit. */ { + if (rdmsr_safe(MSR_AMD64_DE_CFG, value)) + /* Unable to read. Assume the safer default. */ + __clear_bit(X86_FEATURE_LFENCE_DISPATCH, + c->x86_capability); + else if (value & AMD64_DE_CFG_LFENCE_SERIALISE) + /* Already dispatch serialising. */ + __set_bit(X86_FEATURE_LFENCE_DISPATCH, + c->x86_capability); + else if (wrmsr_safe(MSR_AMD64_DE_CFG, + value | AMD64_DE_CFG_LFENCE_SERIALISE) || + rdmsr_safe(MSR_AMD64_DE_CFG, value) || + !(value & AMD64_DE_CFG_LFENCE_SERIALISE)) + /* Attempt to set failed. Assume the safer default. */ + __clear_bit(X86_FEATURE_LFENCE_DISPATCH, + c->x86_capability); + else + /* Successfully enabled! */ + __set_bit(X86_FEATURE_LFENCE_DISPATCH, + c->x86_capability); + } + switch(c->x86) { case 0xf ... 0x17: diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index a7e36ae752..0dece34a00 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -61,6 +61,7 @@ /* Other features, Linux-defined mapping, word 3 */ /* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_LFENCE_DISPATCH (3*32+ 0) /* lfence set as Dispatch Serialising */ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ #define X86_FEATURE_NONSTOP_TSC (3*32+ 9) /* TSC does not stop in C states */ #define X86_FEATURE_ARAT (3*32+ 10) /* Always running APIC timer */ @@ -220,6 +221,7 @@ #define cpu_has_vmx boot_cpu_has(X86_FEATURE_VMXE) #define cpu_has_cpuid_faulting boot_cpu_has(X86_FEATURE_CPUID_FAULTING) +#define cpu_has_lfence_dispatch boot_cpu_has(X86_FEATURE_LFENCE_DISPATCH) #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h index d18860283a..6fae144a67 100644 --- a/xen/include/asm-x86/msr-index.h +++ b/xen/include/asm-x86/msr-index.h @@ -208,6 +208,7 @@ #define MSR_AMD64_IC_CFG 0xc0011021 #define MSR_AMD64_DC_CFG 0xc0011022 #define MSR_AMD64_DE_CFG 0xc0011029 +#define AMD64_DE_CFG_LFENCE_SERIALISE (_AC(1, ULL) << 1) #define MSR_AMD64_DR0_ADDRESS_MASK 0xc0011027 #define MSR_AMD64_DR1_ADDRESS_MASK 0xc0011019 -- 2.39.5