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

[win-pv-devel] [PATCH 04/10] Separate checking upcall_pending in shared info from EvtchnPoll



The current EvtchnPoll routine in in the shared info code is tied to
the two level event channel ABI, wheras checking upcall_pending is ABI
independent. Hence the check should be separated into its own method.

This patch therefore introduces version 2 of the SHARED_INFO interface,
which has a new EvtchnUpcallPending method. Version 1 is still
supported by having its EvtchnPoll variant call EvtchnUpcallPending
method internally.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/shared_info_interface.h |  43 +++++++++-
 include/xen.h                   |   8 ++
 src/xen/system.c                |  20 ++++-
 src/xenbus/evtchn.c             |  16 +++-
 src/xenbus/shared_info.c        | 174 +++++++++++++++++++++++++++++-----------
 5 files changed, 207 insertions(+), 54 deletions(-)

diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
index 2e402a8..0d36ac8 100644
--- a/include/shared_info_interface.h
+++ b/include/shared_info_interface.h
@@ -63,11 +63,34 @@ typedef VOID
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENBUS_SHARED_INFO_UPCALL_PENDING
+    \brief Private method for EVTCHN inerface
+*/
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_UPCALL_PENDING)(
+    IN  PINTERFACE  Interface,
+    IN  ULONG       Cpu
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVENT)(
+    IN  PVOID   Argument,
+    IN  ULONG   Port
+    );
+
 /*! \typedef XENBUS_SHARED_INFO_EVTCHN_POLL
     \brief Private method for EVTCHN inerface
 */  
 typedef BOOLEAN
 (*XENBUS_SHARED_INFO_EVTCHN_POLL)(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVTCHN_POLL_V1)(
     IN  PINTERFACE  Interface,
     IN  BOOLEAN     (*Function)(PVOID, ULONG),
     IN  PVOID       Argument
@@ -123,6 +146,22 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     INTERFACE                           Interface;
     XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
     XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_EVTCHN_POLL_V1   SharedInfoEvtchnPollVersion1;
+    XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
+    XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
+    XENBUS_SHARED_INFO_EVTCHN_UNMASK    SharedInfoEvtchnUnmask;
+    XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
+};
+
+/*! \struct _XENBUS_SHARED_INFO_INTERFACE_V2
+    \brief SHARED_INFO interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_SHARED_INFO_INTERFACE_V2 {
+    INTERFACE                           Interface;
+    XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
+    XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_UPCALL_PENDING   SharedInfoUpcallPending;
     XENBUS_SHARED_INFO_EVTCHN_POLL      SharedInfoEvtchnPoll;
     XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
     XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
@@ -130,7 +169,7 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
 };
 
-typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, 
*PXENBUS_SHARED_INFO_INTERFACE;
+typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, 
*PXENBUS_SHARED_INFO_INTERFACE;
 
 /*! \def XENBUS_SHARED_INFO
     \brief Macro at assist in method invocation
@@ -141,6 +180,6 @@ typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 
XENBUS_SHARED_INFO_INTERFACE, *P
 #endif  // _WINDLL
 
 #define XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN    1
-#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    1
+#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENBUS_SHARED_INFO_H
diff --git a/include/xen.h b/include/xen.h
index 4a202fc..674676c 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -257,4 +257,12 @@ LogPrintf(
     ...
     );
 
+// SYSTEM
+
+XEN_API
+ULONG
+SystemVirtualCpuIndex(
+    IN  ULONG   Index
+    );
+
 #endif  // _XEN_H
diff --git a/src/xen/system.c b/src/xen/system.c
index a9d88c1..1ac8123 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#define XEN_API __declspec(dllexport)
+
 #include <ntddk.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
@@ -447,7 +449,7 @@ SystemPowerStateCallback(
     }
 }
 
-extern NTSTATUS
+NTSTATUS
 SystemInitialize(
     VOID
     )
@@ -503,7 +505,21 @@ fail1:
     return status;
 }
 
-extern VOID
+XEN_API
+ULONG
+SystemVirtualCpuIndex(
+    IN  ULONG           Index
+    )
+{
+    PSYSTEM_CONTEXT     Context = &SystemContext;
+    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
+
+    ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
+
+    return Cpu->ApicID / 2;
+}
+
+VOID
 SystemTeardown(
     VOID
     )
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 9ba2e84..35ad44a 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -665,10 +665,20 @@ EvtchnInterrupt(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return XENBUS_SHARED_INFO(EvtchnPoll,
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              EvtchnPollCallback,
-                              Context);
+                              0))
+        DoneSomething |= XENBUS_SHARED_INFO(EvtchnPoll,
+                                            &Context->SharedInfoInterface,
+                                            0,
+                                            EvtchnPollCallback,
+                                            Context);
+
+    return DoneSomething;
 }
 
 static VOID
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 41c99cf..0afc218 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -44,6 +44,7 @@ struct _XENBUS_SHARED_INFO_CONTEXT {
     LONG                        References;
     PHYSICAL_ADDRESS            Address;
     shared_info_t               *Shared;
+    ULONG                       Port;
     XENBUS_SUSPEND_INTERFACE    SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
@@ -128,7 +129,7 @@ SharedInfoTestBit(
 }
 
 static VOID
-SharedInfoMaskAll(
+SharedInfoEvtchnMaskAll(
     IN  PXENBUS_SHARED_INFO_CONTEXT Context
     )
 {
@@ -149,70 +150,105 @@ SharedInfoMaskAll(
 }
 
 static BOOLEAN
-SharedInfoEvtchnPoll(
+SharedInfoUpcallPending(
     IN  PINTERFACE              Interface,
-    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
-    IN  PVOID                   Argument OPTIONAL
+    IN  ULONG                   Cpu
     )
 {
     PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
-    shared_info_t               *Shared;
-    static ULONG                Port;
-    BOOLEAN                     DoneSomething;
+    shared_info_t               *Shared = Context->Shared;
+    int                         vcpu_id = SystemVirtualCpuIndex(Cpu);
+    UCHAR                       Pending;
 
-    Shared = Context->Shared;
+    KeMemoryBarrier();
 
-    DoneSomething = FALSE;
+    Pending = _InterlockedExchange8((CHAR 
*)&Shared->vcpu_info[vcpu_id].evtchn_upcall_pending, 0);
 
-    for (;;) {
-        UCHAR       Pending;
-        ULONG_PTR   SelectorMask;
+    return (Pending != 0) ? TRUE : FALSE;
+}
 
-        KeMemoryBarrier();
+static BOOLEAN
+SharedInfoEvtchnPoll(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument OPTIONAL
+    )
+{
+    PXENBUS_SHARED_INFO_CONTEXT     Context = Interface->Context;
+    shared_info_t                   *Shared = Context->Shared;
+    int                             vcpu_id = SystemVirtualCpuIndex(Cpu);
+    ULONG                           Port;
+    ULONG_PTR                       SelectorMask;
+    BOOLEAN                         DoneSomething;
 
-        Pending = _InterlockedExchange8((CHAR 
*)&Shared->vcpu_info[0].evtchn_upcall_pending, 0);
-        if (Pending == 0)
-            break;
+    DoneSomething = FALSE;
 
-        SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID 
*)&Shared->vcpu_info[0].evtchn_pending_sel, (PVOID)0);
+    KeMemoryBarrier();
 
-        KeMemoryBarrier();
+    SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID 
*)&Shared->vcpu_info[vcpu_id].evtchn_pending_sel, (PVOID)0);
+
+    KeMemoryBarrier();
 
-        while (SelectorMask != 0) {
-            ULONG   SelectorBit;
-            ULONG   PortBit;
+    Port = Context->Port;
 
-            SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-            PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+    while (SelectorMask != 0) {
+        ULONG   SelectorBit;
+        ULONG   PortBit;
 
-            if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
-                ULONG_PTR   PortMask;
 
-                PortMask = Shared->evtchn_pending[SelectorBit];
-                PortMask &= ~Shared->evtchn_mask[SelectorBit];
+        SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+        PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
+            ULONG_PTR   PortMask;
 
-                while (PortMask != 0 && PortBit < 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
-                    if (SharedInfoTestBit(&PortMask, PortBit)) {
-                        DoneSomething |= Function(Argument, (SelectorBit * 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
+            PortMask = Shared->evtchn_pending[SelectorBit];
+            PortMask &= ~Shared->evtchn_mask[SelectorBit];
 
-                        (VOID) SharedInfoClearBitUnlocked(&PortMask, PortBit);
-                    }
+            while (PortMask != 0 && PortBit < 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
+                if (SharedInfoTestBit(&PortMask, PortBit)) {
+                    DoneSomething |= Event(Argument, (SelectorBit * 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
 
-                    PortBit++;
+                    PortMask &= ~((ULONG_PTR)1 << PortBit);
                 }
 
-                // Are we done with this selector?
-                if (PortMask == 0)
-                    (VOID) SharedInfoClearBitUnlocked(&SelectorMask, 
SelectorBit);
+                PortBit++;
             }
 
-            Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-
-            if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
-                Port = 0;
+            // Are we done with this selector?
+            if (PortMask == 0)
+                SelectorMask &= ~((ULONG_PTR)1 << SelectorBit);
         }
+
+        Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * 
XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
+            Port = 0;
     }
 
+    Context->Port = Port;
+
+    return DoneSomething;
+}
+
+static BOOLEAN
+SharedInfoEvtchnPollVersion1(
+    IN  PINTERFACE              Interface,
+    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
+    IN  PVOID                   Argument OPTIONAL
+    )
+{
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (SharedInfoUpcallPending(Interface, 0))
+        DoneSomething |= SharedInfoEvtchnPoll(Interface,
+                                              0,
+                                              Function,
+                                              Argument);
+
     return DoneSomething;
 }
 
@@ -404,7 +440,7 @@ SharedInfoSuspendCallbackEarly(
     PXENBUS_SHARED_INFO_CONTEXT Context = Argument;
 
     SharedInfoMap(Context);
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 }
 
 static VOID
@@ -423,17 +459,30 @@ SharedInfoDebugCallback(
 
     if (!Crashing) {
         shared_info_t   *Shared;
+        LONG            Cpu;
         ULONG           Selector;
 
         Shared = Context->Shared;
 
         KeMemoryBarrier();
 
-        XENBUS_DEBUG(Printf,
-                     &Context->DebugInterface,
-                     "CPU: PENDING: %s SELECTOR MASK: %p\n",
-                     Shared->vcpu_info[0].evtchn_upcall_pending ? "TRUE" : 
"FALSE",
-                     (PVOID)Shared->vcpu_info[0].evtchn_pending_sel);
+        for (Cpu = 0; Cpu < KeNumberProcessors; Cpu++) {
+            int vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: PENDING: %s\n",
+                         Cpu,
+                         Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
+                         "TRUE" :
+                         "FALSE");
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: SELECTOR MASK: %p\n",
+                         Cpu,
+                         (PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
+        }
 
         for (Selector = 0; Selector < 
XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT; Selector += 4) {
             XENBUS_DEBUG(Printf,
@@ -490,7 +539,7 @@ SharedInfoAcquire(
     if (Context->Shared == NULL)
         goto fail2;
 
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
@@ -583,6 +632,8 @@ SharedInfoRelease (
 
     Trace("====>\n");
 
+    Context->Port = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
@@ -615,6 +666,18 @@ static struct _XENBUS_SHARED_INFO_INTERFACE_V1 
SharedInfoInterfaceVersion1 = {
     { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V1), 1, NULL, NULL, NULL },
     SharedInfoAcquire,
     SharedInfoRelease,
+    SharedInfoEvtchnPollVersion1,
+    SharedInfoEvtchnAck,
+    SharedInfoEvtchnMask,
+    SharedInfoEvtchnUnmask,
+    SharedInfoGetTime
+};
+
+static struct _XENBUS_SHARED_INFO_INTERFACE_V2 SharedInfoInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2), 2, NULL, NULL, NULL },
+    SharedInfoAcquire,
+    SharedInfoRelease,
+    SharedInfoUpcallPending,
     SharedInfoEvtchnPoll,
     SharedInfoEvtchnAck,
     SharedInfoEvtchnMask,
@@ -696,6 +759,23 @@ SharedInfoGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_SHARED_INFO_INTERFACE_V2 *SharedInfoInterface;
+
+        SharedInfoInterface = (struct _XENBUS_SHARED_INFO_INTERFACE_V2 
*)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2))
+            break;
+
+        *SharedInfoInterface = SharedInfoInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

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