Commit 9d58b931 authored by Avi Kivity's avatar Avi Kivity

KVM: VMX: Avoid vmx_recover_nmi_blocking() when unneeded

When we haven't injected an interrupt, we don't need to recover
the nmi blocking state (since the guest can't set it by itself).
This allows us to avoid a VMREAD later on.
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 69c73028
...@@ -129,6 +129,7 @@ struct vcpu_vmx { ...@@ -129,6 +129,7 @@ struct vcpu_vmx {
int launched; int launched;
u8 fail; u8 fail;
u8 cpl; u8 cpl;
bool nmi_known_unmasked;
u32 exit_intr_info; u32 exit_intr_info;
u32 idt_vectoring_info; u32 idt_vectoring_info;
ulong rflags; ulong rflags;
...@@ -2959,6 +2960,7 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) ...@@ -2959,6 +2960,7 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
} }
++vcpu->stat.nmi_injections; ++vcpu->stat.nmi_injections;
vmx->nmi_known_unmasked = false;
if (vmx->rmode.vm86_active) { if (vmx->rmode.vm86_active) {
if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR) != EMULATE_DONE) if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR) != EMULATE_DONE)
kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
...@@ -2983,6 +2985,8 @@ static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu) ...@@ -2983,6 +2985,8 @@ static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
{ {
if (!cpu_has_virtual_nmis()) if (!cpu_has_virtual_nmis())
return to_vmx(vcpu)->soft_vnmi_blocked; return to_vmx(vcpu)->soft_vnmi_blocked;
if (to_vmx(vcpu)->nmi_known_unmasked)
return false;
return vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI; return vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
} }
...@@ -2996,6 +3000,7 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked) ...@@ -2996,6 +3000,7 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
vmx->vnmi_blocked_time = 0; vmx->vnmi_blocked_time = 0;
} }
} else { } else {
vmx->nmi_known_unmasked = !masked;
if (masked) if (masked)
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI); GUEST_INTR_STATE_NMI);
...@@ -3527,9 +3532,11 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) ...@@ -3527,9 +3532,11 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
switch (type) { switch (type) {
case INTR_TYPE_NMI_INTR: case INTR_TYPE_NMI_INTR:
vcpu->arch.nmi_injected = false; vcpu->arch.nmi_injected = false;
if (cpu_has_virtual_nmis()) if (cpu_has_virtual_nmis()) {
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI); GUEST_INTR_STATE_NMI);
vmx->nmi_known_unmasked = false;
}
break; break;
case INTR_TYPE_EXT_INTR: case INTR_TYPE_EXT_INTR:
case INTR_TYPE_SOFT_INTR: case INTR_TYPE_SOFT_INTR:
...@@ -3916,6 +3923,8 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) ...@@ -3916,6 +3923,8 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK; idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
if (cpu_has_virtual_nmis()) { if (cpu_has_virtual_nmis()) {
if (vmx->nmi_known_unmasked)
return;
unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0; unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
vector = exit_intr_info & INTR_INFO_VECTOR_MASK; vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
/* /*
...@@ -3932,6 +3941,10 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) ...@@ -3932,6 +3941,10 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
vector != DF_VECTOR && !idtv_info_valid) vector != DF_VECTOR && !idtv_info_valid)
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI); GUEST_INTR_STATE_NMI);
else
vmx->nmi_known_unmasked =
!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
& GUEST_INTR_STATE_NMI);
} else if (unlikely(vmx->soft_vnmi_blocked)) } else if (unlikely(vmx->soft_vnmi_blocked))
vmx->vnmi_blocked_time += vmx->vnmi_blocked_time +=
ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time)); ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
...@@ -3970,6 +3983,7 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, ...@@ -3970,6 +3983,7 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
*/ */
vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO, vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI); GUEST_INTR_STATE_NMI);
vmx->nmi_known_unmasked = true;
break; break;
case INTR_TYPE_SOFT_EXCEPTION: case INTR_TYPE_SOFT_EXCEPTION:
vmx->vcpu.arch.event_exit_inst_len = vmx->vcpu.arch.event_exit_inst_len =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment