summaryrefslogtreecommitdiffstats
path: root/system/xen/xsa/xsa305-4.12-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/xen/xsa/xsa305-4.12-1.patch')
-rw-r--r--system/xen/xsa/xsa305-4.12-1.patch288
1 files changed, 288 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa305-4.12-1.patch b/system/xen/xsa/xsa305-4.12-1.patch
new file mode 100644
index 0000000000..e1a91a5264
--- /dev/null
+++ b/system/xen/xsa/xsa305-4.12-1.patch
@@ -0,0 +1,288 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: x86/tsx: Introduce tsx= to use MSR_TSX_CTRL when available
+
+To protect against the TSX Async Abort speculative vulnerability, Intel have
+released new microcode for affected parts which introduce the MSR_TSX_CTRL
+control, which allows TSX to be turned off. This will be architectural on
+future parts.
+
+Introduce tsx= to provide a global on/off for TSX, including its enumeration
+via CPUID. Provide stub virtualisation of this MSR, as it is not exposed to
+guests at the moment.
+
+VMs may have booted before microcode is loaded, or before hosts have rebooted,
+and they still want to migrate freely. A VM which booted seeing TSX can
+migrate safely to hosts with TSX disabled - TSX will start unconditionally
+aborting, but still behave in a manner compatible with the ABI.
+
+The guest-visible behaviour is equivalent to late loading the microcode and
+setting the RTM_DISABLE bit in the course of live patching.
+
+This is part of XSA-305 / CVE-2019-11135
+
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
+index e283017015..b7e1bf8e8b 100644
+--- a/docs/misc/xen-command-line.pandoc
++++ b/docs/misc/xen-command-line.pandoc
+@@ -2033,6 +2033,20 @@ Xen version.
+ ### tsc (x86)
+ > `= unstable | skewed | stable:socket`
+
++### tsx
++ = <bool>
++
++ Applicability: x86
++ Default: true
++
++Controls for the use of Transactional Synchronization eXtensions.
++
++On Intel parts released in Q3 2019 (with updated microcode), and future parts,
++a control has been introduced which allows TSX to be turned off.
++
++On systems with the ability to turn TSX off, this boolean offers system wide
++control of whether TSX is enabled or disabled.
++
+ ### ucode (x86)
+ > `= [<integer> | scan]`
+
+diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
+index 8a8d8f060f..9b9a4435fb 100644
+--- a/xen/arch/x86/Makefile
++++ b/xen/arch/x86/Makefile
+@@ -66,6 +66,7 @@ obj-y += sysctl.o
+ obj-y += time.o
+ obj-y += trace.o
+ obj-y += traps.o
++obj-y += tsx.o
+ obj-y += usercopy.o
+ obj-y += x86_emulate.o
+ obj-$(CONFIG_TBOOT) += tboot.o
+diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
+index 57e80694f2..1727497459 100644
+--- a/xen/arch/x86/cpuid.c
++++ b/xen/arch/x86/cpuid.c
+@@ -524,6 +524,20 @@ void recalculate_cpuid_policy(struct domain *d)
+ if ( cpu_has_itsc && (d->disable_migrate || d->arch.vtsc) )
+ __set_bit(X86_FEATURE_ITSC, max_fs);
+
++ /*
++ * On hardware with MSR_TSX_CTRL, the admin may have elected to disable
++ * TSX and hide the feature bits. Migrating-in VMs may have been booted
++ * pre-mitigation when the TSX features were visbile.
++ *
++ * This situation is compatible (albeit with a perf hit to any TSX code in
++ * the guest), so allow the feature bits to remain set.
++ */
++ if ( cpu_has_tsx_ctrl )
++ {
++ __set_bit(X86_FEATURE_HLE, max_fs);
++ __set_bit(X86_FEATURE_RTM, max_fs);
++ }
++
+ /* Clamp the toolstacks choices to reality. */
+ for ( i = 0; i < ARRAY_SIZE(fs); i++ )
+ fs[i] &= max_fs[i];
+diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
+index 56de0fe9e1..c2722d7c73 100644
+--- a/xen/arch/x86/msr.c
++++ b/xen/arch/x86/msr.c
+@@ -132,6 +132,7 @@ int guest_rdmsr(const struct vcpu *v, uint32_t msr, uint64_t *val)
+ case MSR_FLUSH_CMD:
+ /* Write-only */
+ case MSR_TSX_FORCE_ABORT:
++ case MSR_TSX_CTRL:
+ /* Not offered to guests. */
+ goto gp_fault;
+
+@@ -260,6 +261,7 @@ int guest_wrmsr(struct vcpu *v, uint32_t msr, uint64_t val)
+ case MSR_ARCH_CAPABILITIES:
+ /* Read-only */
+ case MSR_TSX_FORCE_ABORT:
++ case MSR_TSX_CTRL:
+ /* Not offered to guests. */
+ goto gp_fault;
+
+diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
+index cf790f36ef..c1c7c44000 100644
+--- a/xen/arch/x86/setup.c
++++ b/xen/arch/x86/setup.c
+@@ -1594,6 +1594,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
+
+ early_microcode_init();
+
++ tsx_init(); /* Needs microcode. May change HLE/RTM feature bits. */
++
+ identify_cpu(&boot_cpu_data);
+
+ set_in_cr4(X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT);
+diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
+index 737a44f055..e21cf0a310 100644
+--- a/xen/arch/x86/smpboot.c
++++ b/xen/arch/x86/smpboot.c
+@@ -376,6 +376,8 @@ void start_secondary(void *unused)
+ if ( boot_cpu_has(X86_FEATURE_IBRSB) )
+ wrmsrl(MSR_SPEC_CTRL, default_xen_spec_ctrl);
+
++ tsx_init(); /* Needs microcode. May change HLE/RTM feature bits. */
++
+ if ( xen_guest )
+ hypervisor_ap_setup();
+
+diff --git a/xen/arch/x86/tsx.c b/xen/arch/x86/tsx.c
+new file mode 100644
+index 0000000000..a8ec2ccc69
+--- /dev/null
++++ b/xen/arch/x86/tsx.c
+@@ -0,0 +1,74 @@
++#include <xen/init.h>
++#include <asm/msr.h>
++
++/*
++ * Valid values:
++ * 1 => Explicit tsx=1
++ * 0 => Explicit tsx=0
++ * -1 => Default, implicit tsx=1
++ *
++ * This is arranged such that the bottom bit encodes whether TSX is actually
++ * disabled, while identifying various explicit (>=0) and implicit (<0)
++ * conditions.
++ */
++int8_t __read_mostly opt_tsx = -1;
++int8_t __read_mostly cpu_has_tsx_ctrl = -1;
++
++static int __init parse_tsx(const char *s)
++{
++ int rc = 0, val = parse_bool(s, NULL);
++
++ if ( val >= 0 )
++ opt_tsx = val;
++ else
++ rc = -EINVAL;
++
++ return rc;
++}
++custom_param("tsx", parse_tsx);
++
++void tsx_init(void)
++{
++ /*
++ * This function is first called between microcode being loaded, and CPUID
++ * being scanned generally. Calculate from raw data whether MSR_TSX_CTRL
++ * is available.
++ */
++ if ( unlikely(cpu_has_tsx_ctrl < 0) )
++ {
++ uint64_t caps = 0;
++
++ if ( boot_cpu_data.cpuid_level >= 7 &&
++ (cpuid_count_edx(7, 0) & cpufeat_mask(X86_FEATURE_ARCH_CAPS)) )
++ rdmsrl(MSR_ARCH_CAPABILITIES, caps);
++
++ cpu_has_tsx_ctrl = !!(caps & ARCH_CAPS_TSX_CTRL);
++ }
++
++ if ( cpu_has_tsx_ctrl )
++ {
++ uint64_t val;
++
++ rdmsrl(MSR_TSX_CTRL, val);
++
++ val &= ~(TSX_CTRL_RTM_DISABLE | TSX_CTRL_CPUID_CLEAR);
++ /* Check bottom bit only. Higher bits are various sentinals. */
++ if ( !(opt_tsx & 1) )
++ val |= TSX_CTRL_RTM_DISABLE | TSX_CTRL_CPUID_CLEAR;
++
++ wrmsrl(MSR_TSX_CTRL, val);
++ }
++ else if ( opt_tsx >= 0 )
++ printk_once(XENLOG_WARNING
++ "MSR_TSX_CTRL not available - Ignoring tsx= setting\n");
++}
++
++/*
++ * Local variables:
++ * mode: C
++ * c-file-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h
+index 32746aa8ae..d5f3899f73 100644
+--- a/xen/include/asm-x86/msr-index.h
++++ b/xen/include/asm-x86/msr-index.h
+@@ -53,6 +53,7 @@
+ #define ARCH_CAPS_SSB_NO (_AC(1, ULL) << 4)
+ #define ARCH_CAPS_MDS_NO (_AC(1, ULL) << 5)
+ #define ARCH_CAPS_IF_PSCHANGE_MC_NO (_AC(1, ULL) << 6)
++#define ARCH_CAPS_TSX_CTRL (_AC(1, ULL) << 7)
+
+ #define MSR_FLUSH_CMD 0x0000010b
+ #define FLUSH_CMD_L1D (_AC(1, ULL) << 0)
+@@ -60,6 +61,10 @@
+ #define MSR_TSX_FORCE_ABORT 0x0000010f
+ #define TSX_FORCE_ABORT_RTM (_AC(1, ULL) << 0)
+
++#define MSR_TSX_CTRL 0x00000122
++#define TSX_CTRL_RTM_DISABLE (_AC(1, ULL) << 0)
++#define TSX_CTRL_CPUID_CLEAR (_AC(1, ULL) << 1)
++
+ /* Intel MSRs. Some also available on other CPUs */
+ #define MSR_IA32_PERFCTR0 0x000000c1
+ #define MSR_IA32_A_PERFCTR0 0x000004c1
+diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
+index d33ac34d29..1b52712180 100644
+--- a/xen/include/asm-x86/processor.h
++++ b/xen/include/asm-x86/processor.h
+@@ -263,6 +263,16 @@ static always_inline unsigned int cpuid_count_ebx(
+ return ebx;
+ }
+
++static always_inline unsigned int cpuid_count_edx(
++ unsigned int leaf, unsigned int subleaf)
++{
++ unsigned int edx, tmp;
++
++ cpuid_count(leaf, subleaf, &tmp, &tmp, &tmp, &edx);
++
++ return edx;
++}
++
+ static inline unsigned long read_cr0(void)
+ {
+ unsigned long cr0;
+@@ -609,6 +619,9 @@ static inline uint8_t get_cpu_family(uint32_t raw, uint8_t *model,
+ return fam;
+ }
+
++extern int8_t opt_tsx, cpu_has_tsx_ctrl;
++void tsx_init(void);
++
+ #endif /* !__ASSEMBLY__ */
+
+ #endif /* __ASM_X86_PROCESSOR_H */
+diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
+index 89939f43c8..6529f12dae 100644
+--- a/xen/include/xen/lib.h
++++ b/xen/include/xen/lib.h
+@@ -114,6 +114,16 @@ extern int printk_ratelimit(void);
+ #define gprintk(lvl, fmt, args...) \
+ printk(XENLOG_GUEST lvl "%pv " fmt, current, ## args)
+
++#define printk_once(fmt, args...) \
++({ \
++ static bool __read_mostly once_; \
++ if ( unlikely(!once_) ) \
++ { \
++ once_ = true; \
++ printk(fmt, ## args); \
++ } \
++})
++
+ #ifdef NDEBUG
+
+ static inline void