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

[Xen-changelog] Backtrack on the new interface for reserved event-channel



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 8f7aad20b4a5ba33762db56bb7e5cb94fe24395e
# Parent  e1152d55ea314944a4256354e163058d81bfbeba
Backtrack on the new interface for reserved event-channel
ports, as binding them in user space via the evtchn driver
would be a pain. Instead extend VIRQs so they can be
classified as 'global' or 'per vcpu'. The former can only
be allocated once per guest, but can be re-bound to
an arbitrary VCPU.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/arch/ia64/xen/xentime.c
--- a/xen/arch/ia64/xen/xentime.c       Wed Apr  5 16:41:51 2006
+++ b/xen/arch/ia64/xen/xentime.c       Wed Apr  5 18:30:02 2006
@@ -274,6 +274,6 @@
 
 void send_timer_event(struct vcpu *v)
 {
-       send_guest_virq(v, VIRQ_TIMER);
-}
-
+       send_guest_vcpu_virq(v, VIRQ_TIMER);
+}
+
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Wed Apr  5 16:41:51 2006
+++ b/xen/arch/x86/time.c       Wed Apr  5 18:30:02 2006
@@ -916,7 +916,7 @@
 
 void send_timer_event(struct vcpu *v)
 {
-    send_guest_virq(v, VIRQ_TIMER);
+    send_guest_vcpu_virq(v, VIRQ_TIMER);
 }
 
 /*
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/common/domain.c
--- a/xen/common/domain.c       Wed Apr  5 16:41:51 2006
+++ b/xen/common/domain.c       Wed Apr  5 18:30:02 2006
@@ -137,7 +137,7 @@
         domain_relinquish_resources(d);
         put_domain(d);
 
-        send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
+        send_guest_global_virq(dom0, VIRQ_DOM_EXC);
     }
 }
 
@@ -192,7 +192,7 @@
 
     /* Don't set DOMF_shutdown until execution contexts are sync'ed. */
     if ( !test_and_set_bit(_DOMF_shutdown, &d->domain_flags) )
-        send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
+        send_guest_global_virq(dom0, VIRQ_DOM_EXC);
 
     UNLOCK_BIGLOCK(d);
 
@@ -267,7 +267,7 @@
     for_each_vcpu ( d, v )
         vcpu_sleep_nosync(v);
 
-    send_guest_virq(dom0->vcpu[0], VIRQ_DEBUGGER);
+    send_guest_global_virq(dom0, VIRQ_DEBUGGER);
 }
 
 
@@ -307,7 +307,7 @@
 
     free_domain(d);
 
-    send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
+    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
 }
 
 void vcpu_pause(struct vcpu *v)
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Wed Apr  5 16:41:51 2006
+++ b/xen/common/event_channel.c        Wed Apr  5 18:30:02 2006
@@ -3,7 +3,7 @@
  * 
  * Event notifications from VIRQs, PIRQs, and other domains.
  * 
- * Copyright (c) 2003-2005, K A Fraser.
+ * Copyright (c) 2003-2006, K A Fraser.
  * 
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -47,6 +47,27 @@
     } while ( 0 )
 
 
+static int virq_is_global(int virq)
+{
+    int rc;
+
+    ASSERT((virq >= 0) && (virq < NR_VIRQS));
+
+    switch ( virq )
+    {
+    case VIRQ_TIMER:
+    case VIRQ_DEBUG:
+        rc = 0;
+        break;
+    default:
+        rc = 1;
+        break;
+    }
+
+    return rc;
+}
+
+
 static int get_free_port(struct domain *d)
 {
     struct evtchn *chn;
@@ -180,6 +201,9 @@
     long           rc = 0;
 
     if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
+        return -EINVAL;
+
+    if ( virq_is_global(virq) && (vcpu != 0) )
         return -EINVAL;
 
     if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || ((v = d->vcpu[vcpu]) == NULL) )
@@ -474,19 +498,43 @@
 }
 
 
-void send_guest_virq(struct vcpu *v, int virq)
-{
-    int port = v->virq_to_evtchn[virq];
-
-    if ( likely(port != 0) )
-        evtchn_set_pending(v, port);
+void send_guest_vcpu_virq(struct vcpu *v, int virq)
+{
+    int port;
+
+    ASSERT(!virq_is_global(virq));
+
+    port = v->virq_to_evtchn[virq];
+    if ( unlikely(port == 0) )
+        return;
+
+    evtchn_set_pending(v, port);
+}
+
+void send_guest_global_virq(struct domain *d, int virq)
+{
+    int port;
+    struct evtchn *chn;
+
+    ASSERT(virq_is_global(virq));
+
+    port = d->vcpu[0]->virq_to_evtchn[virq];
+    if ( unlikely(port == 0) )
+        return;
+
+    chn = evtchn_from_port(d, port);
+    evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
 }
 
 
 void send_guest_pirq(struct domain *d, int pirq)
 {
     int port = d->pirq_to_evtchn[pirq];
-    struct evtchn *chn = evtchn_from_port(d, port);
+    struct evtchn *chn;
+
+    ASSERT(port != 0);
+
+    chn = evtchn_from_port(d, port);
     evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
 }
 
@@ -576,6 +624,12 @@
     chn = evtchn_from_port(d, port);
     switch ( chn->state )
     {
+    case ECS_VIRQ:
+        if ( virq_is_global(chn->u.virq) )
+            chn->notify_vcpu_id = vcpu_id;
+        else
+            rc = -EINVAL;
+        break;
     case ECS_UNBOUND:
     case ECS_INTERDOMAIN:
     case ECS_PIRQ:
@@ -702,41 +756,6 @@
 }
 
 
-int evtchn_open_reserved_port(struct domain *d)
-{
-    struct evtchn *chn;
-    int            port;
-
-    spin_lock(&d->evtchn_lock);
-
-    if ( (port = get_free_port(d)) >= 0 )
-    {
-        chn = evtchn_from_port(d, port);
-        chn->state = ECS_RESERVED;
-    }
-
-    spin_unlock(&d->evtchn_lock);
-
-    return port;
-}
-
-
-void evtchn_close_reserved_port(struct domain *d, int port)
-{
-    struct evtchn *chn;
-
-    spin_lock(&d->evtchn_lock);
-
-    BUG_ON(!port_is_valid(d, port));
-
-    chn = evtchn_from_port(d, port);
-    chn->state          = ECS_FREE;
-    chn->notify_vcpu_id = 0;
-
-    spin_unlock(&d->evtchn_lock);
-}
-
-
 void evtchn_notify_reserved_port(struct domain *d, int port)
 {
     struct evtchn *chn = evtchn_from_port(d, port);
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/common/keyhandler.c
--- a/xen/common/keyhandler.c   Wed Apr  5 16:41:51 2006
+++ b/xen/common/keyhandler.c   Wed Apr  5 18:30:02 2006
@@ -162,7 +162,7 @@
                             &d->shared_info->evtchn_mask[0]),
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_LONG, 
                             &v->vcpu_info->evtchn_pending_sel));
-            send_guest_virq(v, VIRQ_DEBUG);
+            send_guest_vcpu_virq(v, VIRQ_DEBUG);
         }
     }
 
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Wed Apr  5 16:41:51 2006
+++ b/xen/drivers/char/console.c        Wed Apr  5 18:30:02 2006
@@ -294,7 +294,7 @@
     if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
         serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
     /* Always notify the guest: prevents receive path from getting stuck. */
-    send_guest_virq(dom0->vcpu[0], VIRQ_CONSOLE);
+    send_guest_global_virq(dom0, VIRQ_CONSOLE);
 }
 
 static void serial_rx(char c, struct cpu_user_regs *regs)
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/include/public/event_channel.h
--- a/xen/include/public/event_channel.h        Wed Apr  5 16:41:51 2006
+++ b/xen/include/public/event_channel.h        Wed Apr  5 18:30:02 2006
@@ -50,9 +50,13 @@
  * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
  * vcpu.
  * NOTES:
- *  1. A virtual IRQ may be bound to at most one event channel per vcpu.
- *  2. The allocated event channel is bound to the specified vcpu. The binding
- *     may not be changed.
+ *  1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
+ *     in xen.h for the classification of each VIRQ.
+ *  2. Global VIRQs must be allocated on VCPU0 but can subsequently be
+ *     re-bound via EVTCHNOP_bind_vcpu.
+ *  3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
+ *     The allocated event channel is bound to the specified vcpu and the
+ *     binding cannot be changed.
  */
 #define EVTCHNOP_bind_virq        1
 typedef struct evtchn_bind_virq {
@@ -152,9 +156,11 @@
  * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
  * event is pending.
  * NOTES:
- *  1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
- *     the binding. This binding cannot be changed.
- *  2. All other channels notify vcpu0 by default. This default is set when
+ *  1. IPI-bound channels always notify the vcpu specified at bind time.
+ *     This binding cannot be changed.
+ *  2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
+ *     This binding cannot be changed.
+ *  3. All other channels notify vcpu0 by default. This default is set when
  *     the channel is allocated (a port that is freed and subsequently reused
  *     has its binding reset to vcpu0).
  */
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Wed Apr  5 16:41:51 2006
+++ b/xen/include/public/xen.h  Wed Apr  5 18:30:02 2006
@@ -65,12 +65,17 @@
  * VIRTUAL INTERRUPTS
  * 
  * Virtual interrupts that a guest OS may receive from Xen.
- */
-#define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
-#define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
-#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
-#define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
-#define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+ * 
+ * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
+ * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
+ * The latter can be allocated only once per guest: they must initially be
+ * allocated to VCPU0 but can subsequently be re-bound.
+ */
+#define VIRQ_TIMER      0  /* V. Timebase update, and/or requested timeout.  */
+#define VIRQ_DEBUG      1  /* V. Request guest to dump debug info.           */
+#define VIRQ_CONSOLE    2  /* G. (DOM0) Bytes received on emergency console. */
+#define VIRQ_DOM_EXC    3  /* G. (DOM0) Exceptional event for some domain.   */
+#define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
 #define NR_VIRQS        8
 
 /*
diff -r e1152d55ea31 -r 8f7aad20b4a5 xen/include/xen/event.h
--- a/xen/include/xen/event.h   Wed Apr  5 16:41:51 2006
+++ b/xen/include/xen/event.h   Wed Apr  5 18:30:02 2006
@@ -3,7 +3,7 @@
  * 
  * A nice interface for passing asynchronous events to guest OSes.
  * 
- * Copyright (c) 2002-2005, K A Fraser
+ * Copyright (c) 2002-2006, K A Fraser
  */
 
 #ifndef __XEN_EVENT_H__
@@ -18,11 +18,18 @@
 extern void evtchn_set_pending(struct vcpu *v, int port);
 
 /*
- * send_guest_virq:
+ * send_guest_vcpu_virq: Notify guest via a per-VCPU VIRQ.
  *  @v:        VCPU to which virtual IRQ should be sent
  *  @virq:     Virtual IRQ number (VIRQ_*)
  */
-extern void send_guest_virq(struct vcpu *v, int virq);
+extern void send_guest_vcpu_virq(struct vcpu *v, int virq);
+
+/*
+ * send_guest_global_virq: Notify guest via a global VIRQ.
+ *  @d:        Domain to which virtual IRQ should be sent
+ *  @virq:     Virtual IRQ number (VIRQ_*)
+ */
+extern void send_guest_global_virq(struct domain *d, int virq);
 
 /*
  * send_guest_pirq:
@@ -45,9 +52,4 @@
 /* Bind a local event-channel port to the specified VCPU. */
 extern long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id);
 
-/* Reserved event-channel ports for other Xen subsystems. */
-int evtchn_open_reserved_port(struct domain *d);
-void evtchn_close_reserved_port(struct domain *d, int port);
-void evtchn_notify_reserved_port(struct domain *d, int port);
-
 #endif /* __XEN_EVENT_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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