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 | ||
