aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2011-05-25 16:02:54 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 04:45:09 -0400
commitec378aeef9dfc7c4ba72e9bd6cd4bd6f7d5fd0cc (patch)
treed6ae108db5cae27c7b07fa16f78c5eaafa2096d9 /arch/x86/kvm/vmx.c
parent801d342432190947928e18f893f073fd87cd8bdf (diff)
KVM: nVMX: Implement VMXON and VMXOFF
This patch allows a guest to use the VMXON and VMXOFF instructions, and emulates them accordingly. Basically this amounts to checking some prerequisites, and then remembering whether the guest has enabled or disabled VMX operation. Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c110
1 files changed, 108 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 263be2debde8..3a727ca02f24 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -144,6 +144,15 @@ struct shared_msr_entry {
144 u64 mask; 144 u64 mask;
145}; 145};
146 146
147/*
148 * The nested_vmx structure is part of vcpu_vmx, and holds information we need
149 * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
150 */
151struct nested_vmx {
152 /* Has the level1 guest done vmxon? */
153 bool vmxon;
154};
155
147struct vcpu_vmx { 156struct vcpu_vmx {
148 struct kvm_vcpu vcpu; 157 struct kvm_vcpu vcpu;
149 unsigned long host_rsp; 158 unsigned long host_rsp;
@@ -203,6 +212,9 @@ struct vcpu_vmx {
203 u32 exit_reason; 212 u32 exit_reason;
204 213
205 bool rdtscp_enabled; 214 bool rdtscp_enabled;
215
216 /* Support for a guest hypervisor (nested VMX) */
217 struct nested_vmx nested;
206}; 218};
207 219
208enum segment_cache_field { 220enum segment_cache_field {
@@ -3934,6 +3946,99 @@ static int handle_invalid_op(struct kvm_vcpu *vcpu)
3934} 3946}
3935 3947
3936/* 3948/*
3949 * Emulate the VMXON instruction.
3950 * Currently, we just remember that VMX is active, and do not save or even
3951 * inspect the argument to VMXON (the so-called "VMXON pointer") because we
3952 * do not currently need to store anything in that guest-allocated memory
3953 * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their
3954 * argument is different from the VMXON pointer (which the spec says they do).
3955 */
3956static int handle_vmon(struct kvm_vcpu *vcpu)
3957{
3958 struct kvm_segment cs;
3959 struct vcpu_vmx *vmx = to_vmx(vcpu);
3960
3961 /* The Intel VMX Instruction Reference lists a bunch of bits that
3962 * are prerequisite to running VMXON, most notably cr4.VMXE must be
3963 * set to 1 (see vmx_set_cr4() for when we allow the guest to set this).
3964 * Otherwise, we should fail with #UD. We test these now:
3965 */
3966 if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE) ||
3967 !kvm_read_cr0_bits(vcpu, X86_CR0_PE) ||
3968 (vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
3969 kvm_queue_exception(vcpu, UD_VECTOR);
3970 return 1;
3971 }
3972
3973 vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
3974 if (is_long_mode(vcpu) && !cs.l) {
3975 kvm_queue_exception(vcpu, UD_VECTOR);
3976 return 1;
3977 }
3978
3979 if (vmx_get_cpl(vcpu)) {
3980 kvm_inject_gp(vcpu, 0);
3981 return 1;
3982 }
3983
3984 vmx->nested.vmxon = true;
3985
3986 skip_emulated_instruction(vcpu);
3987 return 1;
3988}
3989
3990/*
3991 * Intel's VMX Instruction Reference specifies a common set of prerequisites
3992 * for running VMX instructions (except VMXON, whose prerequisites are
3993 * slightly different). It also specifies what exception to inject otherwise.
3994 */
3995static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
3996{
3997 struct kvm_segment cs;
3998 struct vcpu_vmx *vmx = to_vmx(vcpu);
3999
4000 if (!vmx->nested.vmxon) {
4001 kvm_queue_exception(vcpu, UD_VECTOR);
4002 return 0;
4003 }
4004
4005 vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
4006 if ((vmx_get_rflags(vcpu) & X86_EFLAGS_VM) ||
4007 (is_long_mode(vcpu) && !cs.l)) {
4008 kvm_queue_exception(vcpu, UD_VECTOR);
4009 return 0;
4010 }
4011
4012 if (vmx_get_cpl(vcpu)) {
4013 kvm_inject_gp(vcpu, 0);
4014 return 0;
4015 }
4016
4017 return 1;
4018}
4019
4020/*
4021 * Free whatever needs to be freed from vmx->nested when L1 goes down, or
4022 * just stops using VMX.
4023 */
4024static void free_nested(struct vcpu_vmx *vmx)
4025{
4026 if (!vmx->nested.vmxon)
4027 return;
4028 vmx->nested.vmxon = false;
4029}
4030
4031/* Emulate the VMXOFF instruction */
4032static int handle_vmoff(struct kvm_vcpu *vcpu)
4033{
4034 if (!nested_vmx_check_permission(vcpu))
4035 return 1;
4036 free_nested(to_vmx(vcpu));
4037 skip_emulated_instruction(vcpu);
4038 return 1;
4039}
4040
4041/*
3937 * The exit handlers return 1 if the exit was handled fully and guest execution 4042 * The exit handlers return 1 if the exit was handled fully and guest execution
3938 * may resume. Otherwise they set the kvm_run parameter to indicate what needs 4043 * may resume. Otherwise they set the kvm_run parameter to indicate what needs
3939 * to be done to userspace and return 0. 4044 * to be done to userspace and return 0.
@@ -3961,8 +4066,8 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
3961 [EXIT_REASON_VMREAD] = handle_vmx_insn, 4066 [EXIT_REASON_VMREAD] = handle_vmx_insn,
3962 [EXIT_REASON_VMRESUME] = handle_vmx_insn, 4067 [EXIT_REASON_VMRESUME] = handle_vmx_insn,
3963 [EXIT_REASON_VMWRITE] = handle_vmx_insn, 4068 [EXIT_REASON_VMWRITE] = handle_vmx_insn,
3964 [EXIT_REASON_VMOFF] = handle_vmx_insn, 4069 [EXIT_REASON_VMOFF] = handle_vmoff,
3965 [EXIT_REASON_VMON] = handle_vmx_insn, 4070 [EXIT_REASON_VMON] = handle_vmon,
3966 [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, 4071 [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
3967 [EXIT_REASON_APIC_ACCESS] = handle_apic_access, 4072 [EXIT_REASON_APIC_ACCESS] = handle_apic_access,
3968 [EXIT_REASON_WBINVD] = handle_wbinvd, 4073 [EXIT_REASON_WBINVD] = handle_wbinvd,
@@ -4363,6 +4468,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
4363 struct vcpu_vmx *vmx = to_vmx(vcpu); 4468 struct vcpu_vmx *vmx = to_vmx(vcpu);
4364 4469
4365 free_vpid(vmx); 4470 free_vpid(vmx);
4471 free_nested(vmx);
4366 free_loaded_vmcs(vmx->loaded_vmcs); 4472 free_loaded_vmcs(vmx->loaded_vmcs);
4367 kfree(vmx->guest_msrs); 4473 kfree(vmx->guest_msrs);
4368 kvm_vcpu_uninit(vcpu); 4474 kvm_vcpu_uninit(vcpu);