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

[PATCH xenbus 3/7] Generalize per-processor DPC in SYSTEM



From: Paul Durrant <pdurrant@xxxxxxxxxx>

The DPC is currently used only for acquiring and display per-processor
information but a subsequent patch will also use the DPC for another purpose.
Hence this patch creates a general SystemProcessorDpc() call-back that then
calls a slightly modified SystemProcessorInformation() (which is renamed
SystemProcessorInitialize()) to fulfil the original purpose.

This patch also adds a mechanism for the per-processor DPCs to pass back
a status code to the main initialization code such that it can be aborted if
any of them fail. A new SystemProcessorTeardown() function is added to do
cleanup, and hence we can verify the SYSTEM_PROCESSOR structures are zeroed
in SystemDeregisterProcessorChangeCallback().

Currently no failure is possible during SystemProcessorDpc() but this will
change with the addition of a subsequent patch.

NOTE: __SystemProcessorCount() is relocated earlier in system.c as it now
      needs to be called by SystemDeregisterProcessorChangeCallback(). It
      is relocated earlier than strictly necessary for this, but
      subsequent patches will do further function relocation and add additonal
      funcrtions that also rely on __SystemProcessorCount() being in its new
      position.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xen/system.c | 179 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 133 insertions(+), 46 deletions(-)

diff --git a/src/xen/system.c b/src/xen/system.c
index 8219c86f8321..7bd7cb381f38 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -49,10 +49,12 @@
 #define XEN_SYSTEM_TAG  'TSYS'
 
 typedef struct _SYSTEM_PROCESSOR {
-    KDPC    Dpc;
-    CHAR    Manufacturer[13];
-    UCHAR   ApicID;
-    UCHAR   ProcessorID;
+    KDPC        Dpc;
+    CHAR        Manufacturer[13];
+    UCHAR       ApicID;
+    UCHAR       ProcessorID;
+    NTSTATUS    Status;
+    KEVENT      Event;
 } SYSTEM_PROCESSOR, *PSYSTEM_PROCESSOR;
 
 typedef struct _SYSTEM_WATCHDOG {
@@ -562,37 +564,18 @@ done:
     Info("<====\n");
 }
 
-static
-_Function_class_(KDEFERRED_ROUTINE)
-_IRQL_requires_max_(DISPATCH_LEVEL)
-_IRQL_requires_min_(DISPATCH_LEVEL)
-_IRQL_requires_(DISPATCH_LEVEL)
-_IRQL_requires_same_
-VOID
-SystemProcessorInformation(
-    IN  PKDPC           Dpc,
-    IN  PVOID           _Context,
-    IN  PVOID           Argument1,
-    IN  PVOID           Argument2
+static VOID
+SystemProcessorInitialize(
+    IN  ULONG           Cpu
     )
 {
     PSYSTEM_CONTEXT     Context = &SystemContext;
-    PKEVENT             Event = Argument1;
-    ULONG               Cpu;
-    PROCESSOR_NUMBER    ProcNumber;
     PSYSTEM_PROCESSOR   Processor;
     ULONG               EAX;
     ULONG               EBX;
     ULONG               ECX;
     ULONG               EDX;
 
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(_Context);
-    UNREFERENCED_PARAMETER(Argument2);
-
-    Cpu = KeGetCurrentProcessorNumberEx(&ProcNumber);
-    ASSERT3U(Cpu, <, Context->ProcessorCount);
-
     Processor = &Context->Processor[Cpu];
 
     if (Cpu == 0) {
@@ -609,8 +592,6 @@ SystemProcessorInformation(
             SystemViridianInformation(EAX - 0x40000000);
     }
 
-    Info("====> (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
-
     __CpuId(0, NULL, &EBX, &ECX, &EDX);
 
     RtlCopyMemory(&Processor->Manufacturer[0], &EBX, sizeof (ULONG));
@@ -625,10 +606,73 @@ SystemProcessorInformation(
     Info("Manufacturer: %s\n", Processor->Manufacturer);
     Info("APIC ID: %02X\n", Processor->ApicID);
     Info("PROCESSOR ID: %02X\n", Processor->ProcessorID);
+}
+
+static VOID
+SystemProcessorTeardown(
+    IN  ULONG           Cpu
+    )
+{
+    PSYSTEM_CONTEXT     Context = &SystemContext;
+    PSYSTEM_PROCESSOR   Processor;
 
-    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+    Processor = &Context->Processor[Cpu];
+
+    Processor->ProcessorID = 0;
+    Processor->ApicID = 0;
+    RtlZeroMemory(Processor->Manufacturer, sizeof (Processor->Manufacturer));
+}
+
+static FORCEINLINE ULONG
+__SystemProcessorCount(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT     Context = &SystemContext;
+
+    KeMemoryBarrier();
+
+    return Context->ProcessorCount;
+}
+
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
+VOID
+SystemProcessorDpc(
+    IN  PKDPC           Dpc,
+    IN  PVOID           _Context,
+    IN  PVOID           Argument1,
+    IN  PVOID           Argument2
+    )
+{
+    PSYSTEM_CONTEXT     Context = &SystemContext;
+    ULONG               Cpu;
+    PROCESSOR_NUMBER    ProcNumber;
+    PSYSTEM_PROCESSOR   Processor;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(_Context);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    Cpu = KeGetCurrentProcessorNumberEx(&ProcNumber);
+    ASSERT3U(Cpu, <, Context->ProcessorCount);
+
+    Processor = &Context->Processor[Cpu];
+    Processor->Status = STATUS_UNSUCCESSFUL;
+
+    Info("====> (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
+
+    SystemProcessorInitialize(Cpu);
 
     Info("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
+
+    Processor->Status = STATUS_SUCCESS;
+    KeSetEvent(&Processor->Event, IO_NO_INCREMENT, FALSE);
 }
 
 static
@@ -690,21 +734,24 @@ SystemProcessorChangeCallback(
     }
     case KeProcessorAddCompleteNotify: {
         PSYSTEM_PROCESSOR   Processor;
-        KEVENT              Event;
 
         ASSERT3U(Cpu, <, Context->ProcessorCount);
 
         Processor = &Context->Processor[Cpu];
 
-        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+        KeInitializeEvent(&Processor->Event, NotificationEvent, FALSE);
 
-        KeInitializeDpc(&Processor->Dpc, SystemProcessorInformation, NULL);
+        KeInitializeDpc(&Processor->Dpc, SystemProcessorDpc, NULL);
         KeSetImportanceDpc(&Processor->Dpc, HighImportance);
         KeSetTargetProcessorDpcEx(&Processor->Dpc, &ProcNumber);
 
-        KeInsertQueueDpc(&Processor->Dpc, &Event, NULL);
+        KeInsertQueueDpc(&Processor->Dpc, NULL, NULL);
 
-        (VOID) KeWaitForSingleObject(&Event,
+        //
+        // Wait for the DPC to avoid log lines from multiple processor
+        // initializations from being interleaved.
+        //
+        (VOID) KeWaitForSingleObject(&Processor->Event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
@@ -758,10 +805,23 @@ SystemDeregisterProcessorChangeCallback(
     )
 {
     PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Cpu;
 
     KeDeregisterProcessorChangeCallback(Context->ProcessorChangeHandle);
     Context->ProcessorChangeHandle = NULL;
 
+    for (Cpu = 0; Cpu < __SystemProcessorCount(); Cpu++) {
+        PSYSTEM_PROCESSOR   Processor = &Context->Processor[Cpu];
+
+        SystemProcessorTeardown(Cpu);
+
+        RtlZeroMemory(&Processor->Dpc, sizeof (KDPC));
+        RtlZeroMemory(&Processor->Event, sizeof (KEVENT));
+        Processor->Status = 0;
+
+        ASSERT(IsZeroMemory(Processor, sizeof (SYSTEM_PROCESSOR)));
+    }
+
     __SystemFree(Context->Processor);
     Context->Processor = NULL;
     Context->ProcessorCount = 0;
@@ -964,6 +1024,38 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemCheckProcessors(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Cpu;
+    NTSTATUS        status;
+
+    for (Cpu = 0; Cpu < __SystemProcessorCount(); Cpu++)
+    {
+        PSYSTEM_PROCESSOR   Processor = &Context->Processor[Cpu];
+
+        (VOID) KeWaitForSingleObject(&Processor->Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+
+        status = Processor->Status;
+        if (!NT_SUCCESS(status))
+            goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 NTSTATUS
 SystemInitialize(
     VOID
@@ -1007,8 +1099,15 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    status = SystemCheckProcessors();
+    if (!NT_SUCCESS(status))
+        goto fail9;
+
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
 fail8:
     Error("fail8\n");
 
@@ -1045,18 +1144,6 @@ fail1:
     return status;
 }
 
-static FORCEINLINE ULONG
-__SystemProcessorCount(
-    VOID
-    )
-{
-    PSYSTEM_CONTEXT     Context = &SystemContext;
-
-    KeMemoryBarrier();
-
-    return Context->ProcessorCount;
-}
-
 XEN_API
 ULONG
 SystemProcessorCount(
-- 
2.17.1




 


Rackspace

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