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

[Xen-changelog] Fix the cirrus vga model to not leak memory when switching between



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 1b55b85f8cb2f303209d81aa374abd2119f50d07
# Parent  c92fbde4074d698025204ed959755719a140e9af
Fix the cirrus vga model to not leak memory when switching between
initial vga mode and linear framebuffer.

When creating device model, the vga memory is allocated through
xc_domain_memory_increase_reservation(), however, when switch to use
linear framebuffer, we didn't free that memory, and re-allocate the vga
memory through set_mm_mapping(), that caused memory leak. Now it is
changed to just using qemu_malloc when create device model, and free
that memory when switch to linear framebuffer.

After unset_vram_mapping(), the old memory pointer should be
unmapped; after set_vram_mapping(), the old memory should be freed.

Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
---
 tools/ioemu/hw/cirrus_vga.c |   44 +++++++++++++------
 tools/ioemu/hw/pc.c         |    7 +--
 tools/ioemu/hw/vga.c        |   19 ++++----
 tools/ioemu/hw/vga_int.h    |    2 
 tools/ioemu/vl.c            |   99 ++++----------------------------------------
 5 files changed, 52 insertions(+), 119 deletions(-)

diff -r c92fbde4074d -r 1b55b85f8cb2 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c       Fri May 12 15:15:59 2006 +0100
+++ b/tools/ioemu/hw/cirrus_vga.c       Fri May 12 15:17:21 2006 +0100
@@ -272,7 +272,8 @@ typedef struct CirrusVGAState {
     int last_hw_cursor_y_end;
     int real_vram_size; /* XXX: suppress that */
     CPUWriteMemoryFunc **cirrus_linear_write;
-    int set_mapping;
+    unsigned long map_addr;
+    unsigned long map_end;
 } CirrusVGAState;
 
 typedef struct PCICirrusVGAState {
@@ -2543,12 +2544,12 @@ static void * set_vram_mapping(unsigned 
 static void * set_vram_mapping(unsigned long addr, unsigned long end) {}
 static int unset_vram_mapping(unsigned long addr, unsigned long end) {}
 #endif
+extern int vga_accelerate;
 
 /* Compute the memory access functions */
 static void cirrus_update_memory_access(CirrusVGAState *s)
 {
     unsigned mode;
-    extern int vga_accelerate;
 
     if ((s->sr[0x17] & 0x44) == 0x44) {
         goto generic_io;
@@ -2563,18 +2564,21 @@ static void cirrus_update_memory_access(
 
     mode = s->gr[0x05] & 0x7;
     if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
-            if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) {
-                if (!s->set_mapping) {
-                    void * vram_pointer;
-                    s->set_mapping = 1;
-                    vram_pointer = set_vram_mapping(s->cirrus_lfb_addr 
,s->cirrus_lfb_end);
-                    if (!vram_pointer){
+            if ( vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end ) {
+                if (!s->map_addr) {
+                    void *vram_pointer, *old_vram;
+
+                    vram_pointer =
+                      set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
+                    if (!vram_pointer) {
                         fprintf(stderr, "NULL vram_pointer\n");
-                    } else
-                    {
-                        vga_update_vram((VGAState *)s, vram_pointer,
+                    } else {
+                        old_vram = vga_update_vram((VGAState *)s, vram_pointer,
                                         VGA_RAM_SIZE);
+                        qemu_free(old_vram);
                     }
+                    s->map_addr = s->cirrus_lfb_addr;
+                    s->map_end = s->cirrus_lfb_end;
                 }
             }
             s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
@@ -2583,13 +2587,19 @@ static void cirrus_update_memory_access(
         } else {
         generic_io:
             if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) {
-                if(s->set_mapping) {
+                if(s->map_addr) {
                     int error;
-                    s->set_mapping = 0;
+                    void *old_vram = NULL;
+
                     error = unset_vram_mapping(s->cirrus_lfb_addr,
                                            s->cirrus_lfb_end);
                     if (!error)
-                        vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+                        old_vram =
+                          vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+
+                    if (old_vram)
+                        munmap(old_vram, s->map_addr - s->map_end);
+                    s->map_addr = s->map_end = 0;
                 }
             }
 
@@ -3184,6 +3194,12 @@ static void cirrus_pci_lfb_map(PCIDevice
                                 s->cirrus_linear_io_addr);
     s->cirrus_lfb_addr = addr;
     s->cirrus_lfb_end = addr + VGA_RAM_SIZE;
+
+    if ( vga_accelerate && s->map_addr &&
+         (s->cirrus_lfb_addr != s->map_addr) &&
+         (s->cirrus_lfb_end != s->map_end))
+        fprintf(logfile, "cirrus vga map change while on lfb mode\n");
+
     cpu_register_physical_memory(addr + 0x1000000, 0x400000,
                                 s->cirrus_linear_bitblt_io_addr);
 }
diff -r c92fbde4074d -r 1b55b85f8cb2 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Fri May 12 15:15:59 2006 +0100
+++ b/tools/ioemu/hw/pc.c       Fri May 12 15:17:21 2006 +0100
@@ -385,7 +385,6 @@ void pc_init(uint64_t ram_size, int vga_
     char buf[1024];
     int ret, linux_boot, initrd_size, i, nb_nics1;
     PCIBus *pci_bus;
-    extern void * shared_vram;
     
     linux_boot = (kernel_filename != NULL);
 
@@ -512,14 +511,14 @@ void pc_init(uint64_t ram_size, int vga_
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
             pci_cirrus_vga_init(pci_bus, 
-                                ds, shared_vram, ram_size, 
+                                ds, NULL, ram_size, 
                                 vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, shared_vram, ram_size, 
+            isa_cirrus_vga_init(ds, NULL, ram_size, 
                                 vga_ram_size);
         }
     } else {
-        vga_initialize(pci_bus, ds, shared_vram, ram_size, 
+        vga_initialize(pci_bus, ds, NULL, ram_size, 
                        vga_ram_size);
     }
 
diff -r c92fbde4074d -r 1b55b85f8cb2 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Fri May 12 15:15:59 2006 +0100
+++ b/tools/ioemu/hw/vga.c      Fri May 12 15:17:21 2006 +0100
@@ -1946,11 +1946,11 @@ void vga_bios_init(VGAState *s)
 
 }
 
+/* when used on xen environment, the vga_ram_base is not used */
 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
                      unsigned long vga_ram_offset, int vga_ram_size)
 {
     int i, j, v, b;
-    extern void* shared_vram;
 
     for(i = 0;i < 256; i++) {
         v = 0;
@@ -1979,11 +1979,7 @@ void vga_common_init(VGAState *s, Displa
 
     /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort
      * when guest write vga mem, so allocate a new one */
-#if defined(__i386__) || defined(__x86_64__)
-    s->vram_ptr = shared_vram;
-#else
     s->vram_ptr = qemu_malloc(vga_ram_size);
-#endif
     check_sse2();
     s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1);
     if (s->vram_shadow == NULL)
@@ -2090,12 +2086,14 @@ int vga_initialize(PCIBus *bus, DisplayS
     return 0;
 }
 
-int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
-{
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
+{
+    uint8_t *old_pointer;
+
     if (s->vram_size != vga_ram_size)
     {
         fprintf(stderr, "No support to change vga_ram_size\n");
-        return -1;
+        return NULL;
     }
 
     if ( !vga_ram_base )
@@ -2104,15 +2102,16 @@ int vga_update_vram(VGAState *s, void *v
         if (!vga_ram_base)
         {
             fprintf(stderr, "reallocate error\n");
-            return -1;
+            return NULL;
         }
     }
 
     /* XXX lock needed? */
     memcpy(vga_ram_base, s->vram_ptr, vga_ram_size);
+    old_pointer = s->vram_ptr;
     s->vram_ptr = vga_ram_base;
 
-    return 0;
+    return old_pointer;
 }
 
 /********************************************************/
diff -r c92fbde4074d -r 1b55b85f8cb2 tools/ioemu/hw/vga_int.h
--- a/tools/ioemu/hw/vga_int.h  Fri May 12 15:15:59 2006 +0100
+++ b/tools/ioemu/hw/vga_int.h  Fri May 12 15:17:21 2006 +0100
@@ -165,6 +165,6 @@ void vga_draw_cursor_line_32(uint8_t *d1
                              unsigned int color0, unsigned int color1,
                              unsigned int color_xor);
 
-int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
 extern const uint8_t sr_mask[8];
 extern const uint8_t gr_mask[16];
diff -r c92fbde4074d -r 1b55b85f8cb2 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Fri May 12 15:15:59 2006 +0100
+++ b/tools/ioemu/vl.c  Fri May 12 15:17:21 2006 +0100
@@ -147,12 +147,6 @@ TextConsole *vga_console;
 TextConsole *vga_console;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 int xc_handle;
-unsigned long *vgapage_array;
-unsigned long *freepage_array;
-unsigned long free_pages;
-void *vtop_table;
-unsigned long toptab;
-unsigned long vgaram_pages;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -2454,32 +2448,6 @@ static uint8_t *signal_stack;
 
 #include <xg_private.h>
 
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-#ifdef __i386__
-#define _LEVEL_3_ 0
-#else
-#define _LEVEL_3_ 1
-#endif
-
-#if _LEVEL_3_
-#define L3_PROT (_PAGE_PRESENT)
-#define L1_PAGETABLE_ENTRIES    512
-#else
-#define L1_PAGETABLE_ENTRIES    1024
-#endif
-
-inline int
-get_vl2_table(unsigned long count, unsigned long start)
-{
-#if _LEVEL_3_
-    return ((start + (count << PAGE_SHIFT)) >> L3_PAGETABLE_SHIFT) & 0x3;
-#else
-    return 0;
-#endif
-}
-
 /* FIXME Flush the shadow page */
 int unset_mm_mapping(int xc_handle,
                      uint32_t domid,
@@ -2584,10 +2552,8 @@ int main(int argc, char **argv)
     int serial_device_index;
     char qemu_dm_logfilename[64];
     const char *loadvm = NULL;
-    unsigned long nr_pages, extra_pages, ram_pages, *page_array;
-    xc_dominfo_t info;
+    unsigned long nr_pages, *page_array;
     extern void *shared_page;
-    extern void *shared_vram;
 
 #if !defined(CONFIG_SOFTMMU)
     /* we never want that malloc() uses mmap() */
@@ -3045,28 +3011,9 @@ int main(int argc, char **argv)
     /* init the memory */
     phys_ram_size = ram_size + vga_ram_size + bios_size;
 
-    ram_pages = ram_size/PAGE_SIZE;
-#if defined(__i386__) || defined(__x86_64__)
-    vgaram_pages =  (vga_ram_size -1) / PAGE_SIZE + 1;
-    free_pages = vgaram_pages / L1_PAGETABLE_ENTRIES;
-    extra_pages = vgaram_pages + free_pages;
-#else
-    /* Test vga acceleration later */
-    extra_pages = 0;
-#endif
+    nr_pages = ram_size/PAGE_SIZE;
 
     xc_handle = xc_interface_open();
-
-    xc_domain_getinfo(xc_handle, domid, 1, &info);
-
-    nr_pages = info.nr_pages + extra_pages;
-
-    if ( xc_domain_setmaxmem(xc_handle, domid,
-                             (nr_pages) * PAGE_SIZE/1024 ) != 0)
-    {
-        fprintf(logfile, "set maxmem returned error %d\n", errno);
-        exit(-1);
-    }
 
     if ( (page_array = (unsigned long *)
                         malloc(nr_pages * sizeof(unsigned long))) == NULL)
@@ -3075,24 +3022,16 @@ int main(int argc, char **argv)
         exit(-1);
     }
 
-    if (xc_domain_memory_increase_reservation(xc_handle, domid,
-                                              extra_pages , 0, 0, NULL) != 0)
-    {
-        fprintf(logfile, "increase reservation returned error %d\n", errno);
-        exit(-1);
-    }
-
 #if defined(__i386__) || defined(__x86_64__)
     if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
     {
         fprintf(logfile, "xc_get_pfn_list returned error %d\n", errno);
         exit(-1);
     }
-
     if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
                           PROT_READ|PROT_WRITE,
                           page_array,
-                          ram_pages - 1)) == 0 )
+                          nr_pages - 1)) == 0 )
     {
         fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
         exit(-1);
@@ -3100,31 +3039,11 @@ int main(int argc, char **argv)
 
     shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
                                        PROT_READ|PROT_WRITE,
-                                       page_array[ram_pages - 1]);
-
-    vgapage_array = &page_array[nr_pages - vgaram_pages];
-
-    if ( (shared_vram =  xc_map_foreign_batch(xc_handle, domid,
-                                              PROT_READ|PROT_WRITE,
-                                              vgapage_array,
-                                              vgaram_pages)) == 0)
-    {
-        fprintf(logfile,
-                "xc_map_foreign_batch vgaram returned error %d\n", errno);
-        exit(-1);
-    }
-
-    memset(shared_vram, 0, vgaram_pages * PAGE_SIZE);
-    toptab = page_array[ram_pages] << PAGE_SHIFT;
-
-    vtop_table = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
-                                      PROT_READ|PROT_WRITE,
-                                      page_array[ram_pages]);
-
-    freepage_array = &page_array[nr_pages - extra_pages];
+                                       page_array[nr_pages - 1]);
+
 #elif defined(__ia64__)
-    if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, ram_pages)
-         != ram_pages )
+    if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, nr_pages)
+         != nr_pages)
     {
         fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno);
         exit(-1);
@@ -3133,7 +3052,7 @@ int main(int argc, char **argv)
     if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
                           PROT_READ|PROT_WRITE,
                           page_array,
-                          ram_pages)) == 0 )
+                          nr_pages)) == 0 )
     {
         fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
         exit(-1);
@@ -3141,7 +3060,7 @@ int main(int argc, char **argv)
 
     if ( xc_ia64_get_pfn_list(xc_handle, domid,
                               page_array,
-                              ram_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 )
+                              nr_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 )
     {
         fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno);
         exit(-1);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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