[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/2] evtchn/fifo: initialize priority when events are bound



From: David Vrabel <david.vrabel@xxxxxxxxxx>

Event channel ports that are reused or that were not in the initial
bucket would have a non-default priority.

Add an init evtchn_port_op hook and use this to set the priority when
an event channel is bound.

Within this new evtchn_fifo_init() call, also check if the event is
already on a queue and print a warning, as this event may have its
first event delivered on a queue with the wrong VCPU or priority.
This guest is expected to prevent this (if it cares) by not unbinding
events that are still linked.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
---
 xen/common/event_channel.c |    5 +++++
 xen/common/event_fifo.c    |   17 +++++++++++++++++
 xen/include/xen/event.h    |    7 +++++++
 3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 34efd24..db952af 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -220,6 +220,7 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t 
*alloc)
     chn->state = ECS_UNBOUND;
     if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF )
         chn->u.unbound.remote_domid = current->domain->domain_id;
+    evtchn_port_init(d, chn);
 
     alloc->port = port;
 
@@ -276,6 +277,7 @@ static long 
evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
     lchn->u.interdomain.remote_dom  = rd;
     lchn->u.interdomain.remote_port = (u16)rport;
     lchn->state                     = ECS_INTERDOMAIN;
+    evtchn_port_init(ld, lchn);
     
     rchn->u.interdomain.remote_dom  = ld;
     rchn->u.interdomain.remote_port = (u16)lport;
@@ -330,6 +332,7 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
     chn->state          = ECS_VIRQ;
     chn->notify_vcpu_id = vcpu;
     chn->u.virq         = virq;
+    evtchn_port_init(d, chn);
 
     v->virq_to_evtchn[virq] = bind->port = port;
 
@@ -359,6 +362,7 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
     chn = evtchn_from_port(d, port);
     chn->state          = ECS_IPI;
     chn->notify_vcpu_id = vcpu;
+    evtchn_port_init(d, chn);
 
     bind->port = port;
 
@@ -437,6 +441,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
     chn->state  = ECS_PIRQ;
     chn->u.pirq.irq = pirq;
     link_pirq_port(port, chn, v);
+    evtchn_port_init(d, chn);
 
     bind->port = port;
 
diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c
index 6048784..2ab4c29 100644
--- a/xen/common/event_fifo.c
+++ b/xen/common/event_fifo.c
@@ -34,6 +34,22 @@ static inline event_word_t 
*evtchn_fifo_word_from_port(struct domain *d,
     return d->evtchn_fifo->event_array[p] + w;
 }
 
+static void evtchn_fifo_init(struct domain *d, struct evtchn *evtchn)
+{
+    event_word_t *word;
+
+    evtchn->priority = EVTCHN_FIFO_PRIORITY_DEFAULT;
+
+    /*
+     * If this event is still linked, the first event may be delivered
+     * on the wrong VCPU or with an unexpected priority.
+     */
+    word = evtchn_fifo_word_from_port(d, evtchn->port);
+    if ( word && test_bit(EVTCHN_FIFO_LINKED, word) )
+        gdprintk(XENLOG_WARNING, "domain %d, port %d already on a queue\n",
+                 d->domain_id, evtchn->port);
+}
+
 static int try_set_link(event_word_t *word, event_word_t *w, uint32_t link)
 {
     event_word_t new, old;
@@ -261,6 +277,7 @@ static void evtchn_fifo_print_state(struct domain *d,
 
 static const struct evtchn_port_ops evtchn_port_ops_fifo =
 {
+    .init          = evtchn_fifo_init,
     .set_pending   = evtchn_fifo_set_pending,
     .clear_pending = evtchn_fifo_clear_pending,
     .unmask        = evtchn_fifo_unmask,
diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h
index 70fc271..06c0654 100644
--- a/xen/include/xen/event.h
+++ b/xen/include/xen/event.h
@@ -132,6 +132,7 @@ void evtchn_2l_init(struct domain *d);
  * Low-level event channel port ops.
  */
 struct evtchn_port_ops {
+    void (*init)(struct domain *d, struct evtchn *evtchn);
     void (*set_pending)(struct vcpu *v, struct evtchn *evtchn);
     void (*clear_pending)(struct domain *d, struct evtchn *evtchn);
     void (*unmask)(struct domain *d, struct evtchn *evtchn);
@@ -142,6 +143,12 @@ struct evtchn_port_ops {
     void (*print_state)(struct domain *d, const struct evtchn *evtchn);
 };
 
+static inline void evtchn_port_init(struct domain *d, struct evtchn *evtchn)
+{
+    if ( d->evtchn_port_ops->init )
+        d->evtchn_port_ops->init(d, evtchn);
+}
+
 static inline void evtchn_port_set_pending(struct vcpu *v,
                                            struct evtchn *evtchn)
 {
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.