aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
authorMiroslav Rezanina <mrezanin@redhat.com>2009-09-16 03:56:17 -0400
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-07-20 15:51:22 -0400
commit093d7b4639951ea3021a6f70d376c3ff31f4740c (patch)
tree552be40304174678d2db47c3259ce59fe5483d9f /arch/x86/xen
parente40152ee1e1c7a63f4777791863215e3faa37a86 (diff)
xen: release unused free memory
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>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/enlighten.c1
-rw-r--r--arch/x86/xen/setup.c53
2 files changed, 53 insertions, 1 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 65d8d79b46a8..399bed2de881 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -731,7 +731,6 @@ static void set_xen_basic_apic_ops(void)
731 731
732#endif 732#endif
733 733
734
735static void xen_clts(void) 734static void xen_clts(void)
736{ 735{
737 struct multicall_space mcs; 736 struct multicall_space mcs;
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index ad0047f47cd4..e0942630d47a 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -20,6 +20,7 @@
20#include <xen/page.h> 20#include <xen/page.h>
21#include <xen/interface/callback.h> 21#include <xen/interface/callback.h>
22#include <xen/interface/physdev.h> 22#include <xen/interface/physdev.h>
23#include <xen/interface/memory.h>
23#include <xen/features.h> 24#include <xen/features.h>
24 25
25#include "xen-ops.h" 26#include "xen-ops.h"
@@ -32,6 +33,56 @@ extern void xen_sysenter_target(void);
32extern void xen_syscall_target(void); 33extern void xen_syscall_target(void);
33extern void xen_syscall32_target(void); 34extern void xen_syscall32_target(void);
34 35
36static unsigned long __init xen_release_chunk(phys_addr_t start_addr, phys_addr_t end_addr)
37{
38 struct xen_memory_reservation reservation = {
39 .address_bits = 0,
40 .extent_order = 0,
41 .domid = DOMID_SELF
42 };
43 unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
44 unsigned long start, end;
45 unsigned long len;
46 unsigned long pfn;
47 int ret;
48
49 start = PFN_UP(start_addr);
50 end = PFN_UP(end_addr);
51
52 if (end <= start)
53 return 0;
54
55 len = end - start;
56
57 set_xen_guest_handle(reservation.extent_start, &mfn_list[start]);
58 reservation.nr_extents = len;
59
60 ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
61 WARN(ret != (end - start), "Failed to release memory %lx-%lx err=%d\n",
62 start, end, ret);
63
64 for(pfn = start; pfn < end; pfn++)
65 set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
66
67 return len;
68}
69
70static unsigned long __init xen_return_unused_memory(const struct e820map *e820)
71{
72 unsigned long last_end = 0;
73 unsigned long released = 0;
74 int i;
75
76 for (i = 0; i < e820->nr_map; i++) {
77 released += xen_release_chunk(last_end, e820->map[i].addr);
78 last_end = e820->map[i].addr + e820->map[i].size;
79 }
80
81 released += xen_release_chunk(last_end, PFN_PHYS(xen_start_info->nr_pages));
82
83 printk(KERN_INFO "released %ld pages of unused memory\n", released);
84 return released;
85}
35 86
36/** 87/**
37 * machine_specific_memory_setup - Hook for machine specific memory setup. 88 * machine_specific_memory_setup - Hook for machine specific memory setup.
@@ -67,6 +118,8 @@ char * __init xen_memory_setup(void)
67 118
68 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); 119 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
69 120
121 xen_return_unused_memory(&e820);
122
70 return "Xen"; 123 return "Xen";
71} 124}
72 125