Skip to content

Commit cb61de2

Browse files
Sean Christophersonbonzini
authored andcommitted
KVM: nVMX: do not skip VMEnter instruction that succeeds
A successful VMEnter is essentially a fancy indirect branch that pulls the target RIP from the VMCS. Skipping the instruction is unnecessary (RIP will get overwritten by the VMExit handler) and is problematic because it can incorrectly suppress a #DB due to EFLAGS.TF when a VMFail is detected by hardware (happens after we skip the instruction). Now that vmx_nested_run() is not prematurely skipping the instr, use the full kvm_skip_emulated_instruction() in the VMFail path of nested_vmx_vmexit(). We also need to explicitly update the GUEST_INTERRUPTIBILITY_INFO when loading vmcs12 host state. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Reviewed-by: Jim Mattson <jmattson@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 16fb9a4 commit cb61de2

File tree

1 file changed

+5
-16
lines changed

1 file changed

+5
-16
lines changed

arch/x86/kvm/vmx.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12855,15 +12855,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
1285512855
goto out;
1285612856
}
1285712857

12858-
/*
12859-
* After this point, the trap flag no longer triggers a singlestep trap
12860-
* on the vm entry instructions; don't call kvm_skip_emulated_instruction.
12861-
* This is not 100% correct; for performance reasons, we delegate most
12862-
* of the checks on host state to the processor. If those fail,
12863-
* the singlestep trap is missed.
12864-
*/
12865-
skip_emulated_instruction(vcpu);
12866-
1286712858
/*
1286812859
* We're finally done with prerequisite checking, and can start with
1286912860
* the nested entry.
@@ -13243,6 +13234,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
1324313234
kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
1324413235
kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
1324513236
vmx_set_rflags(vcpu, X86_EFLAGS_FIXED);
13237+
vmx_set_interrupt_shadow(vcpu, 0);
13238+
1324613239
/*
1324713240
* Note that calling vmx_set_cr0 is important, even if cr0 hasn't
1324813241
* actually changed, because vmx_set_cr0 refers to efer set above.
@@ -13636,10 +13629,12 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
1363613629
* in L1 which thinks it just finished a VMLAUNCH or
1363713630
* VMRESUME instruction, so we need to set the failure
1363813631
* flag and the VM-instruction error field of the VMCS
13639-
* accordingly.
13632+
* accordingly, and skip the emulated instruction.
1364013633
*/
1364113634
nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
1364213635

13636+
kvm_skip_emulated_instruction(vcpu);
13637+
1364313638
/*
1364413639
* Restore L1's host state to KVM's software model. We're here
1364513640
* because a consistency check was caught by hardware, which
@@ -13648,12 +13643,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
1364813643
*/
1364913644
nested_vmx_restore_host_state(vcpu);
1365013645

13651-
/*
13652-
* The emulated instruction was already skipped in
13653-
* nested_vmx_run, but the updated RIP was never
13654-
* written back to the vmcs01.
13655-
*/
13656-
skip_emulated_instruction(vcpu);
1365713646
vmx->fail = 0;
1365813647
}
1365913648

0 commit comments

Comments
 (0)