diff options
-rw-r--r-- | arch/x86/xen/enlighten.c | 1 | ||||
-rw-r--r-- | arch/x86/xen/setup.c | 53 |
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 | |||
735 | static void xen_clts(void) | 734 | static 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); | |||
32 | extern void xen_syscall_target(void); | 33 | extern void xen_syscall_target(void); |
33 | extern void xen_syscall32_target(void); | 34 | extern void xen_syscall32_target(void); |
34 | 35 | ||
36 | static 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 | |||
70 | static 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 | ||