[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |