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

[PATCH xenbus 05/12] Update the XENBUS_EVTCHN interface...



From: Paul Durrant <pdurrant@xxxxxxxxxx>

... to allow 'vcpu_id' to be sepcified to the EvtchnOpen() method, when
opening a VIRQ channel.

Non-global VIRQ channels (such as VIRQ_DEBUG and VIRQ_TIMER) can be bound to
a specific vCPU. To allow callers of EvtchnOpen() to do this, it is necessary
for extra arguments to be passed to EvtchnOpenVirq().

This patch updates the version of XENBUS_EVTCHN from 8 to 9, despite there
being no function type change (since EvtchnOpen() is a variadic method) and
modifies the implemention of EvtchnOpen() to pass the number of arguments to
its type-specific helpers. Hence EvtchnOpenVirq() can determine whether or
not it is being supplied with vCPU infomation.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 include/evtchn_interface.h | 25 +++++++++-
 include/revision.h         |  3 +-
 include/xen.h              |  5 +-
 src/xen/event_channel.c    |  3 +-
 src/xenbus/evtchn.c        | 99 +++++++++++++++++++++++++++++++++++---
 src/xenbus/fdo.c           | 15 ++++--
 6 files changed, 135 insertions(+), 15 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index ade725902421..fffde05bf1da 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -100,6 +100,8 @@ typedef VOID
 
     \b VIRQ:
     \param Index The index number of the VIRQ
+    \param Group The group number of the CPU that should handle the VIRQ
+    \param Number The relative number of the CPU that should handle the VIRQ
 
     \return Event channel handle
 */  
@@ -340,7 +342,26 @@ struct _XENBUS_EVTCHN_INTERFACE_V8 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V8 XENBUS_EVTCHN_INTERFACE, 
*PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V9
+    \brief EVTCHN interface version 9
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V9 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_COUNT EvtchnGetCount;
+    XENBUS_EVTCHN_WAIT      EvtchnWait;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V9 XENBUS_EVTCHN_INTERFACE, 
*PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -351,7 +372,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V8 
XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 4
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 8
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 9
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/revision.h b/include/revision.h
index 01b673722374..3a6b398e93a3 100644
--- a/include/revision.h
+++ b/include/revision.h
@@ -57,6 +57,7 @@
     DEFINE_REVISION(0x09000004,  1,  2,  8,  1,  2,  1,  1,  3,  1,  1,  1), \
     DEFINE_REVISION(0x09000005,  1,  2,  8,  1,  2,  1,  2,  4,  1,  1,  1), \
     DEFINE_REVISION(0x09000006,  1,  3,  8,  1,  2,  1,  2,  4,  1,  1,  1), \
-    DEFINE_REVISION(0x09000007,  1,  3,  8,  1,  2,  1,  2,  4,  1,  1,  2)
+    DEFINE_REVISION(0x09000007,  1,  3,  8,  1,  2,  1,  2,  4,  1,  1,  2), \
+    DEFINE_REVISION(0x09000008,  1,  3,  9,  1,  2,  1,  2,  4,  1,  1,  2)
 
 #endif  // _REVISION_H
diff --git a/include/xen.h b/include/xen.h
index c2babc0c0280..3532de839176 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -177,8 +177,9 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindVirq(
-    IN  ULONG   Virq,
-    OUT ULONG   *LocalPort
+    IN  ULONG           Virq,
+    IN  unsigned int    vcpu_id,
+    OUT ULONG           *LocalPort
     );
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index c2ce6a241c8b..2bce1c1c163b 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -145,6 +145,7 @@ XEN_API
 NTSTATUS
 EventChannelBindVirq(
     IN  ULONG               Virq,
+    IN  unsigned int        vcpu_id,
     OUT ULONG               *LocalPort
     )
 {
@@ -153,7 +154,7 @@ EventChannelBindVirq(
     NTSTATUS                status;
 
     op.virq = Virq;
-    op.vcpu = 0;
+    op.vcpu = vcpu_id;
 
     rc = EventChannelOp(EVTCHNOP_bind_virq, &op);
 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 8c8c1648d007..4a764c071433 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -138,13 +138,18 @@ __EvtchnFree(
 
 static NTSTATUS
 EvtchnOpenFixed(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Count,
     IN  va_list                 Arguments
     )
 {
     ULONG                       LocalPort;
     BOOLEAN                     Mask;
 
+    UNREFERENCED_PARAMETER(Context);
+
+    ASSERT3U(Count, ==, 2);
     LocalPort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
 
@@ -156,7 +161,9 @@ EvtchnOpenFixed(
 
 static NTSTATUS
 EvtchnOpenUnbound(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Count,
     IN  va_list                 Arguments
     )
 {
@@ -165,6 +172,9 @@ EvtchnOpenUnbound(
     ULONG                       LocalPort;
     NTSTATUS                    status;
 
+    UNREFERENCED_PARAMETER(Context);
+
+    ASSERT3U(Count, ==, 2);
     RemoteDomain = va_arg(Arguments, USHORT);
     Mask = va_arg(Arguments, BOOLEAN);
 
@@ -187,7 +197,9 @@ fail1:
 
 static NTSTATUS
 EvtchnOpenInterDomain(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Count,
     IN  va_list                 Arguments
     )
 {
@@ -197,6 +209,9 @@ EvtchnOpenInterDomain(
     ULONG                       LocalPort;
     NTSTATUS                    status;
 
+    UNREFERENCED_PARAMETER(Context);
+
+    ASSERT3U(Count, ==, 3);
     RemoteDomain = va_arg(Arguments, USHORT);
     RemotePort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
@@ -223,26 +238,63 @@ fail1:
 
 static NTSTATUS
 EvtchnOpenVirq(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Count,
     IN  va_list                 Arguments
     )
 {
     ULONG                       Index;
+    USHORT                      Group;
+    UCHAR                       Number;
+    PROCESSOR_NUMBER            ProcNumber;
+    ULONG                       Cpu;
+    PXENBUS_EVTCHN_PROCESSOR    Processor;
+    unsigned int                vcpu_id;
     ULONG                       LocalPort;
     NTSTATUS                    status;
 
     Index = va_arg(Arguments, ULONG);
 
-    status = EventChannelBindVirq(Index, &LocalPort);
-    if (!NT_SUCCESS(status))
+    if (Count == 1) {
+        Group = 0;
+        Number = 0;
+    } else {
+        ASSERT3U(Count, ==, 3);
+
+        Group = va_arg(Arguments, USHORT);
+        Number = va_arg(Arguments, UCHAR);
+    }
+
+    RtlZeroMemory(&ProcNumber, sizeof (PROCESSOR_NUMBER));
+    ProcNumber.Group = Group;
+    ProcNumber.Number = Number;
+
+    Cpu = KeGetProcessorIndexFromNumber(&ProcNumber);
+
+    ASSERT3U(Cpu, <, Context->ProcessorCount);
+    Processor = &Context->Processor[Cpu];
+
+    status = STATUS_NOT_SUPPORTED;
+    if (!Processor->UpcallEnabled)
         goto fail1;
 
+    status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+    ASSERT(NT_SUCCESS(status));
+
+    status = EventChannelBindVirq(Index, vcpu_id, &LocalPort);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     Channel->Parameters.Virq.Index = Index;
 
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -292,19 +344,22 @@ EvtchnOpen(
     va_start(Arguments, Argument);
     switch (Type) {
     case XENBUS_EVTCHN_TYPE_FIXED:
-        status = EvtchnOpenFixed(Channel, Arguments);
+        status = EvtchnOpenFixed(Context, Channel, 2, Arguments);
         break;
 
     case XENBUS_EVTCHN_TYPE_UNBOUND:
-        status = EvtchnOpenUnbound(Channel, Arguments);
+        status = EvtchnOpenUnbound(Context, Channel, 2, Arguments);
         break;
 
     case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
-        status = EvtchnOpenInterDomain(Channel, Arguments);
+        status = EvtchnOpenInterDomain(Context, Channel, 3, Arguments);
         break;
 
     case XENBUS_EVTCHN_TYPE_VIRQ:
-        status = EvtchnOpenVirq(Channel, Arguments);
+        // Processor information only specified from version 9 onwards
+        status = EvtchnOpenVirq(Context, Channel,
+                                (Interface->Version < 9) ? 1 : 3,
+                                Arguments);
         break;
 
     default:
@@ -1762,6 +1817,21 @@ static struct _XENBUS_EVTCHN_INTERFACE_V8 
EvtchnInterfaceVersion8 = {
     EvtchnClose,
 };
 
+static struct _XENBUS_EVTCHN_INTERFACE_V9 EvtchnInterfaceVersion9 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V9), 9, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetCount,
+    EvtchnWait,
+    EvtchnGetPort,
+    EvtchnClose,
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1955,6 +2025,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 9: {
+        struct _XENBUS_EVTCHN_INTERFACE_V9  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V9 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V9))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion9;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index cdcfc85d6090..852f2b85c7ee 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -2797,9 +2797,11 @@ static FORCEINLINE NTSTATUS
 __FdoVirqCreate(
     IN  PXENBUS_FDO     Fdo,
     IN  ULONG           Type,
+    IN  ULONG           Cpu,
     OUT PXENBUS_VIRQ    *Virq
     )
 {
+    PROCESSOR_NUMBER    ProcNumber;
     NTSTATUS            status;
 
     *Virq = __FdoAllocate(sizeof (XENBUS_VIRQ));
@@ -2810,12 +2812,18 @@ __FdoVirqCreate(
 
     (*Virq)->Fdo = Fdo;
     (*Virq)->Type = Type;
+
+    status = KeGetProcessorNumberFromIndex(Cpu, &ProcNumber);
+    ASSERT(NT_SUCCESS(status));
+
     (*Virq)->Channel = XENBUS_EVTCHN(Open,
                                      &Fdo->EvtchnInterface,
                                      XENBUS_EVTCHN_TYPE_VIRQ,
                                      FdoVirqCallback,
                                      *Virq,
-                                     Type);
+                                     Type,
+                                     ProcNumber.Group,
+                                     ProcNumber.Number);
 
     status = STATUS_UNSUCCESSFUL;
     if ((*Virq)->Channel == NULL)
@@ -2827,7 +2835,8 @@ __FdoVirqCreate(
                          FALSE,
                          TRUE);
 
-    Info("%s\n", VirqName((*Virq)->Type));
+    Info("%s: CPU %u:%u\n", VirqName((*Virq)->Type),
+         ProcNumber.Group, ProcNumber.Number);
 
     return STATUS_SUCCESS;
 
@@ -2874,7 +2883,7 @@ FdoVirqInitialize(
 
     InitializeListHead(&Fdo->VirqList);
 
-    status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, &Virq);
+    status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, 0, &Virq);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-- 
2.17.1




 


Rackspace

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