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
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.
12 [jan: fix overflow warning on i386]
13 [xiao: fix unused variable warning]
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)
22 arch/x86/include/asm/msr-index.h | 1
23 arch/x86/kvm/svm.c | 84 ++++++++++++++++++++++++++++++++++++++-
24 2 files changed, 84 insertions(+), 1 deletion(-)
26 --- a/arch/x86/include/asm/msr-index.h
27 +++ b/arch/x86/include/asm/msr-index.h
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
39 #include <linux/sched.h>
40 #include <linux/ftrace_event.h>
42 +#include <asm/tlbflush.h>
45 #include <asm/virtext.h>
46 @@ -62,6 +63,8 @@ MODULE_LICENSE("GPL");
47 #define nsvm_printk(fmt, args...) do {} while(0)
50 +static bool erratum_383_found __read_mostly;
52 static const u32 host_save_user_msrs[] = {
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);
59 +static void svm_init_erratum_383(void)
65 + /* Only Fam10h is affected */
66 + if (boot_cpu_data.x86 != 0x10)
69 + /* Use _safe variants to not break nested virtualization */
70 + val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
74 + val |= (1ULL << 47);
76 + low = lower_32_bits(val);
77 + high = upper_32_bits(val);
79 + native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
81 + erratum_383_found = true;
84 static int has_svm(void)
87 @@ -318,7 +346,6 @@ static void svm_hardware_disable(void *g
89 static void svm_hardware_enable(void *garbage)
92 struct svm_cpu_data *svm_data;
94 struct descriptor_table gdt_descr;
95 @@ -350,6 +377,10 @@ static void svm_hardware_enable(void *ga
97 wrmsrl(MSR_VM_HSAVE_PA,
98 page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
100 + svm_init_erratum_383();
105 static void svm_cpu_uninit(int cpu)
106 @@ -1257,8 +1288,59 @@ static int nm_interception(struct vcpu_s
110 +static bool is_erratum_383(void)
115 + if (!erratum_383_found)
118 + value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
122 + /* Bit 62 may or may not be set for this mce */
123 + value &= ~(1ULL << 62);
125 + if (value != 0xb600000000010015ULL)
128 + /* Clear MCi_STATUS registers */
129 + for (i = 0; i < 6; ++i)
130 + native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
132 + value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
136 + value &= ~(1ULL << 2);
137 + low = lower_32_bits(value);
138 + high = upper_32_bits(value);
140 + native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
143 + /* Flush tlb to evict multi-match entries */
149 static void svm_handle_mce(struct vcpu_svm *svm)
151 + if (is_erratum_383()) {
153 + * Erratum 383 triggered. Guest state is corrupt so kill the
156 + pr_err("KVM: Guest triggered AMD Erratum 383\n");
158 + set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests);
164 * On an #MC intercept the MCE handler is not called automatically in
165 * the host. So do it by hand here.