qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] pc: madvise(MADV_DONTNEED) memory on reset


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH] pc: madvise(MADV_DONTNEED) memory on reset
Date: Wed, 24 Feb 2010 13:10:12 -0600

If you compare the RSS of a freshly booted guest and the same guest after a
reboot, it's very likely the freshly booted guest will have an RSS that is
much lower the the rebooted guest because the previous run of the guest faulted
in all available memory.

This patch addresses this issue by using madvise() during reset.  It only
resets RAM areas which means it has to be done in the machine.  I've only done
this for the x86 target because I'm fairly confident that this is allowed
architecturally on x86 although I'm not sure this is universely true.

This does not appear to have an observable cost with a large memory guest and
I can't really think of any down sides.

Reported-by: Karl Rister <address@hidden>
Signed-off-by: Anthony Liguori <address@hidden>
---
 hw/pc.c |   40 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 4f6a522..10446ba 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -45,6 +45,11 @@
 #include "loader.h"
 #include "elf.h"
 #include "multiboot.h"
+#include "kvm.h"
+
+#ifndef _WIN32
+#include <sys/mman.h>
+#endif
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -63,10 +68,19 @@
 
 #define MAX_IDE_BUS 2
 
+#define MAX_MEMORY_ENTRIES 10
+
+typedef struct MemoryEntry {
+    ram_addr_t addr;
+    ram_addr_t size;
+} MemoryEntry;
+
 static FDCtrl *floppy_controller;
 static RTCState *rtc_state;
 static PITState *pit;
 static PCII440FXState *i440fx_state;
+static int num_memory_entries;
+static MemoryEntry memory_entries[MAX_MEMORY_ENTRIES];
 
 #define E820_NR_ENTRIES                16
 
@@ -782,6 +796,27 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static void add_mem_entry(ram_addr_t addr, ram_addr_t size)
+{
+    memory_entries[num_memory_entries].addr = addr;
+    memory_entries[num_memory_entries].size = size;
+    num_memory_entries++;
+}
+
+static void pc_reset_ram(void *opaque)
+{
+    int i;
+
+    for (i = 0; i < num_memory_entries; i++) {
+#ifndef _WIN32
+        if (!kvm_enabled() || kvm_has_sync_mmu()) {
+            madvise(qemu_get_ram_ptr(memory_entries[i].addr),
+                    memory_entries[i].size, MADV_DONTNEED);
+        }
+#endif
+    }
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -835,6 +870,7 @@ static void pc_init1(ram_addr_t ram_size,
     /* allocate RAM */
     ram_addr = qemu_ram_alloc(0xa0000);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
+    add_mem_entry(ram_addr, 0xa0000);
 
     /* Allocate, even though we won't register, so we don't break the
      * phys_ram_base + PA assumption. This range includes vga (0xa0000 - 
0xc0000),
@@ -845,6 +881,7 @@ static void pc_init1(ram_addr_t ram_size,
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
                  ram_addr);
+    add_mem_entry(ram_addr, below_4g_mem_size - 0x100000);
 
     /* above 4giga memory allocation */
     if (above_4g_mem_size > 0) {
@@ -855,6 +892,7 @@ static void pc_init1(ram_addr_t ram_size,
         cpu_register_physical_memory(0x100000000ULL,
                                      above_4g_mem_size,
                                      ram_addr);
+        add_mem_entry(ram_addr, above_4g_mem_size);
 #endif
     }
 
@@ -1050,6 +1088,8 @@ static void pc_init1(ram_addr_t ram_size,
             pci_create_simple(pci_bus, -1, "lsi53c895a");
         }
     }
+
+    qemu_register_reset(pc_reset_ram, NULL);
 }
 
 static void pc_init_pci(ram_addr_t ram_size,
-- 
1.6.5.2





reply via email to

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