From: Chao Gao <chao.gao@intel.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: yang.zhang.wz@gmail.com, "Xuquan (Quan Xu)" <xuquan8@huawei.com>,
quan.xu0@gmail.com, Andrew Cooper <andrew.cooper3@citrix.com>,
Kevin Tian <kevin.tian@intel.com>,
xen-devel@lists.xen.org, Jun Nakajima <jun.nakajima@intel.com>
Subject: Re: [PATCH v3] x86/apicv: Enhance posted-interrupt processing
Date: Thu, 2 Mar 2017 12:28:06 +0800 [thread overview]
Message-ID: <20170302042806.GA12584@skl-2s3.sh.intel.com> (raw)
In-Reply-To: <58B7F6F3020000780013F23D@prv-mh.provo.novell.com>
On Thu, Mar 02, 2017 at 02:41:55AM -0700, Jan Beulich wrote:
>>>> On 02.03.17 at 02:49, <chao.gao@intel.com> wrote:
>
>The patch title, btw, makes it looks like this isn't a bug fix, which is
>contrary to the understanding I've gained so far.
Thanks to your patience and your changing so much description for me. Also
to the questions you asked. I agree to the comments i don't reply to.
How about this:
Fix a wrongly IPI suppression during posted interrupt delivery
>
>> __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 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
>> posted interrupt enabled or not.
>
>As using a PI thing even in the non-PI case is counterintuitive, this
>needs expanding on imo. Maybe not here but in a code comment.
>Or perhaps, looking at the code, this is just not precise enough a
>description: The code is inside a cpu_has_vmx_posted_intr_processing
>conditional, and what you do is move code out of the iommu_intpost
>specific section. I.e. a reference to IOMMU may simply be missing
>here.
Yes. The right description is "regardless of VT-d PI enabled or not".
>
>> The only difference is when the IPI arrives
>> at the pCPU which is happened in non-root mode, the patch will not raise a
>
>s/patch/code/ (or some such)
>
>> useless softirq since the IPI is consumed by hardware rather than raise a
>> softirq unconditionally.
>>
>> Quan doesn't have enough time to upstream this fix patch. He asks me to do
>> this. Merge another his related patch
>> (https://lists.xenproject.org/archives/html/xen-devel/2017-02/msg02885.html).
>
>This doesn't belong in the commit message, and hence should be after
>the first ---.
>
Will take care of this later.
>> --- a/xen/arch/x86/hvm/vmx/vmx.c
>> +++ b/xen/arch/x86/hvm/vmx/vmx.c
>> @@ -1842,13 +1842,59 @@ static void __vmx_deliver_posted_interrupt(struct vcpu *v)
>> bool_t running = v->is_running;
>>
>> vcpu_unblock(v);
>> + /*
>> + * The underlying 'IF' excludes two cases which we don't need further
>
>Who or what is 'IF'?
>
I meaned the 'if sentence'.
>> + * operation to make sure the target vCPU (@v) will sync PIR to vIRR ASAP.
>> + * Specifically, the two cases are:
>> + * 1. The target vCPU is not running, meaning it is blocked or runnable.
>> + * Since we have unblocked the target vCPU above, the target vCPU will
>> + * sync PIR to vIRR when it is chosen to run.
>> + * 2. The target vCPU is the current vCPU and in_irq() is false. It means
>> + * the function is called in noninterrupt context.
>
> * 2. The target vCPU is the current vCPU and we're in
> * non-interrupt context.
>
>> Since we don't call
>> + * the function in noninterrupt context after the last time a vCPU syncs
>> + * PIR to vIRR, excluding this case is also safe.
>
>It is not really clear to me what "the function" here refers to. Surely
>the function the comment is in won't call itself, no matter what
>context.
Yes, it is not clear. How about:
The target vCPU is the current vCPU and we're in non-interrupt context.
we can't be in the window between the call to vmx_intr_assist()
and interrupts getting disabled since no existed code reachs here in
non-interrupt context. Considering that, it is safe to just leave without
further operation.
Do you think this is correct? I have an assumption here to explain why
(in_irq() || (v != current)) is reasonable. It is totally my guess.
>
>> + */
>> 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 running on the same pCPU with the current
>> + * vCPU
>
>This is an impossible thing: There can't be two vCPU-s running on
>the same pCPU-s at the same time. Hence ...
>
>> and the current vCPU is in interrupt context. That's to say,
>> + * the target vCPU is the current vCPU.
>
>... just this last statement is sufficient here.
>
>> + * Note2: Don't worry the v->processor may change since at least when
>> + * the target vCPU is chosen to run or be blocked, there is a chance
>> + * to sync PIR to vIRR.
>> + */
>
>"There is a chance" reads as if it may or may not happen. How about
>"The vCPU being moved to another processor is guaranteed to sync
>PIR to vIRR, due to the involved scheduling cycle"? Of course only if
>this matches reality.
I think your description is right.
>
>> 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 a IPI to the pCPU. When the IPI arrives, the
>
>... an IPI ... (also at least once more below)
>
>> + * 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 the IPI
>> + * vector is special to the pCPU. If the target vCPU is running in
>> + * root-mode, the interrupt handler starts to run. In order to make
>> + * sure the target vCPU could go back to vmx_intr_assist(), the
>> + * interrupt handler should raise a softirq if no pending softirq.
>
>I don't understand this part: Calling vmx_intr_assist() is part of any
>VM entry, so if we're in root mode, the function will necessarily be
>called. Are you perhaps worried about the window between the call
>to vmx_intr_assist() and interrupts getting disabled (or any other
>similar one - I didn't make an attempt to collect a complete set)? If
>so, that's what needs to be mentioned here.
Yes. I only recognized this window. Will mention this window in next version.
>
>> + * 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 we think it is not a big issue. If the target
>
>Maybe "... which will not have any adverse effect"?
>
>> + * 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. Similarly,
>> + * there is a IPI and a softirq sent to a wrong vCPU.
>> + */
>> + if ( cpu != smp_process_id() )
>
>Did you not even build test this patch? I don't think the construct
>above compiles.
Really sorry. I forgot to commit after I fixed this.
Acturally, I found this, fixed it and tested this patch several times( with or
without VT-d PI) to avoid some obvious regression.
>
>> send_IPI_mask(cpumask_of(cpu), posted_intr_vector);
>> + /*
>> + * For case 2, raising a softirq can cause vmx_intr_assist() where PIR
>> + * has a chance to be synced to vIRR to be called. As an optimization,
>> + * We only need to raise a softirq when no pending softirq.
>
>How about "As any softirq will do, as an optimization we only raise
>one if none is pending already"? Again, if this is a valid statement
>only, of course.
Your description is correct imo and better.
Thanks,
Chao
>
>Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2017-03-02 4:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-02 1:49 [PATCH v3] x86/apicv: Enhance posted-interrupt processing Chao Gao
2017-03-02 9:41 ` Jan Beulich
2017-03-02 4:28 ` Chao Gao [this message]
2017-03-02 12:03 ` Jan Beulich
2017-03-03 8:01 ` Tian, Kevin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170302042806.GA12584@skl-2s3.sh.intel.com \
--to=chao.gao@intel.com \
--cc=JBeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=jun.nakajima@intel.com \
--cc=kevin.tian@intel.com \
--cc=quan.xu0@gmail.com \
--cc=xen-devel@lists.xen.org \
--cc=xuquan8@huawei.com \
--cc=yang.zhang.wz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).