|
@@ -5077,21 +5077,30 @@ static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
|
|
|
int pi_vec = nested ? POSTED_INTR_NESTED_VECTOR : POSTED_INTR_VECTOR;
|
|
|
|
|
|
if (vcpu->mode == IN_GUEST_MODE) {
|
|
|
- struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
|
-
|
|
|
/*
|
|
|
- * Currently, we don't support urgent interrupt,
|
|
|
- * all interrupts are recognized as non-urgent
|
|
|
- * interrupt, so we cannot post interrupts when
|
|
|
- * 'SN' is set.
|
|
|
+ * The vector of interrupt to be delivered to vcpu had
|
|
|
+ * been set in PIR before this function.
|
|
|
+ *
|
|
|
+ * Following cases will be reached in this block, and
|
|
|
+ * we always send a notification event in all cases as
|
|
|
+ * explained below.
|
|
|
+ *
|
|
|
+ * Case 1: vcpu keeps in non-root mode. Sending a
|
|
|
+ * notification event posts the interrupt to vcpu.
|
|
|
*
|
|
|
- * If the vcpu is in guest mode, it means it is
|
|
|
- * running instead of being scheduled out and
|
|
|
- * waiting in the run queue, and that's the only
|
|
|
- * case when 'SN' is set currently, warning if
|
|
|
- * 'SN' is set.
|
|
|
+ * Case 2: vcpu exits to root mode and is still
|
|
|
+ * runnable. PIR will be synced to vIRR before the
|
|
|
+ * next vcpu entry. Sending a notification event in
|
|
|
+ * this case has no effect, as vcpu is not in root
|
|
|
+ * mode.
|
|
|
+ *
|
|
|
+ * Case 3: vcpu exits to root mode and is blocked.
|
|
|
+ * vcpu_block() has already synced PIR to vIRR and
|
|
|
+ * never blocks vcpu if vIRR is not cleared. Therefore,
|
|
|
+ * a blocked vcpu here does not wait for any requested
|
|
|
+ * interrupts in PIR, and sending a notification event
|
|
|
+ * which has no effect is safe here.
|
|
|
*/
|
|
|
- WARN_ON_ONCE(pi_test_sn(&vmx->pi_desc));
|
|
|
|
|
|
apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
|
|
|
return true;
|
|
@@ -11911,12 +11920,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
|
|
|
|
|
|
if (set)
|
|
|
ret = irq_set_vcpu_affinity(host_irq, &vcpu_info);
|
|
|
- else {
|
|
|
- /* suppress notification event before unposting */
|
|
|
- pi_set_sn(vcpu_to_pi_desc(vcpu));
|
|
|
+ else
|
|
|
ret = irq_set_vcpu_affinity(host_irq, NULL);
|
|
|
- pi_clear_sn(vcpu_to_pi_desc(vcpu));
|
|
|
- }
|
|
|
|
|
|
if (ret < 0) {
|
|
|
printk(KERN_INFO "%s: failed to update PI IRTE\n",
|