mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
KVM: VMX: Move posted interrupt delivery code to common header
Move posted interrupt delivery code to common header so that TDX can leverage it. No functional change intended. Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> [binbin: split into new patch] Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com> Reviewed-by: Chao Gao <chao.gao@intel.com> Message-ID: <20250222014757.897978-4-binbin.wu@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
34d2d1ca1b
commit
254e5dcd5a
|
|
@ -109,4 +109,71 @@ static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|||
return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
|
||||
}
|
||||
|
||||
static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
|
||||
int pi_vec)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
if (vcpu->mode == IN_GUEST_MODE) {
|
||||
/*
|
||||
* The vector of the virtual has already been set in the PIR.
|
||||
* Send a notification event to deliver the virtual interrupt
|
||||
* unless the vCPU is the currently running vCPU, i.e. the
|
||||
* event is being sent from a fastpath VM-Exit handler, in
|
||||
* which case the PIR will be synced to the vIRR before
|
||||
* re-entering the guest.
|
||||
*
|
||||
* When the target is not the running vCPU, the following
|
||||
* possibilities emerge:
|
||||
*
|
||||
* Case 1: vCPU stays in non-root mode. Sending a notification
|
||||
* event posts the interrupt to the vCPU.
|
||||
*
|
||||
* Case 2: vCPU exits to root mode and is still runnable. The
|
||||
* PIR will be synced to the vIRR before re-entering the guest.
|
||||
* Sending a notification event is ok as the host IRQ handler
|
||||
* will ignore the spurious event.
|
||||
*
|
||||
* Case 3: vCPU exits to root mode and is blocked. vcpu_block()
|
||||
* has already synced PIR to vIRR and never blocks the vCPU if
|
||||
* the vIRR is not empty. Therefore, a blocked vCPU here does
|
||||
* not wait for any requested interrupts in PIR, and sending a
|
||||
* notification event also results in a benign, spurious event.
|
||||
*/
|
||||
|
||||
if (vcpu != kvm_get_running_vcpu())
|
||||
__apic_send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* The vCPU isn't in the guest; wake the vCPU in case it is blocking,
|
||||
* otherwise do nothing as KVM will grab the highest priority pending
|
||||
* IRQ via ->sync_pir_to_irr() in vcpu_enter_guest().
|
||||
*/
|
||||
kvm_vcpu_wake_up(vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Post an interrupt to a vCPU's PIR and trigger the vCPU to process the
|
||||
* interrupt if necessary.
|
||||
*/
|
||||
static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
|
||||
struct pi_desc *pi_desc, int vector)
|
||||
{
|
||||
if (pi_test_and_set_pir(vector, pi_desc))
|
||||
return;
|
||||
|
||||
/* If a previous notification has sent the IPI, nothing to do. */
|
||||
if (pi_test_and_set_on(pi_desc))
|
||||
return;
|
||||
|
||||
/*
|
||||
* The implied barrier in pi_test_and_set_on() pairs with the smp_mb_*()
|
||||
* after setting vcpu->mode in vcpu_enter_guest(), thus the vCPU is
|
||||
* guaranteed to see PID.ON=1 and sync the PIR to IRR if triggering a
|
||||
* posted interrupt "fails" because vcpu->mode != IN_GUEST_MODE.
|
||||
*/
|
||||
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
|
||||
}
|
||||
|
||||
#endif /* __KVM_X86_VMX_COMMON_H */
|
||||
|
|
|
|||
|
|
@ -4182,50 +4182,6 @@ void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
|
|||
pt_update_intercept_for_msr(vcpu);
|
||||
}
|
||||
|
||||
static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
|
||||
int pi_vec)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
if (vcpu->mode == IN_GUEST_MODE) {
|
||||
/*
|
||||
* The vector of the virtual has already been set in the PIR.
|
||||
* Send a notification event to deliver the virtual interrupt
|
||||
* unless the vCPU is the currently running vCPU, i.e. the
|
||||
* event is being sent from a fastpath VM-Exit handler, in
|
||||
* which case the PIR will be synced to the vIRR before
|
||||
* re-entering the guest.
|
||||
*
|
||||
* When the target is not the running vCPU, the following
|
||||
* possibilities emerge:
|
||||
*
|
||||
* Case 1: vCPU stays in non-root mode. Sending a notification
|
||||
* event posts the interrupt to the vCPU.
|
||||
*
|
||||
* Case 2: vCPU exits to root mode and is still runnable. The
|
||||
* PIR will be synced to the vIRR before re-entering the guest.
|
||||
* Sending a notification event is ok as the host IRQ handler
|
||||
* will ignore the spurious event.
|
||||
*
|
||||
* Case 3: vCPU exits to root mode and is blocked. vcpu_block()
|
||||
* has already synced PIR to vIRR and never blocks the vCPU if
|
||||
* the vIRR is not empty. Therefore, a blocked vCPU here does
|
||||
* not wait for any requested interrupts in PIR, and sending a
|
||||
* notification event also results in a benign, spurious event.
|
||||
*/
|
||||
|
||||
if (vcpu != kvm_get_running_vcpu())
|
||||
__apic_send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* The vCPU isn't in the guest; wake the vCPU in case it is blocking,
|
||||
* otherwise do nothing as KVM will grab the highest priority pending
|
||||
* IRQ via ->sync_pir_to_irr() in vcpu_enter_guest().
|
||||
*/
|
||||
kvm_vcpu_wake_up(vcpu);
|
||||
}
|
||||
|
||||
static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
|
||||
int vector)
|
||||
{
|
||||
|
|
@ -4285,20 +4241,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
|
|||
if (!vcpu->arch.apic->apicv_active)
|
||||
return -1;
|
||||
|
||||
if (pi_test_and_set_pir(vector, &vt->pi_desc))
|
||||
return 0;
|
||||
|
||||
/* If a previous notification has sent the IPI, nothing to do. */
|
||||
if (pi_test_and_set_on(&vt->pi_desc))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The implied barrier in pi_test_and_set_on() pairs with the smp_mb_*()
|
||||
* after setting vcpu->mode in vcpu_enter_guest(), thus the vCPU is
|
||||
* guaranteed to see PID.ON=1 and sync the PIR to IRR if triggering a
|
||||
* posted interrupt "fails" because vcpu->mode != IN_GUEST_MODE.
|
||||
*/
|
||||
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
|
||||
__vmx_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user