Skip to content

Commit 27c4fa4

Browse files
committed
KVM: nVMX: Check for pending posted interrupts when looking for nested events
Check for pending (and notified!) posted interrupts when checking if L2 has a pending wake event, as fully posted/notified virtual interrupt is a valid wake event for HLT. Note that KVM must check vmx->nested.pi_pending to avoid prematurely waking L2, e.g. even if KVM sees a non-zero PID.PIR and PID.0N=1, the virtual interrupt won't actually be recognized until a notification IRQ is received by the vCPU or the vCPU does (nested) VM-Enter. Fixes: 26844fe ("KVM: x86: never write to memory from kvm_vcpu_check_block()") Cc: [email protected] Cc: Maxim Levitsky <[email protected]> Reported-by: Jim Mattson <[email protected]> Closes: https://lore.kernel.org/all/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent 322a569 commit 27c4fa4

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

arch/x86/kvm/vmx/nested.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4034,8 +4034,40 @@ static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu)
40344034

40354035
static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
40364036
{
4037-
return nested_vmx_preemption_timer_pending(vcpu) ||
4038-
to_vmx(vcpu)->nested.mtf_pending;
4037+
struct vcpu_vmx *vmx = to_vmx(vcpu);
4038+
void *vapic = vmx->nested.virtual_apic_map.hva;
4039+
int max_irr, vppr;
4040+
4041+
if (nested_vmx_preemption_timer_pending(vcpu) ||
4042+
vmx->nested.mtf_pending)
4043+
return true;
4044+
4045+
/*
4046+
* Virtual Interrupt Delivery doesn't require manual injection. Either
4047+
* the interrupt is already in GUEST_RVI and will be recognized by CPU
4048+
* at VM-Entry, or there is a KVM_REQ_EVENT pending and KVM will move
4049+
* the interrupt from the PIR to RVI prior to entering the guest.
4050+
*/
4051+
if (for_injection)
4052+
return false;
4053+
4054+
if (!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
4055+
__vmx_interrupt_blocked(vcpu))
4056+
return false;
4057+
4058+
if (!vapic)
4059+
return false;
4060+
4061+
vppr = *((u32 *)(vapic + APIC_PROCPRI));
4062+
4063+
if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
4064+
pi_test_on(vmx->nested.pi_desc)) {
4065+
max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
4066+
if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0))
4067+
return true;
4068+
}
4069+
4070+
return false;
40394071
}
40404072

40414073
/*

0 commit comments

Comments
 (0)