]> xenbits.xensource.com Git - people/ssmith/netchannel2-pvops.git/commitdiff
xen: release unused free memory
authorMiroslav Rezanina <mrezanin@redhat.com>
Wed, 16 Sep 2009 07:56:17 +0000 (03:56 -0400)
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Wed, 16 Sep 2009 18:00:00 +0000 (11:00 -0700)
Scan an e820 table and release any memory which lies between e820 entries,
as it won't be used and would just be wasted.  At present this is just to
release any memory beyond the end of the e820 map, but it will also deal
with holes being punched in the map.

Derived from patch by Miroslav Rezanina <mrezanin@redhat.com>

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
arch/x86/xen/enlighten.c
arch/x86/xen/setup.c

index 5b55c92e5a03f5a997445a330d15ee7643643e2f..4a2367c281d201cd9a6a6f894bfe201ac1632717 100644 (file)
@@ -728,7 +728,6 @@ static __init void set_xen_basic_apic_ops(void)
 
 #endif
 
-
 static void xen_clts(void)
 {
        struct multicall_space mcs;
index ad0047f47cd476004c99485877f6d62a7db20d86..e0942630d47ab3a5849041c1b347456344b1b4fe 100644 (file)
@@ -20,6 +20,7 @@
 #include <xen/page.h>
 #include <xen/interface/callback.h>
 #include <xen/interface/physdev.h>
+#include <xen/interface/memory.h>
 #include <xen/features.h>
 
 #include "xen-ops.h"
@@ -32,6 +33,56 @@ extern void xen_sysenter_target(void);
 extern void xen_syscall_target(void);
 extern void xen_syscall32_target(void);
 
+static unsigned long __init xen_release_chunk(phys_addr_t start_addr, phys_addr_t end_addr)
+{
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+       unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
+       unsigned long start, end;
+       unsigned long len;
+       unsigned long pfn;
+       int ret;
+
+       start = PFN_UP(start_addr);
+       end = PFN_UP(end_addr);
+
+       if (end <= start)
+               return 0;
+
+       len = end - start;
+
+       set_xen_guest_handle(reservation.extent_start, &mfn_list[start]);
+       reservation.nr_extents = len;
+
+       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+       WARN(ret != (end - start), "Failed to release memory %lx-%lx err=%d\n",
+            start, end, ret);
+
+       for(pfn = start; pfn < end; pfn++)
+               set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+
+       return len;
+}
+
+static unsigned long __init xen_return_unused_memory(const struct e820map *e820)
+{
+       unsigned long last_end = 0;
+       unsigned long released = 0;
+       int i;
+
+       for (i = 0; i < e820->nr_map; i++) {
+               released += xen_release_chunk(last_end, e820->map[i].addr);
+               last_end = e820->map[i].addr + e820->map[i].size;
+       }
+
+       released += xen_release_chunk(last_end, PFN_PHYS(xen_start_info->nr_pages));
+
+       printk(KERN_INFO "released %ld pages of unused memory\n", released);
+       return released;
+}
 
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
@@ -67,6 +118,8 @@ char * __init xen_memory_setup(void)
 
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
+       xen_return_unused_memory(&e820);
+
        return "Xen";
 }