| From c1118b3602c2329671ad5ec8bdf8e374323d6343 Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Mon, 22 Sep 2014 13:17:48 +0200 |
| Subject: x86: kvm: use alternatives for VMCALL vs. VMMCALL if kernel text is read-only |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| 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> |
| Signed-off-by: Chris J Arges <chris.j.arges@canonical.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/include/asm/cpufeature.h | 1 + |
| arch/x86/include/asm/kvm_para.h | 10 ++++++++-- |
| arch/x86/kernel/cpu/amd.c | 7 +++++++ |
| 3 files changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/include/asm/cpufeature.h |
| +++ b/arch/x86/include/asm/cpufeature.h |
| @@ -203,6 +203,7 @@ |
| #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ |
| #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ |
| #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ |
| +#define X86_FEATURE_VMMCALL (8*32+15) /* Prefer vmmcall to vmcall */ |
| |
| |
| /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ |
| --- a/arch/x86/include/asm/kvm_para.h |
| +++ b/arch/x86/include/asm/kvm_para.h |
| @@ -2,6 +2,7 @@ |
| #define _ASM_X86_KVM_PARA_H |
| |
| #include <asm/processor.h> |
| +#include <asm/alternative.h> |
| #include <uapi/asm/kvm_para.h> |
| |
| extern void kvmclock_init(void); |
| @@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_g |
| } |
| #endif /* CONFIG_KVM_GUEST */ |
| |
| -/* This instruction is vmcall. On non-VT architectures, it will generate a |
| - * trap that we will then rewrite to the appropriate instruction. |
| +#ifdef CONFIG_DEBUG_RODATA |
| +#define KVM_HYPERCALL \ |
| + ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) |
| +#else |
| +/* On AMD processors, vmcall will generate a trap that we will |
| + * then rewrite to the appropriate instruction. |
| */ |
| #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" |
| +#endif |
| |
| /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall |
| * instruction. The hypervisor may replace it with something else but only the |
| --- a/arch/x86/kernel/cpu/amd.c |
| +++ b/arch/x86/kernel/cpu/amd.c |
| @@ -508,6 +508,13 @@ static void early_init_amd(struct cpuinf |
| } |
| #endif |
| |
| + /* |
| + * This is only needed to tell the kernel whether to use VMCALL |
| + * and VMMCALL. VMMCALL is never executed except under virt, so |
| + * we can set it unconditionally. |
| + */ |
| + set_cpu_cap(c, X86_FEATURE_VMMCALL); |
| + |
| /* F16h erratum 793, CVE-2013-6885 */ |
| if (c->x86 == 0x16 && c->x86_model <= 0xf) { |
| u64 val; |