Skip to content

Commit

Permalink
x86: kvm: use alternatives for VMCALL vs. VMMCALL if kernel text is r…
Browse files Browse the repository at this point in the history
…ead-only

commit c1118b3 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>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
  • Loading branch information
Paolo Bonzini authored and Ben Hutchings committed Jan 1, 2015
1 parent 85c3fe9 commit 9a8d305
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,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 */
Expand Down
10 changes: 8 additions & 2 deletions arch/x86/include/asm/kvm_para.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,21 @@ struct kvm_vcpu_pv_apf_data {

#ifdef __KERNEL__
#include <asm/processor.h>
#include <asm/alternative.h>

extern void kvmclock_init(void);
extern int kvm_register_clock(char *txt);


/* 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 vmrun or the vmmrun
* instruction. The hypervisor may replace it with something else but only the
Expand Down
7 changes: 7 additions & 0 deletions arch/x86/kernel/cpu/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,13 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
}
#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);
}

static void __cpuinit init_amd(struct cpuinfo_x86 *c)
Expand Down

0 comments on commit 9a8d305

Please sign in to comment.