aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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