Skip to content

Commit 254e5dc

Browse files
yamahatabonzini
authored andcommitted
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>
1 parent 34d2d1c commit 254e5dc

File tree

2 files changed

+68
-58
lines changed

2 files changed

+68
-58
lines changed

arch/x86/kvm/vmx/common.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,71 @@ static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
109109
return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
110110
}
111111

112+
static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
113+
int pi_vec)
114+
{
115+
#ifdef CONFIG_SMP
116+
if (vcpu->mode == IN_GUEST_MODE) {
117+
/*
118+
* The vector of the virtual has already been set in the PIR.
119+
* Send a notification event to deliver the virtual interrupt
120+
* unless the vCPU is the currently running vCPU, i.e. the
121+
* event is being sent from a fastpath VM-Exit handler, in
122+
* which case the PIR will be synced to the vIRR before
123+
* re-entering the guest.
124+
*
125+
* When the target is not the running vCPU, the following
126+
* possibilities emerge:
127+
*
128+
* Case 1: vCPU stays in non-root mode. Sending a notification
129+
* event posts the interrupt to the vCPU.
130+
*
131+
* Case 2: vCPU exits to root mode and is still runnable. The
132+
* PIR will be synced to the vIRR before re-entering the guest.
133+
* Sending a notification event is ok as the host IRQ handler
134+
* will ignore the spurious event.
135+
*
136+
* Case 3: vCPU exits to root mode and is blocked. vcpu_block()
137+
* has already synced PIR to vIRR and never blocks the vCPU if
138+
* the vIRR is not empty. Therefore, a blocked vCPU here does
139+
* not wait for any requested interrupts in PIR, and sending a
140+
* notification event also results in a benign, spurious event.
141+
*/
142+
143+
if (vcpu != kvm_get_running_vcpu())
144+
__apic_send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
145+
return;
146+
}
147+
#endif
148+
/*
149+
* The vCPU isn't in the guest; wake the vCPU in case it is blocking,
150+
* otherwise do nothing as KVM will grab the highest priority pending
151+
* IRQ via ->sync_pir_to_irr() in vcpu_enter_guest().
152+
*/
153+
kvm_vcpu_wake_up(vcpu);
154+
}
155+
156+
/*
157+
* Post an interrupt to a vCPU's PIR and trigger the vCPU to process the
158+
* interrupt if necessary.
159+
*/
160+
static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
161+
struct pi_desc *pi_desc, int vector)
162+
{
163+
if (pi_test_and_set_pir(vector, pi_desc))
164+
return;
165+
166+
/* If a previous notification has sent the IPI, nothing to do. */
167+
if (pi_test_and_set_on(pi_desc))
168+
return;
169+
170+
/*
171+
* The implied barrier in pi_test_and_set_on() pairs with the smp_mb_*()
172+
* after setting vcpu->mode in vcpu_enter_guest(), thus the vCPU is
173+
* guaranteed to see PID.ON=1 and sync the PIR to IRR if triggering a
174+
* posted interrupt "fails" because vcpu->mode != IN_GUEST_MODE.
175+
*/
176+
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
177+
}
178+
112179
#endif /* __KVM_X86_VMX_COMMON_H */

arch/x86/kvm/vmx/vmx.c

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4182,50 +4182,6 @@ void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
41824182
pt_update_intercept_for_msr(vcpu);
41834183
}
41844184

4185-
static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
4186-
int pi_vec)
4187-
{
4188-
#ifdef CONFIG_SMP
4189-
if (vcpu->mode == IN_GUEST_MODE) {
4190-
/*
4191-
* The vector of the virtual has already been set in the PIR.
4192-
* Send a notification event to deliver the virtual interrupt
4193-
* unless the vCPU is the currently running vCPU, i.e. the
4194-
* event is being sent from a fastpath VM-Exit handler, in
4195-
* which case the PIR will be synced to the vIRR before
4196-
* re-entering the guest.
4197-
*
4198-
* When the target is not the running vCPU, the following
4199-
* possibilities emerge:
4200-
*
4201-
* Case 1: vCPU stays in non-root mode. Sending a notification
4202-
* event posts the interrupt to the vCPU.
4203-
*
4204-
* Case 2: vCPU exits to root mode and is still runnable. The
4205-
* PIR will be synced to the vIRR before re-entering the guest.
4206-
* Sending a notification event is ok as the host IRQ handler
4207-
* will ignore the spurious event.
4208-
*
4209-
* Case 3: vCPU exits to root mode and is blocked. vcpu_block()
4210-
* has already synced PIR to vIRR and never blocks the vCPU if
4211-
* the vIRR is not empty. Therefore, a blocked vCPU here does
4212-
* not wait for any requested interrupts in PIR, and sending a
4213-
* notification event also results in a benign, spurious event.
4214-
*/
4215-
4216-
if (vcpu != kvm_get_running_vcpu())
4217-
__apic_send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
4218-
return;
4219-
}
4220-
#endif
4221-
/*
4222-
* The vCPU isn't in the guest; wake the vCPU in case it is blocking,
4223-
* otherwise do nothing as KVM will grab the highest priority pending
4224-
* IRQ via ->sync_pir_to_irr() in vcpu_enter_guest().
4225-
*/
4226-
kvm_vcpu_wake_up(vcpu);
4227-
}
4228-
42294185
static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
42304186
int vector)
42314187
{
@@ -4285,20 +4241,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
42854241
if (!vcpu->arch.apic->apicv_active)
42864242
return -1;
42874243

4288-
if (pi_test_and_set_pir(vector, &vt->pi_desc))
4289-
return 0;
4290-
4291-
/* If a previous notification has sent the IPI, nothing to do. */
4292-
if (pi_test_and_set_on(&vt->pi_desc))
4293-
return 0;
4294-
4295-
/*
4296-
* The implied barrier in pi_test_and_set_on() pairs with the smp_mb_*()
4297-
* after setting vcpu->mode in vcpu_enter_guest(), thus the vCPU is
4298-
* guaranteed to see PID.ON=1 and sync the PIR to IRR if triggering a
4299-
* posted interrupt "fails" because vcpu->mode != IN_GUEST_MODE.
4300-
*/
4301-
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
4244+
__vmx_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
43024245
return 0;
43034246
}
43044247

0 commit comments

Comments
 (0)