qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [patch] Windows host support bugfixes


From: Filip Navara
Subject: [Qemu-devel] [patch] Windows host support bugfixes
Date: Sun, 10 Apr 2005 10:59:14 +0200
User-agent: Mozilla Thunderbird 0.9 (Windows/20041103)

Hi,

the attached patch solves the memory corruption problems which caused QVM86 to crash on Windows NT host. The underlying problem was that the guest physical memory was allocated using malloc and wasn't aligned to page boundary which later caused problems when mapping the pages in the kernel module...

Regards,
Filip Navara
2004-04-10  Filip Navara  <address@hidden>

        * README: Fix typos.
        * patch.qvm86: Add patch to force page aligned allocations on WinNT
        hosts.
        * qvm86-win32.h: Ditto.
        * qvm86-win32.c (host_alloc_pages, host_free_pages): Allocate pages
        from non-cached memory instead of standard memory pool.
        (host_map_user): Guard for unaligned mappings, better error handling.
        (host_unmap_user): Fix a memory leak.

Index: README
===================================================================
RCS file: /cvsroot/qvm86/qvm86/README,v
retrieving revision 1.4
diff -u -r1.4 README
--- README      9 Apr 2005 23:32:54 -0000       1.4
+++ README      10 Apr 2005 07:40:29 -0000
@@ -27,8 +27,8 @@
 /dev/qvm86 should be created automatically when you load the module.
 
 On Windows hosts you need to copy qvm86.sys to windows/system32/drivers, apply
-avm86.reg, and do "net start qvm86".  Windows host support is extremely
-experimental.  The windows code has ben built with the mingw32 toolchains.
+qvm86.reg and do "net start qvm86".  Windows host support is extremely
+experimental.  The windows code has been built with the mingw32 toolchains.
 It is possible to compile on cygwin, but some hacking of makefiles is
 required to ensure -mno-cygwin is used.
 
Index: patch.qvm86
===================================================================
RCS file: /cvsroot/qvm86/qvm86/patch.qvm86,v
retrieving revision 1.3
diff -u -r1.3 patch.qvm86
--- patch.qvm86 9 Apr 2005 23:32:54 -0000       1.3
+++ patch.qvm86 10 Apr 2005 08:47:20 -0000
@@ -365,8 +365,27 @@
 retrieving revision 1.8
 diff -u -p -r1.8 osdep.c
 --- osdep.c    21 Feb 2005 20:10:36 -0000      1.8
-+++ osdep.c    9 Apr 2005 19:14:38 -0000
-@@ -308,7 +308,7 @@ void *qemu_malloc(size_t size)
++++ osdep.c    10 Apr 2005 08:44:29 -0000
+@@ -273,15 +273,13 @@
+ 
+ #else
+ 
+-#ifdef _BSD
++#ifdef _WIN32
++#include <windows.h>
++#elif defined(_BSD)
+ #include <stdlib.h>
+ #else
+ #include <malloc.h>
+ #endif
+-#ifdef _WIN32
+-/* XXX: find a solution to have page aligned data */
+-#define memalign(align, size) malloc(size)
+-#endif
+ 
+ int qemu_write(int fd, const void *buf, size_t n)
+ {
+@@ -308,7 +306,7 @@
      return malloc(size);
  }
  
@@ -375,6 +394,32 @@
  
  #include <sys/mman.h>
  #include <fcntl.h>
+@@ -373,7 +371,12 @@
+ /* alloc shared memory pages */
+ void *qemu_vmalloc(size_t size)
+ {
+-#ifdef _BSD
++#ifdef _WIN32
++    /* FIXME: this is not exactly optimal solution since VirtualAlloc
++       has 64Kb granularity, but at least it guarantees us that the
++       memory is page aligned. */
++    return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
++#elif defined (_BSD)
+     return valloc(size);
+ #else
+     return memalign(4096, size);
+@@ -382,7 +385,11 @@
+ 
+ void qemu_vfree(void *ptr)
+ {
++#ifdef _WIN32
++    VirtualFree(ptr, 0, MEM_RELEASE);
++#else
+     free(ptr);
++#endif
+ }
+ 
+ #endif
 Index: target-i386/helper2.c
 ===================================================================
 RCS file: /cvsroot/qemu/qemu/target-i386/helper2.c,v
Index: qvm86-win32.c
===================================================================
RCS file: /cvsroot/qvm86/qvm86/qvm86-win32.c,v
retrieving revision 1.1
diff -u -r1.1 qvm86-win32.c
--- qvm86-win32.c       9 Apr 2005 23:32:54 -0000       1.1
+++ qvm86-win32.c       10 Apr 2005 08:41:32 -0000
@@ -27,7 +27,7 @@
 {
     void * ptr;
 
-    ptr = (void *)ExAllocatePoolWithTag(NonPagedPool, size, 
TAG('Q','V','M','Z'));
+    ptr = ExAllocatePoolWithTag(NonPagedPool, size, TAG('Q','V','M','Z'));
     if (!ptr)
         return NULL;
     RtlZeroMemory(ptr, size);
@@ -39,7 +39,7 @@
 {
     char * ptr;
 
-    ptr = (void *)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * count, 
TAG('Q','V','M','P'));
+    ptr = MmAllocateNonCachedMemory(PAGE_SIZE * count);
     if (!ptr)
         return NULL;
     RtlZeroMemory(ptr, PAGE_SIZE * count);
@@ -59,7 +59,7 @@
 {
     if (!ptr)
         return;
-    ExFreePool(ptr);
+    MmFreeNonCachedMemory(ptr, PAGE_SIZE * count);
 }
 
 unsigned long
@@ -76,9 +76,21 @@
     PMDL mdl;
     PPFN_NUMBER mdl_pages;
 
+    /* fail if the user address isn't aligned */
+    if (useraddr & 0xfff)
+    {
+        DbgPrint("qvm86: Tried to map unaligned user memory (%p)\n", useraddr);
+        map->host = NULL;
+        return;
+    }
+
     mdl = ExAllocatePool(NonPagedPool, sizeof(MDL) + sizeof(PFN_NUMBER));
     if (mdl == NULL)
+    {
+        DbgPrint("qvm86: Not enough memory for MDL structure\n");
+        map->host = NULL;
         return;
+    }
     mdl_pages = (PPFN_NUMBER)(mdl + 1);
 
     MmInitializeMdl(mdl, useraddr, PAGE_SIZE);
@@ -87,6 +99,7 @@
     map->host = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
     if (map->host == NULL)
     {
+        DbgPrint("qvm86: Can't map MDL to kernel address space\n");
         ExFreePool(mdl);
         return;
     }
@@ -104,6 +117,7 @@
 
     MmUnmapLockedPages(map->host, mdl);
     MmUnlockPages(mdl);
+    ExFreePool(mdl);
 
     /* TODO: This should probably be done elsewhere.  */
     map->host = NULL;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]