xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: David Vrabel <david.vrabel@citrix.com>
To: xen-devel@lists.xen.org
Cc: Keir Fraser <keir@xen.org>,
	David Vrabel <david.vrabel@citrix.com>,
	Jan Beulich <jan.beulich@suse.com>
Subject: [PATCH 2/3] evtchn: don't lose pending state if FIFO event array page is missing
Date: Thu, 31 Oct 2013 15:03:10 +0000	[thread overview]
Message-ID: <1383231791-4604-3-git-send-email-david.vrabel@citrix.com> (raw)
In-Reply-To: <1383231791-4604-1-git-send-email-david.vrabel@citrix.com>

From: David Vrabel <david.vrabel@citrix.com>

When the FIFO-based ABI is in use, if an event is bound when the
corresponding event array page is missing any attempt to set the event
pending will lose the event (because there is nowhere to write the
pending state).

This wasn't initially considered an issue because guests were expected
to only bind events once they had expanded the event array, however:

1. A domain may start with events already bound (by the toolstack).

2. The guest does not know what the port number will be until the
   event is bound (it doesn't know how many already bound events there
   are), so it does not know how many event array pages are required.
   This makes it difficult to expand in advanced (the current Linux
   implementation expands after binding for example).

To prevent pending events from being lost because there is no array
page, temporarily store the pending state in evtchn->pending.  When an
array page is added, use this state to set the port as pending.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 xen/common/event_fifo.c |   47 +++++++++++++++++++++++++++++++++++++++++------
 xen/include/xen/sched.h |    1 +
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c
index bec8d87..64dbfff 100644
--- a/xen/common/event_fifo.c
+++ b/xen/common/event_fifo.c
@@ -61,8 +61,16 @@ static void evtchn_fifo_set_pending(struct vcpu *v, struct evtchn *evtchn)
 
     port = evtchn->port;
     word = evtchn_fifo_word_from_port(d, port);
+
+    /*
+     * Event array page may not exist yet, save the pending state for
+     * when the page is added.
+     */
     if ( unlikely(!word) )
+    {
+        evtchn->pending = 1;
         return;
+    }
 
     /*
      * No locking around getting the queue. This may race with
@@ -322,16 +330,29 @@ static void cleanup_event_array(struct domain *d)
     xfree(d->evtchn_fifo);
 }
 
-static void set_priority_all(struct domain *d, unsigned int priority)
+static void setup_ports(struct domain *d)
 {
     unsigned int port;
 
+    /*
+     * For each port that is already bound:
+     *
+     * - save its pending state.
+     * - set default priority.
+     */
     for ( port = 1; port < d->max_evtchns; port++ )
     {
+        struct evtchn *evtchn;
+
         if ( !port_is_valid(d, port) )
             break;
 
-        evtchn_port_set_priority(d, evtchn_from_port(d, port), priority);
+        evtchn = evtchn_from_port(d, port);
+
+        if ( test_bit(port, &shared_info(d, evtchn_pending)) )
+            evtchn->pending = 1;
+
+        evtchn_fifo_set_priority(d, evtchn, EVTCHN_FIFO_PRIORITY_DEFAULT);
     }
 }
 
@@ -369,9 +390,6 @@ int evtchn_fifo_init_control(struct evtchn_init_control *init_control)
     /*
      * If this is the first control block, setup an empty event array
      * and switch to the fifo port ops.
-     *
-     * Any ports currently bound will have their priority set to the
-     * default.
      */
     if ( rc == 0 && !d->evtchn_fifo )
     {
@@ -382,7 +400,7 @@ int evtchn_fifo_init_control(struct evtchn_init_control *init_control)
         {
             d->evtchn_port_ops = &evtchn_port_ops_fifo;
             d->max_evtchns = EVTCHN_FIFO_NR_CHANNELS;
-            set_priority_all(d, EVTCHN_FIFO_PRIORITY_DEFAULT);
+            setup_ports(d);
         }
     }
 
@@ -395,6 +413,7 @@ static int add_page_to_event_array(struct domain *d, unsigned long gfn)
 {
     void *virt;
     unsigned int slot;
+    unsigned int port = d->evtchn_fifo->num_evtchns;
     int rc;
 
     slot = d->evtchn_fifo->num_evtchns / EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
@@ -408,6 +427,22 @@ static int add_page_to_event_array(struct domain *d, unsigned long gfn)
     d->evtchn_fifo->event_array[slot] = virt;
     d->evtchn_fifo->num_evtchns += EVTCHN_FIFO_EVENT_WORDS_PER_PAGE;
 
+    /*
+     * Re-raise any events that were pending while this array page was
+     * missing.
+     */
+    for ( ; port < d->evtchn_fifo->num_evtchns; port++ )
+    {
+        struct evtchn *evtchn;
+
+        if ( !port_is_valid(d, port) )
+            break;
+
+        evtchn = evtchn_from_port(d, port);
+        if ( evtchn->pending )
+            evtchn_fifo_set_pending(d->vcpu[evtchn->notify_vcpu_id], evtchn);
+    }
+
     return 0;
 }
 
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 25bf637..624ea15 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -97,6 +97,7 @@ struct evtchn
         u16 virq;      /* state == ECS_VIRQ */
     } u;
     u8 priority;
+    u8 pending:1;
 #ifdef FLASK_ENABLE
     void *ssid;
 #endif
-- 
1.7.2.5

  parent reply	other threads:[~2013-10-31 15:03 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-31 15:03 [PATCHv2 0/3] Xen: FIFO-based event channel ABI fixes David Vrabel
2013-10-31 15:03 ` [PATCH 1/3] MAINTAINERS: Add FIFO-based event channel ABI maintainer David Vrabel
2013-11-04 14:29   ` Jan Beulich
2013-11-05 21:06     ` Keir Fraser
2013-11-06 11:49       ` David Vrabel
2013-11-06 12:40         ` Jan Beulich
2013-10-31 15:03 ` David Vrabel [this message]
2013-11-04 14:29   ` [PATCH 2/3] evtchn: don't lose pending state if FIFO event array page is missing Jan Beulich
2013-11-05 21:07     ` Keir Fraser
2013-10-31 15:03 ` [PATCH 3/3] evtchn/fifo: don't spin indefinitely when setting LINK David Vrabel
2013-10-31 18:13   ` Boris Ostrovsky
2013-11-04 14:39   ` Jan Beulich
2013-11-04 14:52     ` David Vrabel
2013-11-04 14:57       ` Jan Beulich
2013-11-04 16:30         ` David Vrabel
2013-11-05 14:18           ` Jan Beulich
2013-11-04 15:07       ` Ian Campbell
2013-11-04 15:11         ` David Vrabel
2013-11-05 14:19   ` Jan Beulich
2013-11-05 14:25   ` Jan Beulich
2013-11-06 13:38   ` David Vrabel
2013-11-06 15:01     ` Boris Ostrovsky
2013-11-06 15:07       ` David Vrabel
2013-11-10 21:21   ` Matt Wilson
2013-10-31 15:13 ` [PATCHv2 0/3] Xen: FIFO-based event channel ABI fixes David Vrabel

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=1383231791-4604-3-git-send-email-david.vrabel@citrix.com \
    --to=david.vrabel@citrix.com \
    --cc=jan.beulich@suse.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xen.org \
    /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).