[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4] x86/apicv: Fix wrong IPI suppression during posted interrupt delivery
On March 03, 2017 10:36 AM, Chao Gao wrote: >__vmx_deliver_posted_interrupt() wrongly used a softirq bit to decide >whether to suppress an IPI. Its logic was: the first time an IPI was sent, we >set >the softirq bit. Next time, we would check that softirq bit before sending >another IPI. If the 1st IPI arrived at the pCPU which was in non-root mode, the >hardware would consume the IPI and sync PIR to vIRR. >During the process, no one (both hardware and software) will clear the softirq >bit. As a result, the following IPI would be wrongly suppressed. > >This patch discards the suppression check, always sending an IPI. >The softirq also need to be raised. But there is a little change. >This patch moves the place where we raise a softirq for 'cpu != >smp_processor_id()' case to the IPI interrupt handler. >Namely, don't raise a softirq for this case and set the interrupt handler to >pi_notification_interrupt()(in which a softirq is raised) regardless of VT-d PI >enabled or not. The only difference is when an IPI arrives at the pCPU which is >happened in non-root mode, the code will not raise a useless softirq since the >IPI is consumed by hardware rather than raise a softirq unconditionally. > >Signed-off-by: Quan Xu <xuquan8@xxxxxxxxxx> >Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> >Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx> >--- >v4: >- Replace patch v3 title "Enhance posted-interrupt processing" with the >current title. >- Desciption changes >- Fix a compiler error > >--- > xen/arch/x86/hvm/vmx/vmx.c | 50 >+++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 43 insertions(+), 7 deletions(-) > >diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c >index 5b1717d..1a0e130 100644 >--- a/xen/arch/x86/hvm/vmx/vmx.c >+++ b/xen/arch/x86/hvm/vmx/vmx.c >@@ -1842,13 +1842,53 @@ static void >__vmx_deliver_posted_interrupt(struct vcpu *v) > bool_t running = v->is_running; > > vcpu_unblock(v); >+ /* >+ * Just like vcpu_kick(), nothing is needed for the following two cases: >+ * 1. The target vCPU is not running, meaning it is blocked or runnable. >+ * 2. The target vCPU is the current vCPU and we're in non-interrupt >+ * context. >+ */ > if ( running && (in_irq() || (v != current)) ) > { >+ /* >+ * Note: Only two cases will reach here: >+ * 1. The target vCPU is running on other pCPU. >+ * 2. The target vCPU is the current vCPU. >+ * >+ * Note2: Don't worry the v->processor may change. The vCPU >being >+ * moved to another processor is guaranteed to sync PIR to vIRR, >+ * due to the involved scheduling cycle. >+ */ > unsigned int cpu = v->processor; > >- if ( !test_and_set_bit(VCPU_KICK_SOFTIRQ, &softirq_pending(cpu)) >- && (cpu != smp_processor_id()) ) >+ /* >+ * For case 1, we send an IPI to the pCPU. When an IPI arrives, the I almost agree to your comments!! You really mentioned 2 times 'two cases'.. so 'For case 1' here is a little ambiguous.. I am not sure what does it refer to, the first 'case 1' or the second one? From here to ... >+ * target vCPU maybe is running in non-root mode, running in root >+ * mode, runnable or blocked. If the target vCPU is running in >+ * non-root mode, the hardware will sync PIR to vIRR for >+ * 'posted_intr_vector' is special to the pCPU. If the target vCPU is >+ * running in root-mode, the interrupt handler starts to run. >+ * Considering an IPI may arrive in the window between the call to >+ * vmx_intr_assist() and interrupts getting disabled, the interrupt >+ * handler should raise a softirq to ensure events will be delivered >+ * in time. If the target vCPU is runnable, it will sync PIR to >+ * vIRR next time it is chose to run. In this case, a IPI and a >+ * softirq is sent to a wrong vCPU which will not have any adverse >+ * effect. If the target vCPU is blocked, since vcpu_block() checks >+ * whether there is an event to be delivered through >+ * local_events_need_delivery() just after blocking, the vCPU must >+ * have synced PIR to vIRR. ... here. This looks an explanation to the first 'two cases' -- """nothing is needed for the following two cases""" If so, you'd better move it next to the first 'two cases'.. -Quan > Similarly, there is a IPI and a softirq >+ * sent to a wrong vCPU. >+ */ To me, this is a little confusing.. also " a IPI and a softirq is sent to a wrong vCPU which will not have any adverse effect. "... what about dropping it? And some typo: 's/maybe is/is maybe/' 's/a IPI/an IPI/' >+ if ( cpu != smp_processor_id() ) > send_IPI_mask(cpumask_of(cpu), posted_intr_vector); >+ /* >+ * For case 2, raising a softirq ensures PIR will be synced to vIRR. >+ * As any softirq will do, as an optimization we only raise one if >+ * none is pending already. >+ */ >+ else if ( !softirq_pending(cpu) ) >+ raise_softirq(VCPU_KICK_SOFTIRQ); > } > } > >@@ -2281,13 +2321,9 @@ const struct hvm_function_table * __init >start_vmx(void) > > if ( cpu_has_vmx_posted_intr_processing ) > { >+ alloc_direct_apic_vector(&posted_intr_vector, >+ pi_notification_interrupt); > if ( iommu_intpost ) >- { >- alloc_direct_apic_vector(&posted_intr_vector, >pi_notification_interrupt); > alloc_direct_apic_vector(&pi_wakeup_vector, >pi_wakeup_interrupt); >- } >- else >- alloc_direct_apic_vector(&posted_intr_vector, >event_check_interrupt); > } > else > { >-- >1.8.3.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |