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

[PATCH] Windows PV drivers fail to set up RSS when vCPUs > 8


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Date: Mon, 14 Mar 2022 15:27:46 +0000
  • Authentication-results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Delivery-date: Mon, 14 Mar 2022 15:28:27 +0000
  • Ironport-data: A9a23:fF/5aa1Uh+ueKgBrovbD5YFxkn2cJEfYwER7XKvMYLTBsI5bpzEAm 2AaC2nSaPeDNDD3KN4jbtm+px9SuJfdmoVhTwI/pC1hF35El5HIVI+TRqvS04J+DSFhoGZPt Zh2hgzodZhsJpPkjk7xdOCn9xGQ7InQLlbGILes1htZGEk1EE/NtTo5w7Rj2tUx3YDja++wk YiaT/P3aQfNNwFcagr424rbwP+4lK2v0N+wlgVWicFj5DcypVFMZH4sDfjZw0/DaptVBoaHq 9Prl9lVyI97EyAFUbtJmp6jGqEDryW70QKm0hK6UID66vROS7BbPg/W+5PwZG8O4whlkeydx /1/8pyPZkRuIpfWldU6YxRYPwUlZ7Z/reqvzXiX6aR/zmXDenrohf5vEFs3LcsT/eMf7WNmr KJCbmpXN1ba2rzwkOnTpupE36zPKOHuNZkDu3cmzTjDE/s3aZvCX7/L9ZlT2zJYasVmQ6iHP pFCNGcHgBLoQTlSEVMUFZkCuMCSn0jDTBdJlXXPqv9ii4TU5FMoi+W8WDbPQfSVRMMQhljdq m/Y8mDRBhABKMfZ2TeD6mirhOLEgWX8Qo16KVGj3qc02hvJnDVVUUBIEwvgyRWktqKgc+AYK 3M7uW0yl7I/xWubQ9nRe0biu0fR63bwROFsO+E97QiMzI/d7ACYGnUIQ1Z9VTA2iCMlbWd0j wHUxrsFERQq6eTIEizFqt94uBvoYUAowXk+iTjopOfvy/3qu8kNgx3GVb6P+4bl34SuSVkcL 91nxRXSZon/b+ZWjc1XHnid2lpAQ6QlqSZvum3qspqNtF8RWWJcT9XABaLnxfhBNp2FaVKKo WIJncOThMhXU83SzX3SGr1SQ+jxjxpgDNE7qQQzd6TNChz3oyLzFWyuyGwWyLhV3jYsJmayP R67VfJ5755PJnq6BZKbkKrqY/nGOZPITIy/PtiNN4ImSsEoKGevoXE/DWbNjjuFuBV9zskC1 WKzLJ/E4YAyUv88klJbho41jNcW+8zJ7TiKFM6hkEj/j+b2ibz8Ye5tDWZip9sRtMusyDg5O f4FXydW432ziNHDXxQ=
  • Ironport-hdrordr: A9a23:q2NNc6/Bmaoi3b2doxNuk+DWI+orL9Y04lQ7vn2YSXRuE/Bw8P re+8jztCWE8Qr5N0tQ+uxoVJPufZq+z+8Q3WByB8bBYOCOggLBR+sOgbcKqweQfREWndQ86U 4PScZD4aXLfD1Hsfo=
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

Signed-off-by: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
---
 src/xenvif/receiver.c | 168 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 148 insertions(+), 20 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 10ac6f5..0c7b32a 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -106,6 +106,7 @@ typedef struct _XENVIF_RECEIVER_RING {
     PLIST_ENTRY                 PacketQueue;
     KDPC                        QueueDpc;
     ULONG                       QueueDpcs;
+    PROCESSOR_NUMBER            TargetProcessor;
     LIST_ENTRY                  PacketComplete;
     XENVIF_RECEIVER_HASH        Hash;
 } XENVIF_RECEIVER_RING, *PXENVIF_RECEIVER_RING;
@@ -2498,6 +2499,9 @@ __ReceiverRingInitialize(
 
     KeInitializeThreadedDpc(&(*Ring)->QueueDpc, ReceiverRingQueueDpc, *Ring);
 
+    status = KeGetProcessorNumberFromIndex((*Ring)->Index, 
&(*Ring)->TargetProcessor);
+    ASSERT(NT_SUCCESS(status));
+
     return STATUS_SUCCESS;
 
 fail7:
@@ -2550,6 +2554,45 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+__ReceiverRingSetAffinity(
+    IN  PXENVIF_RECEIVER_RING   Ring,
+    IN  PPROCESSOR_NUMBER       Processor
+    )
+{
+    PXENVIF_RECEIVER            Receiver;
+    PXENVIF_FRONTEND            Frontend;
+    NTSTATUS status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if ((Ring == NULL) || (Processor == NULL))
+        goto fail1;
+
+    Receiver = Ring->Receiver;
+    Frontend = Receiver->Frontend;
+
+    /* Always update ring target processor
+       Actually set affinities if frontend override not present.
+       Re-bind event-channel if already connected */
+
+    __ReceiverRingAcquireLock(Ring);
+
+    Ring->TargetProcessor = *Processor;
+
+    /* Don't rebind event channel at this point. */
+    KeSetTargetProcessorDpcEx(&Ring->PollDpc, &Ring->TargetProcessor);
+    KeSetTargetProcessorDpcEx(&Ring->QueueDpc, &Ring->TargetProcessor);
+
+    __ReceiverRingReleaseLock(Ring);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static FORCEINLINE NTSTATUS
 __ReceiverRingConnect(
     IN  PXENVIF_RECEIVER_RING   Ring
@@ -2560,7 +2603,6 @@ __ReceiverRingConnect(
     PFN_NUMBER                  Pfn;
     CHAR                        Name[MAXNAMELEN];
     ULONG                       Index;
-    PROCESSOR_NUMBER            ProcNumber;
     NTSTATUS                    status;
 
     Receiver = Ring->Receiver;
@@ -2637,16 +2679,17 @@ __ReceiverRingConnect(
     if (Ring->Channel == NULL)
         goto fail6;
 
-    status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
-    ASSERT(NT_SUCCESS(status));
+    status = XENBUS_EVTCHN(Bind,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            Ring->TargetProcessor.Group,
+                            Ring->TargetProcessor.Number);
+    if (!NT_SUCCESS(status))
+        Warning("Cound not set initial receiver ring affinity: 0x%x\n", 
status);
+    /* You haven't specifically asked for an affinity yet, so just warn. */
 
-    KeSetTargetProcessorDpcEx(&Ring->PollDpc, &ProcNumber);
-
-    (VOID) XENBUS_EVTCHN(Bind,
-                         &Receiver->EvtchnInterface,
-                         Ring->Channel,
-                         ProcNumber.Group,
-                         ProcNumber.Number);
+    KeSetTargetProcessorDpcEx(&Ring->PollDpc, &Ring->TargetProcessor);
+    KeSetTargetProcessorDpcEx(&Ring->QueueDpc, &Ring->TargetProcessor);
 
     (VOID) XENBUS_EVTCHN(Unmask,
                          &Receiver->EvtchnInterface,
@@ -2665,11 +2708,6 @@ __ReceiverRingConnect(
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = KeGetProcessorNumberFromIndex(Ring->Index, &ProcNumber);
-    ASSERT(NT_SUCCESS(status));
-
-    KeSetTargetProcessorDpcEx(&Ring->QueueDpc, &ProcNumber);
-
     return STATUS_SUCCESS;
 
 fail7:
@@ -3917,6 +3955,56 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+__ReceiverSetQueueAffinities(
+    IN  PXENVIF_RECEIVER        Receiver,
+    IN  PPROCESSOR_NUMBER       QueueAffinities,
+    IN  ULONG                   Count
+    )
+{
+    PXENVIF_FRONTEND        Frontend;
+    ULONG                   Index;
+    NTSTATUS                status;
+    KIRQL                   Irql;
+
+    Frontend = Receiver->Frontend;
+
+    status = STATUS_INVALID_PARAMETER;
+
+    if (QueueAffinities == NULL)
+        goto fail1;
+
+    if (Count > FrontendGetNumQueues(Frontend))
+        goto fail2;
+
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+
+    for (Index = 0; Index < Count; Index++) {
+        PXENVIF_RECEIVER_RING   Ring = Receiver->Ring[Index];
+
+        status = __ReceiverRingSetAffinity(Ring, &QueueAffinities[Index]);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+    }
+
+    KeLowerIrql(Irql);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    KeLowerIrql(Irql);
+
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 NTSTATUS
 ReceiverUpdateHashMapping(
     IN  PXENVIF_RECEIVER    Receiver,
@@ -3926,10 +4014,15 @@ ReceiverUpdateHashMapping(
 {
     PXENVIF_FRONTEND        Frontend;
     PULONG                  QueueMapping;
+    PPROCESSOR_NUMBER       QueueAffinities;
     ULONG                   NumQueues;
+    ULONG                   QueuesDetermined;
+    ULONG                   QIndex;
     ULONG                   Index;
+    BOOLEAN                 MapEntryDone;
     NTSTATUS                status;
 
+
     Frontend = Receiver->Frontend;
 
     QueueMapping = __ReceiverAllocate(sizeof (ULONG) * Size);
@@ -3939,26 +4032,61 @@ ReceiverUpdateHashMapping(
         goto fail1;
 
     NumQueues = FrontendGetNumQueues(Frontend);
+    QueuesDetermined = 0;
+
+    QueueAffinities = __ReceiverAllocate(sizeof(PROCESSOR_NUMBER) * NumQueues);
+    if (QueueAffinities == NULL)
+        goto fail2;
 
     status = STATUS_INVALID_PARAMETER;
+    /* N^Squared-ish, but performed infrequently */
     for (Index = 0; Index < Size; Index++) {
-        QueueMapping[Index] = 
KeGetProcessorIndexFromNumber(&ProcessorMapping[Index]);
-
-        if (QueueMapping[Index] >= NumQueues)
-            goto fail2;
+        MapEntryDone = FALSE;
+        /* Existing queue meets affinity requirement for the mapping at this 
index? */
+        for (QIndex = 0; QIndex < QueuesDetermined; QIndex++) {
+            if ((QueueAffinities[QIndex].Group == 
ProcessorMapping[Index].Group) &&
+                (QueueAffinities[QIndex].Number == 
ProcessorMapping[Index].Number)) {
+                QueueMapping[Index] = QIndex;
+                MapEntryDone = TRUE;
+            }
+        }
+        if (!MapEntryDone) {
+            /* New queue "allocation", with new affinity, if possible */
+            if (QueuesDetermined < NumQueues) {
+                QIndex = QueuesDetermined;
+                QueueAffinities[QIndex] = ProcessorMapping[Index];
+                QueueMapping[Index] = QIndex;
+                QueuesDetermined ++;
+            } else {
+                goto fail3;
+            }
+        }
     }
 
     status = FrontendSetHashMapping(Frontend, QueueMapping, Size);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
+
+    status = __ReceiverSetQueueAffinities(Receiver, QueueAffinities, 
QueuesDetermined);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
     __ReceiverFree(QueueMapping);
+    __ReceiverFree(QueueAffinities);
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
 
+    __ReceiverFree(QueueAffinities);
+
 fail2:
     Error("fail2\n");
 
-- 
2.25.0.windows.1




 


Rackspace

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