]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - 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
CommitLineData
7d777456
GKH
1From a61279422bc32ecbf85e3a6a9349287c7df0b0b1 Mon Sep 17 00:00:00 2001
2From: Joerg Roedel <joerg.roedel@amd.com>
3Date: Mon, 17 May 2010 14:43:35 +0200
4Subject: KVM: SVM: Implement workaround for Erratum 383
5
6This patch implements a workaround for AMD erratum 383 into
7KVM. Without this erratum fix it is possible for a guest to
8kill the host machine. This patch implements the suggested
9workaround for hypervisors which will be published by the
10next revision guide update.
11
12[jan: fix overflow warning on i386]
13[xiao: fix unused variable warning]
14
15Cc: stable@kernel.org
16Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
17Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
18Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
19Signed-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.