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

[win-pv-devel] [PATCH 2/5] Remove use of KeNumberProcessors from SYSTEM code



The Xen SYSTEM module queries system information, including per-cpu
information. It is therefore best to make use if processor callback
functions rather than iterating over boot-time active processors, as this
makes the code robust to processors hot-added after boot.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/common/names.h |  20 +++++
 src/xen/system.c   | 252 +++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 205 insertions(+), 67 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index f4a8bd0..90636bb 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -450,6 +450,26 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+static FORCEINLINE const CHAR *
+ProcessorChangeName(
+    IN  KE_PROCESSOR_CHANGE_NOTIFY_STATE    Change
+    )
+{
+#define _PROCESSOR_CHANGE_NAME(_Change) \
+    case KeProcessor ## _Change:        \
+        return #_Change;
+
+    switch (Change) {
+    _PROCESSOR_CHANGE_NAME(AddStartNotify);
+    _PROCESSOR_CHANGE_NAME(AddCompleteNotify);
+    _PROCESSOR_CHANGE_NAME(AddFailureNotify);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
 
+#undef _PROCESSOR_CHANGE_NAME
+}
 
 #endif // _COMMON_NAMES_H_
diff --git a/src/xen/system.c b/src/xen/system.c
index 0934ac8..efe5049 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -41,23 +41,26 @@
 #include "registry.h"
 #include "system.h"
 #include "acpi.h"
+#include "names.h"
 #include "dbg_print.h"
 #include "assert.h"
 
 #define XEN_SYSTEM_TAG  'TSYS'
 
 typedef struct _SYSTEM_CPU {
-    ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
     UCHAR   ProcessorID;
+    KDPC    Dpc;
+    KEVENT  Event;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
     PACPI_MADT  Madt;
-    SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
-    PVOID       Handle;
+    PSYSTEM_CPU Cpu[MAXIMUM_PROCESSORS];
+    PVOID       PowerStateHandle;
+    PVOID       ProcessorChangeHandle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
@@ -325,32 +328,38 @@ SystemApicIDToProcessorID(
 
 #pragma warning(pop)
 
-KDEFERRED_ROUTINE   SystemCpuInformation;
-
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
 VOID
 SystemCpuInformation(
-    IN  PKDPC   Dpc,
-    IN  PVOID   Context,
-    IN  PVOID   Argument1,
-    IN  PVOID   Argument2
+    IN  PKDPC       Dpc,
+    IN  PVOID       _Context,
+    IN  PVOID       Argument1,
+    IN  PVOID       Argument2
     )
 {
-    PSYSTEM_CPU Cpu = Context;
-    PKSPIN_LOCK Lock = Argument1;
-    PKEVENT     Event = Argument2;
-    ULONG       EBX;
-    ULONG       ECX;
-    ULONG       EDX;
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Index;
+    PSYSTEM_CPU     Cpu;
+    ULONG           EBX;
+    ULONG           ECX;
+    ULONG           EDX;
 
-    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(_Context);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
 
-    ASSERT(Cpu != NULL);
-    ASSERT(Lock != NULL);
-    ASSERT(Event != NULL);
+    Index = KeGetCurrentProcessorNumber();
+    Cpu = Context->Cpu[Index];
 
-    KeAcquireSpinLockAtDpcLevel(Lock);
+    ASSERT(Cpu != NULL);
+    ASSERT3P(Dpc, ==, &Cpu->Dpc);
 
-    Info("====> (%u)\n", Cpu->Index);
+    Info("====> (%u)\n", Index);
 
     __CpuId(0, NULL, &EBX, &ECX, &EDX);
 
@@ -358,63 +367,133 @@ SystemCpuInformation(
     RtlCopyMemory(&Cpu->Manufacturer[4], &EDX, sizeof (ULONG));
     RtlCopyMemory(&Cpu->Manufacturer[8], &ECX, sizeof (ULONG));
 
-    Info("Manufacturer: %s\n", Cpu->Manufacturer);
-
     __CpuId(1, NULL, &EBX, NULL, NULL);
 
     Cpu->ApicID = EBX >> 24;
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
 
+    Info("Manufacturer: %s\n", Cpu->Manufacturer);
     Info("APIC ID: %02X\n", Cpu->ApicID);
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
-    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+    KeSetEvent(&Cpu->Event, IO_NO_INCREMENT, FALSE);
 
-    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
+    Info("<==== (%u)\n", Index);
+}
+
+static
+_Function_class_(PROCESSOR_CALLBACK_FUNCTION)
+VOID
+SystemProcessorChangeCallback(
+    IN      PVOID                               Argument,
+    IN      PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT Change,
+    IN OUT  PNTSTATUS                           Status
+    )
+{
+    PSYSTEM_CONTEXT                             Context = &SystemContext;
+    ULONG                                       Index;
+
+    UNREFERENCED_PARAMETER(Argument);
+
+    Index = Change->NtNumber;
+    Trace("====> (%u:%s)\n", Index, ProcessorChangeName(Change->State));
 
-    Info("<==== (%u)\n", Cpu->Index);
+    switch (Change->State) {
+    case KeProcessorAddStartNotify: {
+        PSYSTEM_CPU Cpu;
 
-    KeReleaseSpinLockFromDpcLevel(Lock);
-    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+        Cpu = __SystemAllocate(sizeof (SYSTEM_CPU));
+
+        if (Cpu == NULL) {
+            *Status = STATUS_NO_MEMORY;
+            break;
+        }
+
+        ASSERT3P(Context->Cpu[Index], ==, NULL);
+        Context->Cpu[Index] = Cpu;
+        break;
+    }
+    case KeProcessorAddCompleteNotify: {
+        PSYSTEM_CPU Cpu = Context->Cpu[Index];
+        PKDPC       Dpc = &Cpu->Dpc;
+        PKEVENT     Event = &Cpu->Event;
+
+        KeInitializeDpc(Dpc, SystemCpuInformation, (PVOID)(ULONG_PTR)Index);
+        KeSetImportanceDpc(Dpc, HighImportance);
+        KeSetTargetProcessorDpc(Dpc, (CCHAR)Index);
+
+        KeInitializeEvent(Event, NotificationEvent, FALSE);
+
+        KeInsertQueueDpc(Dpc, NULL, NULL);
+
+        (VOID) KeWaitForSingleObject(Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        break;
+    }
+    case KeProcessorAddFailureNotify: {
+        PSYSTEM_CPU Cpu = Context->Cpu[Index];
+
+        ASSERT(Cpu != NULL);
+
+        Context->Cpu[Index] = NULL;
+        __SystemFree(Cpu);
+
+        break;
+    }
+    }
+
+    Trace("<==== (%u:%s)\n", Index, ProcessorChangeName(Change->State));
 }
 
-static VOID
-SystemGetCpuInformation(
+static NTSTATUS
+SystemRegisterProcessorChangeCallback(
     VOID
     )
 {
-    PSYSTEM_CONTEXT     Context = &SystemContext;
-    static KSPIN_LOCK   Lock;
-    static KDPC         Dpc[MAXIMUM_PROCESSORS];
-    static KEVENT       Event[MAXIMUM_PROCESSORS];
-    PKEVENT             __Event[MAXIMUM_PROCESSORS];
-    static KWAIT_BLOCK  WaitBlock[MAXIMUM_PROCESSORS];
-    LONG                Index;
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    NTSTATUS        status;
 
-    KeInitializeSpinLock(&Lock);
+    Context->ProcessorChangeHandle = 
KeRegisterProcessorChangeCallback(SystemProcessorChangeCallback,
+                                                                       NULL,
+                                                                       
KE_PROCESSOR_CHANGE_ADD_EXISTING);
 
-    for (Index = 0; Index < KeNumberProcessors; Index++) {
-        PSYSTEM_CPU Cpu = &Context->Cpu[Index];
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->ProcessorChangeHandle == NULL)
+        goto fail1;
 
-        Cpu->Index = Index;
-        KeInitializeDpc(&Dpc[Index],
-                        SystemCpuInformation,
-                        Cpu);
-        KeSetTargetProcessorDpc(&Dpc[Index], (CCHAR)Index);
-        KeSetImportanceDpc(&Dpc[Index], HighImportance);
+    return STATUS_SUCCESS;
 
-        __Event[Index] = &Event[Index];
-        KeInitializeEvent(__Event[Index], NotificationEvent, FALSE);
+fail1:
+    Error("fail1 (%08x)\n", status);
 
-        KeInsertQueueDpc(&Dpc[Index], &Lock, __Event[Index]);
+    return status;
+}
+
+static VOID
+SystemDeregisterProcessorChangeCallback(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Index;
+
+    KeDeregisterProcessorChangeCallback(Context->ProcessorChangeHandle);
+    Context->ProcessorChangeHandle = NULL;
+
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; Index++) {
+        PSYSTEM_CPU Cpu = Context->Cpu[Index];
+
+        if (Cpu == NULL)
+            continue;
+
+        Context->Cpu[Index] = NULL;
+        __SystemFree(Cpu);
     }
 
-    (VOID) KeWaitForMultipleObjects(KeNumberProcessors,
-                                    __Event,
-                                    WaitAll,
-                                    Executive,
-                                    KernelMode,
-                                    FALSE,
-                                    NULL,
-                                    WaitBlock);
+    ASSERT(IsZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * 
MAXIMUM_PROCESSORS));
 }
 
 static NTSTATUS
@@ -545,6 +624,30 @@ SystemPowerStateCallback(
     }
 }
 
+static NTSTATUS
+SystemRegisterPowerStateCallback(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+
+    return SystemRegisterCallback(L"\\Callback\\PowerState",
+                                  SystemPowerStateCallback,
+                                  NULL,
+                                  &Context->PowerStateHandle);
+}
+
+static VOID
+SystemDeregisterPowerStateCallback(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+
+    SystemDeregisterCallback(Context->PowerStateHandle);
+    Context->PowerStateHandle = NULL;
+}
+
 NTSTATUS
 SystemInitialize(
     VOID
@@ -576,17 +679,21 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    SystemGetCpuInformation();
-
-    status = SystemRegisterCallback(L"\\Callback\\PowerState",
-                                    SystemPowerStateCallback,
-                                    NULL,
-                                    &Context->Handle);
+    status = SystemRegisterProcessorChangeCallback();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = SystemRegisterPowerStateCallback();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    SystemDeregisterProcessorChangeCallback();
+
 fail6:
     Error("fail6\n");
 
@@ -620,10 +727,22 @@ SystemVirtualCpuIndex(
     )
 {
     PSYSTEM_CONTEXT     Context = &SystemContext;
-    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
+    PSYSTEM_CPU         Cpu = Context->Cpu[Index];
+    LARGE_INTEGER       Timeout;
+    NTSTATUS            status;
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
+    Timeout.QuadPart = 0;
+
+    // Make sure the SystemCpuInformation() has run
+    status = KeWaitForSingleObject(&Cpu->Event,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   &Timeout);
+    ASSERT(NT_SUCCESS(status) && status != STATUS_TIMEOUT);
+
     return Cpu->ProcessorID;
 }
 
@@ -634,10 +753,9 @@ SystemTeardown(
 {
     PSYSTEM_CONTEXT Context = &SystemContext;
 
-    SystemDeregisterCallback(Context->Handle);
-    Context->Handle = NULL;
+    SystemDeregisterPowerStateCallback();
 
-    RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
+    SystemDeregisterProcessorChangeCallback();
 
     __SystemFree(Context->Madt);
     Context->Madt = NULL;
-- 
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®.