[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6.5 22/26] x86/boot: Calculate the most appropriate BTI mitigation to use
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- v4: * New v5: * Whitespace fixes --- docs/misc/xen-command-line.markdown | 6 ++- xen/arch/x86/spec_ctrl.c | 103 ++++++++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index 19e12ac..3429484 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -246,7 +246,7 @@ enough. Setting this to a high value may cause boot failure, particularly if the NMI watchdog is also enabled. ### bti (x86) -> `= List of [ thunk=retpoline|lfence|plain ]` +> `= List of [ thunk=retpoline|lfence|plain, ibrs=<bool> ]` Branch Target Injection controls. By default, Xen will pick the most appropriate BTI mitigations based on compiled in support, loaded microcode, @@ -259,6 +259,10 @@ select which of the thunks gets patched into the `__x86.indirect_thunk.%reg` locations. The default thunk is `retpoline`, with the alternatives being `plain` (a `jmp *%reg` gadget), and `lfence` (an `lfence; jmp *%reg` gadget). +On hardware supporting IBRS, the `ibrs=` option can be used to force or +prevent Xen using the feature itself. If Xen is not using IBRS itself, +functionality is still set up so IBRS can be virtualised for guests. + ### xenheap\_megabytes (arm32) > `= <size>` diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c index d9ace2d..1cccb8a 100644 --- a/xen/arch/x86/spec_ctrl.c +++ b/xen/arch/x86/spec_ctrl.c @@ -20,6 +20,7 @@ #include <xen/init.h> #include <xen/lib.h> +#include <asm/microcode.h> #include <asm/processor.h> #include <asm/spec_ctrl.h> @@ -31,11 +32,12 @@ enum ind_thunk { THUNK_LFENCE, THUNK_JMP, } opt_thunk __initdata = THUNK_DEFAULT; +int opt_ibrs __initdata = -1; static int __init parse_bti(const char *s) { const char *ss; - int rc = 0; + int val, rc = 0; do { ss = strchr(s, ','); @@ -55,6 +57,8 @@ static int __init parse_bti(const char *s) else rc = -EINVAL; } + else if ( (val = parse_boolean("ibrs", s, ss)) >= 0 ) + opt_ibrs = val; else rc = -EINVAL; @@ -91,24 +95,82 @@ static void __init print_details(enum ind_thunk thunk) printk(XENLOG_DEBUG " Compiled-in support: INDIRECT_THUNK\n"); printk(XENLOG_INFO - "BTI mitigations: Thunk %s\n", + "BTI mitigations: Thunk %s, Others:%s\n", thunk == THUNK_NONE ? "N/A" : thunk == THUNK_RETPOLINE ? "RETPOLINE" : thunk == THUNK_LFENCE ? "LFENCE" : - thunk == THUNK_JMP ? "JMP" : "?"); + thunk == THUNK_JMP ? "JMP" : "?", + boot_cpu_has(X86_FEATURE_XEN_IBRS_SET) ? " IBRS+" : + boot_cpu_has(X86_FEATURE_XEN_IBRS_CLEAR) ? " IBRS-" : ""); +} + +/* Calculate whether Retpoline is known-safe on this CPU. */ +static bool __init retpoline_safe(void) +{ + unsigned int ucode_rev = this_cpu(ucode_cpu_info).cpu_sig.rev; + + if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) + return true; + + if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || + boot_cpu_data.x86 != 6 ) + return false; + + switch ( boot_cpu_data.x86_model ) + { + case 0x17: /* Penryn */ + case 0x1d: /* Dunnington */ + case 0x1e: /* Nehalem */ + case 0x1f: /* Auburndale / Havendale */ + case 0x1a: /* Nehalem EP */ + case 0x2e: /* Nehalem EX */ + case 0x25: /* Westmere */ + case 0x2c: /* Westmere EP */ + case 0x2f: /* Westmere EX */ + case 0x2a: /* SandyBridge */ + case 0x2d: /* SandyBridge EP/EX */ + case 0x3a: /* IvyBridge */ + case 0x3e: /* IvyBridge EP/EX */ + case 0x3c: /* Haswell */ + case 0x3f: /* Haswell EX/EP */ + case 0x45: /* Haswell D */ + case 0x46: /* Haswell H */ + return true; + + /* + * Broadwell processors are retpoline-safe after specific microcode + * versions. + */ + case 0x3d: /* Broadwell */ + return ucode_rev >= 0x28; + case 0x47: /* Broadwell H */ + return ucode_rev >= 0x1b; + case 0x4f: /* Broadwell EP/EX */ + return ucode_rev >= 0xb000025; + case 0x56: /* Broadwell D */ + return false; /* TBD. */ + + /* + * Skylake and later processors are not retpoline-safe. + */ + default: + return false; + } } void __init init_speculation_mitigations(void) { enum ind_thunk thunk = THUNK_DEFAULT; + bool ibrs = false; /* * Has the user specified any custom BTI mitigations? If so, follow their * instructions exactly and disable all heuristics. */ - if ( opt_thunk != THUNK_DEFAULT ) + if ( opt_thunk != THUNK_DEFAULT || opt_ibrs != -1 ) { thunk = opt_thunk; + ibrs = !!opt_ibrs; } else { @@ -124,7 +186,21 @@ void __init init_speculation_mitigations(void) */ if ( cpu_has_lfence_dispatch ) thunk = THUNK_LFENCE; + /* + * On Intel hardware, we'd like to use retpoline in preference to + * IBRS, but only if it is safe on this hardware. + */ + else if ( boot_cpu_has(X86_FEATURE_IBRSB) ) + { + if ( retpoline_safe() ) + thunk = THUNK_RETPOLINE; + else + ibrs = true; + } } + /* Without compiler thunk support, use IBRS if available. */ + else if ( boot_cpu_has(X86_FEATURE_IBRSB) ) + ibrs = true; } /* @@ -135,6 +211,13 @@ void __init init_speculation_mitigations(void) thunk = THUNK_NONE; /* + * If IBRS is in use and thunks are compiled in, there is no point + * suffering extra overhead. Switch to the least-overhead thunk. + */ + if ( ibrs && thunk == THUNK_DEFAULT ) + thunk = THUNK_JMP; + + /* * If there are still no thunk preferences, the compiled default is * actually retpoline, and it is better than nothing. */ @@ -147,6 +230,18 @@ void __init init_speculation_mitigations(void) else if ( thunk == THUNK_JMP ) setup_force_cpu_cap(X86_FEATURE_IND_THUNK_JMP); + /* + * Even if we've chosen not to use IBRS for Xen itself, we still need the + * IBRS entry/exit logic to virtualise IBRS support for guests. + */ + if ( boot_cpu_has(X86_FEATURE_IBRSB) ) + { + if ( ibrs ) + setup_force_cpu_cap(X86_FEATURE_XEN_IBRS_SET); + else + setup_force_cpu_cap(X86_FEATURE_XEN_IBRS_CLEAR); + } + print_details(thunk); } -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |