xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ian Campbell <Ian.Campbell@citrix.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: julien.grall@citrix.com, xen-devel@lists.xensource.com
Subject: Re: [PATCH v4 2/6] xen/arm: track the state of guest IRQs
Date: Thu, 12 Dec 2013 12:03:49 +0000	[thread overview]
Message-ID: <1386849829.11201.13.camel@kazak.uk.xensource.com> (raw)
In-Reply-To: <1386788841-32471-2-git-send-email-stefano.stabellini@eu.citrix.com>

On Wed, 2013-12-11 at 19:07 +0000, Stefano Stabellini wrote:
> Introduce a status field in struct pending_irq. Valid states are
> GUEST_PENDING, GUEST_VISIBLE and GUEST_ENABLED and they are not mutually
> exclusive.  See the in-code comment for an explanation of the states and
> how they are used.
> Use atomic operations to set and clear the status bits. Note that
> setting GIC_IRQ_GUEST_VISIBLE and clearing GIC_IRQ_GUEST_PENDING can be
> done in two separate operations as the underlying pending status is
> actually only cleared on the LR after the guest ACKs the interrupts.
> Until that happens it's not possible to receive another interrupt.
> 
> The main effect of this patch is that an IRQ can be set to GUEST_PENDING
> while it is being serviced by the guest. In maintenance_interrupt we
> check whether GUEST_PENDING is set and if it is we add the irq back into
> the lr_pending queue so that it's going to be reinjected one more time,
> if the interrupt is still enabled at the vgicd level.
> If it is not, it is going to be injected as soon as the guest renables
> the interrupt.
> 
> One exception is evtchn_irq: in that case we don't want to
> set the GIC_IRQ_GUEST_PENDING bit if it is already GUEST_VISIBLE,
> because as part of the event handling loop, the guest would realize that
> new events are present even without a new notification.
> Also we already have a way to figure out exactly when we do need to
> inject a second notification if vgic_vcpu_inject_irq is called after the
> end of the guest event handling loop and before the guest EOIs the
> interrupt (see db453468d92369e7182663fb13e14d83ec4ce456 "arm: vgic: fix
> race between evtchn upcall and evtchnop_send").
> 
> In maintenance_interrupt only stop injecting interrupts if no new
> interrupts have been added to the LRs.
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> 
> ---
> Changes in v2:
> - use atomic operations to modify the pending_irq status bits, remove
> the now unnecessary locks;
> - make status unsigned long;
> - in maintenance_interrupt only stops injecting interrupts if no new
> interrupts have been added to the LRs;
> - add a state to keep track whether the guest irq is enabled at the
> vgicd level;
> 
> Changes in v3:
> - do not set the GUEST_PENDING bit for evtchn_irq if the irq is already
> guest visible.
> 
> Changes in v4:
> - move set_bit _GIC_IRQ_GUEST_VISIBLE and clear_bit
> _GIC_IRQ_GUEST_PENDING to gic_set_lr;
> - turn set_int into a bool_t;
> - remove raw GIC_IRQ_GUEST values;
> - in maintenance_interrupt if the irq is still PENDING, add it back into
> the lr_pending queue instead of immediately reinjecting it.
> ---
>  xen/arch/arm/gic.c           |   54 ++++++++++++++++++++++++++++++++----------
>  xen/arch/arm/vgic.c          |   17 ++++++++++---
>  xen/include/asm-arm/domain.h |   37 +++++++++++++++++++++++++++++
>  3 files changed, 93 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 5f7a548..19e0ae4 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -615,6 +615,7 @@ static inline void gic_set_lr(int lr, unsigned int virtual_irq,
>          unsigned int state, unsigned int priority)
>  {
>      int maintenance_int = GICH_LR_MAINTENANCE_IRQ;
> +    struct pending_irq *p = irq_to_pending(current, virtual_irq);
>  
>      BUG_ON(lr >= nr_lrs);
>      BUG_ON(lr < 0);
> @@ -624,6 +625,9 @@ static inline void gic_set_lr(int lr, unsigned int virtual_irq,
>          maintenance_int |
>          ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) |
>          ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT);
> +
> +    set_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
> +    clear_bit(GIC_IRQ_GUEST_PENDING, &p->status);

So WRT races in vgic_vcpu_inject_irq we were discussing on v3. The above
vs:

+        if ( (irq != current->domain->arch.evtchn_irq) ||
+             (!test_bit(_GIC_IRQ_GUEST_VISIBLE, &n->status)) )
+            set_bit(_GIC_IRQ_GUEST_PENDING, &n->status);

If one cpu (A) is in gic_set_lr while another (B) is in
vgic_vcpu_inject_irq, is there any ordering which fails to do the right
thing.

        A -- set VISIBLE
        B -- test VISIBLE
        B -- set PENDING
        A -- clear PENDING

Doesn't seem right?

        B -- test VISIBLE
        A -- set VISIBLE
        A -- clear PENDING
        B -- doesn't set PENDING
        
Seems OK.

        A -- set VISIBLE
    B -- test VISIBLE
    A -- clear PENDING
    B -- set PENDING

OK?

        B -- test VISIBLE
    A -- set VISIBLE
        B -- set PENDING
        A -- clear PENDING
   
Wrong?

If A clear's pending first does that work out right every time?

Ian.

  reply	other threads:[~2013-12-12 12:03 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-11 19:06 [PATCH v4 0/6] interrupt handling fixes Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 1/6] xen/arm: Physical IRQ is not always equal to virtual IRQ Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 2/6] xen/arm: track the state of guest IRQs Stefano Stabellini
2013-12-12 12:03   ` Ian Campbell [this message]
2013-12-12 15:09     ` Stefano Stabellini
2013-12-12 12:18   ` Ian Campbell
2013-12-12 15:17     ` Stefano Stabellini
2013-12-12 15:23       ` Ian Campbell
2013-12-12 15:25         ` Stefano Stabellini
2013-12-12 15:45           ` Ian Campbell
2013-12-12 15:46             ` Ian Campbell
2013-12-12 15:50               ` Stefano Stabellini
2013-12-12 15:48             ` Stefano Stabellini
2013-12-12 15:56   ` Ian Campbell
2013-12-12 16:06     ` Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 3/6] xen/arm: do not add a second irq to the LRs if one is already present Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 4/6] xen/arm: implement gic_irq_enable and gic_irq_disable Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 5/6] xen/arm: Only enable physical IRQs when the guest asks Stefano Stabellini
2013-12-11 19:07 ` [PATCH v4 6/6] xen/arm: disable a physical IRQ when the guest disables the corresponding IRQ Stefano Stabellini
2013-12-12 16:06   ` Ian Campbell
2013-12-12 16:34     ` Stefano Stabellini

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=1386849829.11201.13.camel@kazak.uk.xensource.com \
    --to=ian.campbell@citrix.com \
    --cc=julien.grall@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xensource.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).