Commit 2b385019adf661fa20ae263103096acc4e05447d
Committed by
Greg Kroah-Hartman
1 parent
f886cdf1f8
x86: kvm: use alternatives for VMCALL vs. VMMCALL if kernel text is read-only
commit c1118b3602c2329671ad5ec8bdf8e374323d6343 upstream. On x86_64, kernel text mappings are mapped read-only with CONFIG_DEBUG_RODATA. In that case, KVM will fail to patch VMCALL instructions to VMMCALL as required on AMD processors. The failure mode is currently a divide-by-zero exception, which obviously is a KVM bug that has to be fixed. However, picking the right instruction between VMCALL and VMMCALL will be faster and will help if you cannot upgrade the hypervisor. Reported-by: Chris Webb <chris@arachsys.com> Tested-by: Chris Webb <chris@arachsys.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: x86@kernel.org Acked-by: Borislav Petkov <bp@suse.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Cc: Chris J Arges <chris.j.arges@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 3 changed files with 16 additions and 2 deletions Side-by-side Diff
arch/x86/include/asm/cpufeature.h
... | ... | @@ -202,6 +202,7 @@ |
202 | 202 | #define X86_FEATURE_DECODEASSISTS ( 8*32+12) /* AMD Decode Assists support */ |
203 | 203 | #define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */ |
204 | 204 | #define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */ |
205 | +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ | |
205 | 206 | |
206 | 207 | |
207 | 208 | /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ |
arch/x86/include/asm/kvm_para.h
... | ... | @@ -2,6 +2,7 @@ |
2 | 2 | #define _ASM_X86_KVM_PARA_H |
3 | 3 | |
4 | 4 | #include <asm/processor.h> |
5 | +#include <asm/alternative.h> | |
5 | 6 | #include <uapi/asm/kvm_para.h> |
6 | 7 | |
7 | 8 | extern void kvmclock_init(void); |
8 | 9 | |
... | ... | @@ -16,10 +17,15 @@ |
16 | 17 | } |
17 | 18 | #endif /* CONFIG_KVM_GUEST */ |
18 | 19 | |
19 | -/* This instruction is vmcall. On non-VT architectures, it will generate a | |
20 | - * trap that we will then rewrite to the appropriate instruction. | |
20 | +#ifdef CONFIG_DEBUG_RODATA | |
21 | +#define KVM_HYPERCALL \ | |
22 | + ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) | |
23 | +#else | |
24 | +/* On AMD processors, vmcall will generate a trap that we will | |
25 | + * then rewrite to the appropriate instruction. | |
21 | 26 | */ |
22 | 27 | #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" |
28 | +#endif | |
23 | 29 | |
24 | 30 | /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall |
25 | 31 | * instruction. The hypervisor may replace it with something else but only the |
arch/x86/kernel/cpu/amd.c
... | ... | @@ -525,6 +525,13 @@ |
525 | 525 | } |
526 | 526 | #endif |
527 | 527 | |
528 | + /* | |
529 | + * This is only needed to tell the kernel whether to use VMCALL | |
530 | + * and VMMCALL. VMMCALL is never executed except under virt, so | |
531 | + * we can set it unconditionally. | |
532 | + */ | |
533 | + set_cpu_cap(c, X86_FEATURE_VMMCALL); | |
534 | + | |
528 | 535 | /* F16h erratum 793, CVE-2013-6885 */ |
529 | 536 | if (c->x86 == 0x16 && c->x86_model <= 0xf) |
530 | 537 | msr_set_bit(MSR_AMD64_LS_CFG, 15); |