]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.32.17/0003-KVM-SVM-Implement-workaround-for-Erratum-383.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.17 / 0003-KVM-SVM-Implement-workaround-for-Erratum-383.patch
1 From a61279422bc32ecbf85e3a6a9349287c7df0b0b1 Mon Sep 17 00:00:00 2001
2 From: Joerg Roedel <joerg.roedel@amd.com>
3 Date: Mon, 17 May 2010 14:43:35 +0200
4 Subject: KVM: SVM: Implement workaround for Erratum 383
5
6 This patch implements a workaround for AMD erratum 383 into
7 KVM. Without this erratum fix it is possible for a guest to
8 kill the host machine. This patch implements the suggested
9 workaround for hypervisors which will be published by the
10 next revision guide update.
11
12 [jan: fix overflow warning on i386]
13 [xiao: fix unused variable warning]
14
15 Cc: stable@kernel.org
16 Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
17 Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
18 Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
19 Signed-off-by: Avi Kivity <avi@redhat.com>
20 (cherry picked from commit 67ec66077799f2fef84b21a643912b179c422281)
21 ---
22 arch/x86/include/asm/msr-index.h | 1
23 arch/x86/kvm/svm.c | 84 ++++++++++++++++++++++++++++++++++++++-
24 2 files changed, 84 insertions(+), 1 deletion(-)
25
26 --- a/arch/x86/include/asm/msr-index.h
27 +++ b/arch/x86/include/asm/msr-index.h
28 @@ -106,6 +106,7 @@
29 #define MSR_AMD64_PATCH_LOADER 0xc0010020
30 #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
31 #define MSR_AMD64_OSVW_STATUS 0xc0010141
32 +#define MSR_AMD64_DC_CFG 0xc0011022
33 #define MSR_AMD64_IBSFETCHCTL 0xc0011030
34 #define MSR_AMD64_IBSFETCHLINAD 0xc0011031
35 #define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
36 --- a/arch/x86/kvm/svm.c
37 +++ b/arch/x86/kvm/svm.c
38 @@ -27,6 +27,7 @@
39 #include <linux/sched.h>
40 #include <linux/ftrace_event.h>
41
42 +#include <asm/tlbflush.h>
43 #include <asm/desc.h>
44
45 #include <asm/virtext.h>
46 @@ -62,6 +63,8 @@ MODULE_LICENSE("GPL");
47 #define nsvm_printk(fmt, args...) do {} while(0)
48 #endif
49
50 +static bool erratum_383_found __read_mostly;
51 +
52 static const u32 host_save_user_msrs[] = {
53 #ifdef CONFIG_X86_64
54 MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
55 @@ -299,6 +302,31 @@ static void skip_emulated_instruction(st
56 svm_set_interrupt_shadow(vcpu, 0);
57 }
58
59 +static void svm_init_erratum_383(void)
60 +{
61 + u32 low, high;
62 + int err;
63 + u64 val;
64 +
65 + /* Only Fam10h is affected */
66 + if (boot_cpu_data.x86 != 0x10)
67 + return;
68 +
69 + /* Use _safe variants to not break nested virtualization */
70 + val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
71 + if (err)
72 + return;
73 +
74 + val |= (1ULL << 47);
75 +
76 + low = lower_32_bits(val);
77 + high = upper_32_bits(val);
78 +
79 + native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
80 +
81 + erratum_383_found = true;
82 +}
83 +
84 static int has_svm(void)
85 {
86 const char *msg;
87 @@ -318,7 +346,6 @@ static void svm_hardware_disable(void *g
88
89 static void svm_hardware_enable(void *garbage)
90 {
91 -
92 struct svm_cpu_data *svm_data;
93 uint64_t efer;
94 struct descriptor_table gdt_descr;
95 @@ -350,6 +377,10 @@ static void svm_hardware_enable(void *ga
96
97 wrmsrl(MSR_VM_HSAVE_PA,
98 page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
99 +
100 + svm_init_erratum_383();
101 +
102 + return;
103 }
104
105 static void svm_cpu_uninit(int cpu)
106 @@ -1257,8 +1288,59 @@ static int nm_interception(struct vcpu_s
107 return 1;
108 }
109
110 +static bool is_erratum_383(void)
111 +{
112 + int err, i;
113 + u64 value;
114 +
115 + if (!erratum_383_found)
116 + return false;
117 +
118 + value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
119 + if (err)
120 + return false;
121 +
122 + /* Bit 62 may or may not be set for this mce */
123 + value &= ~(1ULL << 62);
124 +
125 + if (value != 0xb600000000010015ULL)
126 + return false;
127 +
128 + /* Clear MCi_STATUS registers */
129 + for (i = 0; i < 6; ++i)
130 + native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
131 +
132 + value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
133 + if (!err) {
134 + u32 low, high;
135 +
136 + value &= ~(1ULL << 2);
137 + low = lower_32_bits(value);
138 + high = upper_32_bits(value);
139 +
140 + native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
141 + }
142 +
143 + /* Flush tlb to evict multi-match entries */
144 + __flush_tlb_all();
145 +
146 + return true;
147 +}
148 +
149 static void svm_handle_mce(struct vcpu_svm *svm)
150 {
151 + if (is_erratum_383()) {
152 + /*
153 + * Erratum 383 triggered. Guest state is corrupt so kill the
154 + * guest.
155 + */
156 + pr_err("KVM: Guest triggered AMD Erratum 383\n");
157 +
158 + set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests);
159 +
160 + return;
161 + }
162 +
163 /*
164 * On an #MC intercept the MCE handler is not called automatically in
165 * the host. So do it by hand here.