[PATCH v2 1/2] KVM: nVMX: don't check PIR.ON when processing nested posted interrupts

From: Maxim Levitsky

Date: Sat Oct 10 2026 - 20:13:51 EST


Despite the suggestion to test and set the PIR.ON and avoid sending
a posted interrupt if it is already set, there is no requirement
for this bit to be set for posted interrupt processing to happen
when the target CPU receives the posted notification vector.

See section 30.6 POSTED-INTERRUPT PROCESSING:

"The processor clears the outstanding-notification bit in
the posted-interrupt descriptor. This is done atomically so as to leave
the remainder of the descriptor unmodified
(e.g., with a locked AND operation)."

Apparently Windows' implementation of APICv does exactly this:
it sets bits in PIR, without bothering to also set the PIR.ON.

Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx>
---
arch/x86/kvm/vmx/nested.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 151873407abd..8504a2c12d9d 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -4041,8 +4041,16 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)

vmx->nested.pi_pending = false;

- if (!pi_test_and_clear_on(vmx->nested.pi_desc))
- return 0;
+ /*
+ * Don't test the value of PID.ON.
+ * It is valid to trigger a posted interrupt without setting this bit
+ */
+ pi_clear_on(vmx->nested.pi_desc);
+
+ /* Ensure that guests sees the change to PIR.ON before KVM harvest
+ * the PIR
+ */
+ __smp_mb__after_atomic();

max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
if (max_irr > 0) {
@@ -4209,8 +4217,7 @@ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
if ((max_irr & 0xf0) > (vppr & 0xf0))
return true;

- if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
- pi_test_on(vmx->nested.pi_desc)) {
+ if (vmx->nested.pi_pending && vmx->nested.pi_desc) {
max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0))
return true;
--
2.54.0