diff options
Diffstat (limited to 'arch/x86/xen/setup.c')
| -rw-r--r-- | arch/x86/xen/setup.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index ad0047f47cd4..328b00305426 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,73 @@ 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, | ||
| 37 | phys_addr_t end_addr) | ||
| 38 | { | ||
| 39 | struct xen_memory_reservation reservation = { | ||
| 40 | .address_bits = 0, | ||
| 41 | .extent_order = 0, | ||
| 42 | .domid = DOMID_SELF | ||
| 43 | }; | ||
| 44 | unsigned long start, end; | ||
| 45 | unsigned long len = 0; | ||
| 46 | unsigned long pfn; | ||
| 47 | int ret; | ||
| 48 | |||
| 49 | start = PFN_UP(start_addr); | ||
| 50 | end = PFN_DOWN(end_addr); | ||
| 51 | |||
| 52 | if (end <= start) | ||
| 53 | return 0; | ||
| 54 | |||
| 55 | printk(KERN_INFO "xen_release_chunk: looking at area pfn %lx-%lx: ", | ||
| 56 | start, end); | ||
| 57 | for(pfn = start; pfn < end; pfn++) { | ||
| 58 | unsigned long mfn = pfn_to_mfn(pfn); | ||
| 59 | |||
| 60 | /* Make sure pfn exists to start with */ | ||
| 61 | if (mfn == INVALID_P2M_ENTRY || mfn_to_pfn(mfn) != pfn) | ||
| 62 | continue; | ||
| 63 | |||
| 64 | set_xen_guest_handle(reservation.extent_start, &mfn); | ||
| 65 | reservation.nr_extents = 1; | ||
| 66 | |||
| 67 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, | ||
| 68 | &reservation); | ||
| 69 | WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", | ||
| 70 | start, end, ret); | ||
| 71 | if (ret == 1) { | ||
| 72 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | ||
| 73 | len++; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | printk(KERN_CONT "%ld pages freed\n", len); | ||
| 77 | |||
| 78 | return len; | ||
| 79 | } | ||
| 80 | |||
| 81 | static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, | ||
| 82 | const struct e820map *e820) | ||
| 83 | { | ||
| 84 | phys_addr_t max_addr = PFN_PHYS(max_pfn); | ||
| 85 | phys_addr_t last_end = 0; | ||
| 86 | unsigned long released = 0; | ||
| 87 | int i; | ||
| 88 | |||
| 89 | for (i = 0; i < e820->nr_map && last_end < max_addr; i++) { | ||
| 90 | phys_addr_t end = e820->map[i].addr; | ||
| 91 | end = min(max_addr, end); | ||
| 92 | |||
| 93 | released += xen_release_chunk(last_end, end); | ||
| 94 | last_end = e820->map[i].addr + e820->map[i].size; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (last_end < max_addr) | ||
| 98 | released += xen_release_chunk(last_end, max_addr); | ||
| 99 | |||
| 100 | printk(KERN_INFO "released %ld pages of unused memory\n", released); | ||
| 101 | return released; | ||
| 102 | } | ||
| 35 | 103 | ||
| 36 | /** | 104 | /** |
| 37 | * machine_specific_memory_setup - Hook for machine specific memory setup. | 105 | * machine_specific_memory_setup - Hook for machine specific memory setup. |
| @@ -67,6 +135,8 @@ char * __init xen_memory_setup(void) | |||
| 67 | 135 | ||
| 68 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 136 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
| 69 | 137 | ||
| 138 | xen_return_unused_memory(xen_start_info->nr_pages, &e820); | ||
| 139 | |||
| 70 | return "Xen"; | 140 | return "Xen"; |
| 71 | } | 141 | } |
| 72 | 142 | ||
| @@ -156,6 +226,8 @@ void __init xen_arch_setup(void) | |||
| 156 | struct physdev_set_iopl set_iopl; | 226 | struct physdev_set_iopl set_iopl; |
| 157 | int rc; | 227 | int rc; |
| 158 | 228 | ||
| 229 | xen_panic_handler_init(); | ||
| 230 | |||
| 159 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); | 231 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); |
| 160 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); | 232 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); |
| 161 | 233 | ||
