Hello,

this patch adds a few (not so) paranoid checks:  most importantly, it makes
sure that the guest physical memory is actually unmapped from user space
before it is freed.  (This was probably the source for sporadic crashes
I was experiencing ...)   

Also, as the use of the PG_reserved bit appears to be OK (the 'bttv' driver
and other drivers in 2.3.x do it as well), I've replaced the HACK warning
by a comment explaining what it is supposed to do ...

Bye,
Ulrich

ChangeLog entry:

        [host-linux.c] [host-linux.h]
        Added check to prevent the guest physical memory from being 
        freed while still mapped to user space.
        Added check to prevent duplicate allocation (memory leak!).
        Use 'mem_map_(un)reserve' macros instead of manipulating page 
        flags directly.

        [user.c]
        Unmap guest physical memory before freeing it.

Patch:

diff -ur fmw-19990825a/kernel/host-linux.c fmw-uw/kernel/host-linux.c
--- fmw-19990825a/kernel/host-linux.c   Wed Aug 25 20:54:46 1999
+++ fmw-uw/kernel/host-linux.c  Fri Aug 27 00:28:08 1999
@@ -210,6 +210,7 @@
 
     // free the virtual memory
     unalloc_vm_pages();
+    mon_ok = 0;
 
 #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,31)
     return(0);
@@ -258,6 +259,12 @@
         case FMWALLOCVPHYS:
             printk(KERN_WARNING "freemware: allocating %luM of memory\n", arg);
 
+            // Don't allow duplicate allocation
+            if (mon_ok) {
+                printk(KERN_WARNING "freemware: device already in use\n", arg);
+                return (-EBUSY);
+            }
+
             // Check that the amount of memory we allocate is reasonable
             if (arg > FMW_MAX_PHY_MEGS) {
                 printk(KERN_WARNING "freemware: request of too much phymem 
(%luMegs)\n", arg);
@@ -372,6 +379,13 @@
           break;
 
       case FMWTEARDOWN: // tear down VM environment
+
+          // Do *not* free pages that are still mapped to user space!
+          if (inode->i_mmap != NULL) {
+              printk(KERN_WARNING "freemware: guest memory is still mapped!\n");
+              return -EBUSY;
+          }
+
           unalloc_vm_pages();
           mon_ok = 0;
           return(0);
@@ -393,6 +407,12 @@
 {
     int i, firstpage, nr_pages;
 
+    /* Must have memory allocated */
+    if (!mon_ok) {
+        printk(KERN_WARNING "freemware: device not initialized\n");
+        return -EACCES;
+    }
+
     /* Private mappings make no sense ... */
     if ( !(vma->vm_flags & VM_SHARED) ) {
         printk(KERN_WARNING "freemware: private mapping\n");
@@ -523,7 +543,10 @@
     // give back pages which were allocated for the VM environment
     for (p=0; p<vm_pages.guest_n_pages; p++) {
         if (vm_pages.guest[p]) {
-            clear_bit(PG_reserved, &mem_map[MAP_NR(vm_pages.guest[p])].flags);   /* 
HACK!!! */
+
+            /* Remove the PG_reserved flag before returning the page */
+            mem_map_unreserve(MAP_NR(vm_pages.guest[p]));
+
             free_page(vm_pages.guest[p]);
         }
     }
@@ -564,11 +587,17 @@
             unalloc_vm_pages();
             return (-ENOMEM);
         }
-        set_bit(PG_reserved, &mem_map[MAP_NR(vm_pages.guest[p])].flags);   /* HACK!!! 
*/
-       //printk(KERN_WARNING "freemware: free page laddr was %08x\n",
-       //  vm_pages.guest[p]);
-       //printk(KERN_WARNING "freemware: free page paddr was %08lx\n",
-       //  virt_to_phys((void *) vm_pages.guest[p]));
+
+        /* 
+         * As we want to map these pages to user space, we need to mark
+         * them as 'reserved' pages by setting the PG_reserved bit.
+         *
+         * This has the effect that:
+         *  - remap_page_range accepts them as candidates for remapping
+         *  - the swapper does *not* try to swap these pages out, even
+         *    after they are mapped to user space
+         */
+        mem_map_reserve(MAP_NR(vm_pages.guest[p]));
     }
 
     vm_pages.monitor_page_dir = get_free_page(GFP_KERNEL);
diff -ur fmw-19990825a/kernel/include/host-linux.h fmw-uw/kernel/include/host-linux.h
--- fmw-19990825a/kernel/include/host-linux.h   Sun Aug 22 18:55:07 1999
+++ fmw-uw/kernel/include/host-linux.h  Thu Aug 26 23:20:15 1999
@@ -35,6 +35,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
+#include <linux/wrapper.h>
 #include <linux/version.h>
 #include <asm/irq.h>
 
diff -ur fmw-19990825a/user/user.c fmw-uw/user/user.c
--- fmw-19990825a/user/user.c   Wed Aug 25 20:54:46 1999
+++ fmw-uw/user/user.c  Fri Aug 27 00:29:02 1999
@@ -102,6 +102,12 @@
 
     fprintf(stderr, "Guest counter: %d\n", *(int *)(ptr + COUNTER_OFF));
 
+    fprintf(stderr, "Unmapping guest physical memory\n");
+    if (munmap(ptr, 8*1024*1024) != 0) {
+        perror("munmap");
+        exit(1);
+    }
+
     fprintf(stderr, "Tearing down VM\n");
     request = FMWTEARDOWN;
     data = 0;
-- 
  Ulrich Weigand,
  IMMD 1, Universitaet Erlangen-Nuernberg,
  Martensstr. 3, D-91058 Erlangen, Phone: +49 9131 85-7688

Reply via email to