Skip to content

Commit c112b5f

Browse files
Luwei Kangbonzini
authored andcommitted
KVM: x86: Recompute PID.ON when clearing PID.SN
Some Posted-Interrupts from passthrough devices may be lost or overwritten when the vCPU is in runnable state. The SN (Suppress Notification) of PID (Posted Interrupt Descriptor) will be set when the vCPU is preempted (vCPU in KVM_MP_STATE_RUNNABLE state but not running on physical CPU). If a posted interrupt comes at this time, the irq remapping facility will set the bit of PIR (Posted Interrupt Requests) but not ON (Outstanding Notification). Then, the interrupt will not be seen by KVM, which always expects PID.ON=1 if PID.PIR=1 as documented in the Intel processor SDM but not in the VT-d specification. To fix this, restore the invariant after PID.SN is cleared. Signed-off-by: Luwei Kang <luwei.kang@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 08e1675 commit c112b5f

File tree

3 files changed

+17
-21
lines changed

3 files changed

+17
-21
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,21 +1193,6 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
11931193
if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
11941194
return;
11951195

1196-
/*
1197-
* First handle the simple case where no cmpxchg is necessary; just
1198-
* allow posting non-urgent interrupts.
1199-
*
1200-
* If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
1201-
* PI.NDST: pi_post_block will do it for us and the wakeup_handler
1202-
* expects the VCPU to be on the blocked_vcpu_list that matches
1203-
* PI.NDST.
1204-
*/
1205-
if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
1206-
vcpu->cpu == cpu) {
1207-
pi_clear_sn(pi_desc);
1208-
return;
1209-
}
1210-
12111196
/* The full case. */
12121197
do {
12131198
old.control = new.control = pi_desc->control;
@@ -1222,6 +1207,17 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
12221207
new.sn = 0;
12231208
} while (cmpxchg64(&pi_desc->control, old.control,
12241209
new.control) != old.control);
1210+
1211+
/*
1212+
* Clear SN before reading the bitmap. The VT-d firmware
1213+
* writes the bitmap and reads SN atomically (5.2.3 in the
1214+
* spec), so it doesn't really have a memory barrier that
1215+
* pairs with this, but we cannot do that and we need one.
1216+
*/
1217+
smp_mb__after_atomic();
1218+
1219+
if (!bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS))
1220+
pi_set_on(pi_desc);
12251221
}
12261222

12271223
/*

arch/x86/kvm/vmx/vmx.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,16 +337,16 @@ static inline int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
337337
return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
338338
}
339339

340-
static inline void pi_clear_sn(struct pi_desc *pi_desc)
340+
static inline void pi_set_sn(struct pi_desc *pi_desc)
341341
{
342-
return clear_bit(POSTED_INTR_SN,
342+
return set_bit(POSTED_INTR_SN,
343343
(unsigned long *)&pi_desc->control);
344344
}
345345

346-
static inline void pi_set_sn(struct pi_desc *pi_desc)
346+
static inline void pi_set_on(struct pi_desc *pi_desc)
347347
{
348-
return set_bit(POSTED_INTR_SN,
349-
(unsigned long *)&pi_desc->control);
348+
set_bit(POSTED_INTR_ON,
349+
(unsigned long *)&pi_desc->control);
350350
}
351351

352352
static inline void pi_clear_on(struct pi_desc *pi_desc)

arch/x86/kvm/x86.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7801,7 +7801,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
78017801
* 1) We should set ->mode before checking ->requests. Please see
78027802
* the comment in kvm_vcpu_exiting_guest_mode().
78037803
*
7804-
* 2) For APICv, we should set ->mode before checking PIR.ON. This
7804+
* 2) For APICv, we should set ->mode before checking PID.ON. This
78057805
* pairs with the memory barrier implicit in pi_test_and_set_on
78067806
* (see vmx_deliver_posted_interrupt).
78077807
*

0 commit comments

Comments
 (0)