]> xenbits.xensource.com Git - people/pauldu/xenbus.git/commitdiff
extend evtchn api with virq cpu binding
authorPaul Durrant <pdurrant@amazon.com>
Tue, 17 Nov 2020 12:51:34 +0000 (12:51 +0000)
committerPaul Durrant <pdurrant@amazon.com>
Tue, 17 Nov 2020 19:30:57 +0000 (19:30 +0000)
Signed-off-by: Paul Durrant <pdurrant@amazon.com>
include/evtchn_interface.h
include/revision.h
include/xen.h
src/common/names.h
src/xen/event_channel.c
src/xenbus/evtchn.c
src/xenbus/fdo.c

index ade725902421af1f7f9b61f24d8b1c4a6269f235..fffde05bf1da807c36aef0bccde8c0723b798a75 100644 (file)
@@ -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
 
index 01b6737223742ed1bc484e0ce67635bf045cea3d..3a6b398e93a3f9a6e95879cd0c86859cfb8ae146 100644 (file)
@@ -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
index 171fa4ef43b9ebe8c8ae8e428995e08184517ab8..a85c07bb3e3d9daffb88dea641187bdb148cb6f7 100644 (file)
@@ -178,6 +178,7 @@ XEN_API
 NTSTATUS
 EventChannelBindVirq(
     IN  uint32_t        Virq,
+    IN  unsigned int    vcpu_id,
     OUT evtchn_port_t   *LocalPort
     );
 
@@ -208,8 +209,8 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelInitControl(
-    IN  PFN_NUMBER              Pfn,
-    IN  unsigned int            vcpu_id
+    IN  PFN_NUMBER      Pfn,
+    IN  unsigned int    vcpu_id
     );
 
 __checkReturn
@@ -223,8 +224,8 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindVirtualCpu(
-    IN  ULONG               LocalPort,
-    IN  unsigned int        vcpu_id
+    IN  evtchn_port_t   LocalPort,
+    IN  unsigned int    vcpu_id
     );
 
 __checkReturn
index 90636bb86d7427467d1c455fac1f0f54a1077178..84267d18fe5ef1e33918110773ada7fe0ea63427 100644 (file)
@@ -33,6 +33,7 @@
 #define _COMMON_NAMES_H_
 
 #include <ntddk.h>
+#include <xen.h>
 
 static FORCEINLINE const CHAR *
 PowerStateTypeName(
@@ -472,4 +473,25 @@ ProcessorChangeName(
 #undef _PROCESSOR_CHANGE_NAME
 }
 
+static FORCEINLINE const CHAR *
+VirqName(
+    IN  ULONG   Type
+    )
+{
+#define _VIRQ_NAME(_Type) \
+    case VIRQ_ ## _Type:  \
+        return #_Type;
+
+    switch (Type) {
+    _VIRQ_NAME(DEBUG);
+    _VIRQ_NAME(TIMER);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef _VIRQ_NAME
+}
+
 #endif // _COMMON_NAMES_H_
index aa9fb4859c7b37ef749b2d2470ca9ff36f8eb1ad..00d4e1ce641b4ac3b2269ff105cd48232be32256 100644 (file)
@@ -145,6 +145,7 @@ XEN_API
 NTSTATUS
 EventChannelBindVirq(
     IN  uint32_t            Virq,
+    IN  unsigned int        vcpu_id,
     OUT evtchn_port_t       *LocalPort
     )
 {
@@ -153,7 +154,7 @@ EventChannelBindVirq(
     NTSTATUS                status;
 
     op.virq = Virq;
-    op.vcpu = 0;
+    op.vcpu = vcpu_id;
 
     rc = EventChannelOp(EVTCHNOP_bind_virq, &op);
 
@@ -332,7 +333,7 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindVirtualCpu(
-    IN  ULONG               LocalPort,
+    IN  evtchn_port_t       LocalPort,
     IN  unsigned int        vcpu_id
     )
 {
index 8a819f35de2dbcffd13176c3d2d66fa29d6551c6..4d185c4c620440f7859a35dd7d06d21e36a1d2ed 100644 (file)
@@ -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:
@@ -629,7 +684,7 @@ EvtchnTrigger(
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     KIRQL                       Irql;
     PROCESSOR_NUMBER            ProcNumber;
-    ULONG                       Index;
+    ULONG                       Cpu;
     PXENBUS_EVTCHN_PROCESSOR    Processor;
     PXENBUS_INTERRUPT           Interrupt;
     BOOLEAN                     Pending;
@@ -640,10 +695,10 @@ EvtchnTrigger(
     ProcNumber = Channel->ProcNumber;
     KeReleaseSpinLock(&Channel->Lock, Irql);
 
-    Index = KeGetProcessorIndexFromNumber(&ProcNumber);
+    Cpu = KeGetProcessorIndexFromNumber(&ProcNumber);
 
-    ASSERT3U(Index, <, Context->ProcessorCount);
-    Processor = &Context->Processor[Index];
+    ASSERT3U(Cpu, <, Context->ProcessorCount);
+    Processor = &Context->Processor[Cpu];
 
     Interrupt = (Processor->UpcallEnabled) ?
                 Processor->Interrupt :
@@ -675,7 +730,7 @@ EvtchnBind(
 {
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     PROCESSOR_NUMBER            ProcNumber;
-    ULONG                       Index;
+    ULONG                       Cpu;
     PXENBUS_EVTCHN_PROCESSOR    Processor;
     ULONG                       LocalPort;
     unsigned int                vcpu_id;
@@ -688,10 +743,10 @@ EvtchnBind(
     ProcNumber.Group = Group;
     ProcNumber.Number = Number;
 
-    Index = KeGetProcessorIndexFromNumber(&ProcNumber);
+    Cpu = KeGetProcessorIndexFromNumber(&ProcNumber);
 
-    ASSERT3U(Index, <, Context->ProcessorCount);
-    Processor = &Context->Processor[Index];
+    ASSERT3U(Cpu, <, Context->ProcessorCount);
+    Processor = &Context->Processor[Cpu];
 
     status = STATUS_NOT_SUPPORTED;
     if (!Processor->UpcallEnabled)
@@ -708,7 +763,7 @@ EvtchnBind(
 
     LocalPort = Channel->LocalPort;
 
-    status = SystemVirtualCpuIndex(Index, &vcpu_id);
+    status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
     ASSERT(NT_SUCCESS(status));
 
     status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
@@ -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;
index 1ef6606f47d6179caa5c94a91409c2543c54c754..10ad424f7133ec0990a4d138331997ecdee113ef 100644 (file)
@@ -2781,6 +2781,8 @@ static FORCEINLINE NTSTATUS
 __FdoVirqCreate(
     IN  PXENBUS_FDO     Fdo,
     IN  ULONG           Type,
+    IN  USHORT          Group,
+    IN  UCHAR           Number,
     OUT PXENBUS_VIRQ    *Virq
     )
 {
@@ -2789,7 +2791,7 @@ __FdoVirqCreate(
     *Virq = __FdoAllocate(sizeof (XENBUS_VIRQ));
 
     status = STATUS_NO_MEMORY;
-    if ( Virq == NULL )
+    if (*Virq == NULL)
         goto fail1;
 
     (*Virq)->Fdo = Fdo;
@@ -2799,12 +2801,16 @@ __FdoVirqCreate(
                                      XENBUS_EVTCHN_TYPE_VIRQ,
                                      FdoVirqCallback,
                                      *Virq,
-                                     Type);
+                                     Type,
+                                     Group,
+                                     Number);
 
     status = STATUS_UNSUCCESSFUL;
     if ((*Virq)->Channel == NULL)
         goto fail2;
 
+    Info("%s: CPU %u:%u\n", VirqName(Type), Group, Number);
+
     (VOID) XENBUS_EVTCHN(Unmask,
                          &Fdo->EvtchnInterface,
                          (*Virq)->Channel,
@@ -2831,6 +2837,8 @@ __FdoVirqDestroy(
 {
     PXENBUS_FDO         Fdo = Virq->Fdo;
 
+    Info("%s\n", VirqName(Virq->Type));
+
     XENBUS_EVTCHN(Close,
                   &Fdo->EvtchnInterface,
                   Virq->Channel);
@@ -2840,15 +2848,20 @@ __FdoVirqDestroy(
 
 static NTSTATUS
 FdoVirqInitialize(
-    IN  PXENBUS_FDO         Fdo
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PXENBUS_VIRQ            Virq;
-    NTSTATUS                status;
+    PROCESSOR_NUMBER    ProcNumber;
+    PXENBUS_VIRQ        Virq;
+    NTSTATUS            status;
 
     InitializeListHead(&Fdo->VirqList);
 
-    status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, &Virq);
+    status = KeGetProcessorNumberFromIndex(0, &ProcNumber);
+    ASSERT(NT_SUCCESS(status));
+
+    status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, ProcNumber.Group,
+                             ProcNumber.Number, &Virq);
     if (!NT_SUCCESS(status))
         goto fail1;