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

[PATCH xenbus 4/7] Introduce DriverGet/PutNamedPages()



From: Paul Durrant <pdurrant@xxxxxxxxxx>

A subsequent patch will need a mechanism to allocate memory that persists
for the lifetime of the VM. Because it is possible for the XEN.SYS module
can be unloaded, references to the PFNs of the allocated buffer are stored
under a volatile registry key such that they can be re-discovered if XEN.SYS
is re-loaded.

DriverGetNamedPages() will either allocate or discover PFNs and wrap them in
an MDL which is then mapped and passed back to the caller.
DriverPutNamedPages() will unmap the PFNs but not free them (since they
will have been written into the registry by DriverGetNamedPages()).

NOTE: There is also a whitespace fix in the call to RegistryCreateSubKey()
      for the 'ParametersKey' in driver.c.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xen/driver.c | 355 ++++++++++++++++++++++++++++++++++++++++++++---
 src/xen/driver.h |  11 ++
 2 files changed, 349 insertions(+), 17 deletions(-)

diff --git a/src/xen/driver.c b/src/xen/driver.c
index 9e4a18ef7dfd..4670539b488a 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -33,6 +33,7 @@
 
 #include <ntddk.h>
 #include <procgrp.h>
+#include <ntstrsafe.h>
 #include <xen.h>
 
 #include "registry.h"
@@ -47,6 +48,7 @@
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
+#include "util.h"
 #include "version.h"
 
 #define DEFAULT_XEN_LOG_LEVEL   LOG_LEVEL_CRITICAL
@@ -59,12 +61,31 @@ typedef struct _XEN_DRIVER {
     PLOG_DISPOSITION    XenDisposition;
     PLOG_DISPOSITION    QemuDisposition;
     HANDLE              UnplugKey;
+    HANDLE              MemoryKey;
 } XEN_DRIVER, *PXEN_DRIVER;
 
 static XEN_DRIVER   Driver;
 
+#define XEN_DRIVER_TAG  'VIRD'
+
 extern PULONG   InitSafeBootMode;
 
+static FORCEINLINE PVOID
+__DriverAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_DRIVER_TAG);
+}
+
+static FORCEINLINE VOID
+__DriverFree(
+    IN  PVOID   Buffer
+    )
+{
+    __FreePoolWithTag(Buffer, XEN_DRIVER_TAG);
+}
+
 static FORCEINLINE BOOLEAN
 __DriverSafeMode(
     VOID
@@ -97,6 +118,284 @@ DriverGetUnplugKey(
     return __DriverGetUnplugKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetMemoryKey(
+    IN  HANDLE  Key
+    )
+{
+    Driver.MemoryKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetMemoryKey(
+    VOID
+    )
+{
+    return Driver.MemoryKey;
+}
+
+#define MAXNAMELEN 128
+
+static FORCEINLINE NTSTATUS
+__DriverSetPfnArray(
+    IN  PCHAR       Name,
+    IN  ULONG       Count,
+    IN  PFN_NUMBER  PfnArray[]
+    )
+{
+    HANDLE          Key = __DriverGetMemoryKey();
+    LONG            Index;
+    NTSTATUS        status;
+
+    Index = 0;
+    while (Index < (LONG)Count) {
+        CHAR    ValueName[MAXNAMELEN];
+        PVOID   Value;
+        ULONG   Length;
+
+        status = RtlStringCbPrintfA(ValueName,
+                                    MAXNAMELEN,
+                                    "%s_%u",
+                                    Name,
+                                    Index);
+        ASSERT(NT_SUCCESS(status));
+
+        Value = &PfnArray[Index];
+        Length = sizeof (PFN_NUMBER);
+
+        status = RegistryUpdateBinaryValue(Key,
+                                           ValueName,
+                                           Value,
+                                           Length);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        Info("%s %p\n", ValueName, (PVOID)PfnArray[Index]);
+
+        Index++;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (--Index >= 0) {
+        CHAR    ValueName[MAXNAMELEN];
+
+        status = RtlStringCbPrintfA(ValueName,
+                                    MAXNAMELEN,
+                                    "%s_%u",
+                                    Name,
+                                    Index);
+        ASSERT(NT_SUCCESS(status));
+
+        (VOID) RegistryDeleteValue(Key, ValueName);
+    }
+
+    return status;
+}
+
+static FORCEINLINE NTSTATUS
+__DriverAllocatePfnArray(
+    IN  PCHAR           Name,
+    IN  ULONG           Count,
+    OUT PFN_NUMBER      PfnArray[]
+    )
+{
+    PHYSICAL_ADDRESS    LowAddress;
+    PHYSICAL_ADDRESS    HighAddress;
+    LARGE_INTEGER       SkipBytes;
+    SIZE_T              TotalBytes;
+    PMDL                Mdl;
+    NTSTATUS            status;
+
+    LowAddress.QuadPart = 0ull;
+    HighAddress.QuadPart = ~0ull;
+    SkipBytes.QuadPart = 0ull;
+    TotalBytes = PAGE_SIZE * Count;
+
+    Mdl = MmAllocatePagesForMdlEx(LowAddress,
+                                  HighAddress,
+                                  SkipBytes,
+                                  TotalBytes,
+                                  MmCached,
+                                  MM_ALLOCATE_FULLY_REQUIRED);
+
+    status = STATUS_NO_MEMORY;
+    if (Mdl == NULL)
+        goto fail1;
+
+    if (Mdl->ByteCount < TotalBytes)
+        goto fail2;
+
+    ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
+                             MDL_PARTIAL_HAS_BEEN_MAPPED |
+                             MDL_PARTIAL |
+                             MDL_PARENT_MAPPED_SYSTEM_VA |
+                             MDL_SOURCE_IS_NONPAGED_POOL |
+                             MDL_IO_SPACE)) == 0);
+
+    status = __DriverSetPfnArray(Name, Count, MmGetMdlPfnArray(Mdl));
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    RtlCopyMemory(PfnArray, MmGetMdlPfnArray(Mdl), sizeof (PFN_NUMBER) * 
Count);
+
+    ExFreePool(Mdl);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmFreePagesFromMdl(Mdl);
+    ExFreePool(Mdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static FORCEINLINE NTSTATUS
+__DriverGetPfnArray(
+    IN  PCHAR       Name,
+    IN  ULONG       Count,
+    OUT PFN_NUMBER  PfnArray[]
+    )
+{
+    HANDLE          Key = __DriverGetMemoryKey();
+    ULONG           Index;
+    NTSTATUS        status;
+
+    for (Index = 0; Index < Count; Index++) {
+        CHAR    ValueName[MAXNAMELEN];
+        PVOID   Value;
+        ULONG   Length;
+
+        status = RtlStringCbPrintfA(ValueName,
+                                    MAXNAMELEN,
+                                    "%s_%u",
+                                    Name,
+                                    Index);
+        ASSERT(NT_SUCCESS(status));
+
+        status = RegistryQueryBinaryValue(Key,
+                                          ValueName,
+                                          &Value,
+                                          &Length);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Length != sizeof (PFN_NUMBER))
+            goto fail2;
+
+        PfnArray[Index] = *(PPFN_NUMBER)Value;
+
+        RegistryFreeBinaryValue(Value);
+
+        Info("%s %p\n", Name, (PVOID)PfnArray[Index]);
+    }
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+PMDL
+DriverGetNamedPages(
+    IN  PCHAR   Name,
+    IN  ULONG   Count
+    )
+{
+    ULONG       Size;
+    PMDL        Mdl;
+    PUCHAR      MdlMappedSystemVa;
+    NTSTATUS    status;
+
+    Size = sizeof (MDL) + (sizeof (PFN_NUMBER) * Count);
+    Mdl = __DriverAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Mdl == NULL)
+        goto fail1;
+
+#pragma warning(push)
+#pragma warning(disable:28145) // modifying struct MDL
+
+    Mdl->Size = (USHORT)Size;
+    Mdl->MdlFlags = MDL_PAGES_LOCKED;
+    Mdl->ByteCount = PAGE_SIZE * Count;
+
+#pragma warning(pop)
+
+    status = __DriverGetPfnArray(Name, Count, MmGetMdlPfnArray(Mdl));
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+            status = __DriverAllocatePfnArray(Name, Count,
+                                              MmGetMdlPfnArray(Mdl));
+
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
+
+    MdlMappedSystemVa = MmMapLockedPagesSpecifyCache(Mdl,
+                                                     KernelMode,
+                                                     MmCached,
+                                                     NULL,
+                                                     FALSE,
+                                                     NormalPagePriority);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (MdlMappedSystemVa == NULL)
+        goto fail3;
+
+    Mdl->StartVa = PAGE_ALIGN(MdlMappedSystemVa);
+
+    return Mdl;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    __DriverFree(Mdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return NULL;
+}
+
+VOID
+DriverPutNamedPages(
+    IN  PMDL    Mdl
+    )
+{
+    PUCHAR         MdlMappedSystemVa;
+
+    ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
+    MdlMappedSystemVa = Mdl->MappedSystemVa;
+
+    MmUnmapLockedPages(MdlMappedSystemVa, Mdl);
+
+    // DO NOT FREE PAGES
+
+    __DriverFree(Mdl);
+}
+
 XEN_API
 NTSTATUS
 XenTouch(
@@ -173,8 +472,9 @@ DllInitialize(
     )
 {
     HANDLE              ServiceKey;
-    HANDLE              UnplugKey;
     HANDLE              ParametersKey;
+    HANDLE              UnplugKey;
+    HANDLE              MemoryKey;
     LOG_LEVEL           LogLevel;
     NTSTATUS            status;
 
@@ -198,9 +498,9 @@ DllInitialize(
         goto fail3;
 
     status = RegistryCreateSubKey(ServiceKey,
-                                "Parameters",
-                                REG_OPTION_NON_VOLATILE,
-                                &ParametersKey);
+                                  "Parameters",
+                                  REG_OPTION_NON_VOLATILE,
+                                  &ParametersKey);
     if (!NT_SUCCESS(status))
         goto fail4;
 
@@ -249,31 +549,40 @@ DllInitialize(
 
     __DriverSetUnplugKey(UnplugKey);
 
+    status = RegistryCreateSubKey(ServiceKey,
+                                  "Memory",
+                                  REG_OPTION_VOLATILE,
+                                  &MemoryKey);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
+    __DriverSetMemoryKey(MemoryKey);
+
     HypercallInitialize();
 
     status = AcpiInitialize();
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     status = SystemInitialize();
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail8;
 
     status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = ModuleInitialize();
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail10;
 
     status = ProcessInitialize();
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail11;
 
     status = UnplugInitialize();
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail12;
 
     RegistryCloseKey(ParametersKey);
 
@@ -283,36 +592,42 @@ DllInitialize(
 
     return STATUS_SUCCESS;
 
+fail12:
+    Error("fail12\n");
+
+    ProcessTeardown();
+
 fail11:
     Error("fail11\n");
 
-    ProcessTeardown();
+    ModuleTeardown();
 
 fail10:
     Error("fail10\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail9:
     Error("fail9\n");
 
-    BugCheckTeardown();
+    SystemTeardown();
 
 fail8:
     Error("fail8\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail7:
     Error("fail7\n");
 
-    AcpiTeardown();
+    HypercallTeardown();
+
+    RegistryCloseKey(MemoryKey);
+    __DriverSetMemoryKey(NULL);
 
 fail6:
     Error("fail6\n");
 
-    HypercallTeardown();
-
     RegistryCloseKey(UnplugKey);
     __DriverSetUnplugKey(NULL);
 
@@ -355,6 +670,7 @@ DllUnload(
     VOID
     )
 {
+    HANDLE  MemoryKey;
     HANDLE  UnplugKey;
 
     Trace("====>\n");
@@ -373,6 +689,11 @@ DllUnload(
 
     HypercallTeardown();
 
+    MemoryKey = __DriverGetMemoryKey();
+
+    RegistryCloseKey(MemoryKey);
+    __DriverSetMemoryKey(NULL);
+
     UnplugKey = __DriverGetUnplugKey();
 
     RegistryCloseKey(UnplugKey);
diff --git a/src/xen/driver.h b/src/xen/driver.h
index c4f7a6fb6f6d..8c39735147c6 100644
--- a/src/xen/driver.h
+++ b/src/xen/driver.h
@@ -37,4 +37,15 @@ DriverGetUnplugKey(
     VOID
     );
 
+extern PMDL
+DriverGetNamedPages(
+    IN  PCHAR   Name,
+    IN  ULONG   Count
+    );
+
+extern VOID
+DriverPutNamedPages(
+    IN  PMDL    Mdl
+    );
+
 #endif  // _XEN_DRIVER_H
-- 
2.17.1




 


Rackspace

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