Skip to content

Commit 70f3aac

Browse files
jsmattsonjrbonzini
authored andcommitted
kvm: nVMX: Remove superfluous VMX instruction fault checks
According to the Intel SDM, "Certain exceptions have priority over VM exits. These include invalid-opcode exceptions, faults based on privilege level*, and general-protection exceptions that are based on checking I/O permission bits in the task-state segment (TSS)." There is no need to check for faulting conditions that the hardware has already checked. * These include faults generated by attempts to execute, in virtual-8086 mode, privileged instructions that are not recognized in that mode. Signed-off-by: Jim Mattson <jmattson@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 6ed071f commit 70f3aac

File tree

1 file changed

+14
-43
lines changed

1 file changed

+14
-43
lines changed

arch/x86/kvm/vmx.c

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7052,34 +7052,24 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)
70527052
static int handle_vmon(struct kvm_vcpu *vcpu)
70537053
{
70547054
int ret;
7055-
struct kvm_segment cs;
70567055
struct vcpu_vmx *vmx = to_vmx(vcpu);
70577056
const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
70587057
| FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
70597058

7060-
/* The Intel VMX Instruction Reference lists a bunch of bits that
7061-
* are prerequisite to running VMXON, most notably cr4.VMXE must be
7062-
* set to 1 (see vmx_set_cr4() for when we allow the guest to set this).
7063-
* Otherwise, we should fail with #UD. We test these now:
7059+
/*
7060+
* The Intel VMX Instruction Reference lists a bunch of bits that are
7061+
* prerequisite to running VMXON, most notably cr4.VMXE must be set to
7062+
* 1 (see vmx_set_cr4() for when we allow the guest to set this).
7063+
* Otherwise, we should fail with #UD. But most faulting conditions
7064+
* have already been checked by hardware, prior to the VM-exit for
7065+
* VMXON. We do test guest cr4.VMXE because processor CR4 always has
7066+
* that bit set to 1 in non-root mode.
70647067
*/
7065-
if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE) ||
7066-
!kvm_read_cr0_bits(vcpu, X86_CR0_PE) ||
7067-
(vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
7068-
kvm_queue_exception(vcpu, UD_VECTOR);
7069-
return 1;
7070-
}
7071-
7072-
vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
7073-
if (is_long_mode(vcpu) && !cs.l) {
7068+
if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) {
70747069
kvm_queue_exception(vcpu, UD_VECTOR);
70757070
return 1;
70767071
}
70777072

7078-
if (vmx_get_cpl(vcpu)) {
7079-
kvm_inject_gp(vcpu, 0);
7080-
return 1;
7081-
}
7082-
70837073
if (vmx->nested.vmxon) {
70847074
nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
70857075
return kvm_skip_emulated_instruction(vcpu);
@@ -7106,29 +7096,15 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
71067096
* Intel's VMX Instruction Reference specifies a common set of prerequisites
71077097
* for running VMX instructions (except VMXON, whose prerequisites are
71087098
* slightly different). It also specifies what exception to inject otherwise.
7099+
* Note that many of these exceptions have priority over VM exits, so they
7100+
* don't have to be checked again here.
71097101
*/
71107102
static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
71117103
{
7112-
struct kvm_segment cs;
7113-
struct vcpu_vmx *vmx = to_vmx(vcpu);
7114-
7115-
if (!vmx->nested.vmxon) {
7104+
if (!to_vmx(vcpu)->nested.vmxon) {
71167105
kvm_queue_exception(vcpu, UD_VECTOR);
71177106
return 0;
71187107
}
7119-
7120-
vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
7121-
if ((vmx_get_rflags(vcpu) & X86_EFLAGS_VM) ||
7122-
(is_long_mode(vcpu) && !cs.l)) {
7123-
kvm_queue_exception(vcpu, UD_VECTOR);
7124-
return 0;
7125-
}
7126-
7127-
if (vmx_get_cpl(vcpu)) {
7128-
kvm_inject_gp(vcpu, 0);
7129-
return 0;
7130-
}
7131-
71327108
return 1;
71337109
}
71347110

@@ -7472,7 +7448,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
74727448
if (get_vmx_mem_address(vcpu, exit_qualification,
74737449
vmx_instruction_info, true, &gva))
74747450
return 1;
7475-
/* _system ok, as nested_vmx_check_permission verified cpl=0 */
7451+
/* _system ok, as hardware has verified cpl=0 */
74767452
kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
74777453
&field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
74787454
}
@@ -7605,7 +7581,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
76057581
if (get_vmx_mem_address(vcpu, exit_qualification,
76067582
vmx_instruction_info, true, &vmcs_gva))
76077583
return 1;
7608-
/* ok to use *_system, as nested_vmx_check_permission verified cpl=0 */
7584+
/* ok to use *_system, as hardware has verified cpl=0 */
76097585
if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
76107586
(void *)&to_vmx(vcpu)->nested.current_vmptr,
76117587
sizeof(u64), &e)) {
@@ -7638,11 +7614,6 @@ static int handle_invept(struct kvm_vcpu *vcpu)
76387614
if (!nested_vmx_check_permission(vcpu))
76397615
return 1;
76407616

7641-
if (!kvm_read_cr0_bits(vcpu, X86_CR0_PE)) {
7642-
kvm_queue_exception(vcpu, UD_VECTOR);
7643-
return 1;
7644-
}
7645-
76467617
vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
76477618
type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
76487619

0 commit comments

Comments
 (0)