Commit 2b385019adf661fa20ae263103096acc4e05447d

Authored by Paolo Bonzini
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);