From 093d7b4639951ea3021a6f70d376c3ff31f4740c Mon Sep 17 00:00:00 2001
From: Miroslav Rezanina <mrezanin@redhat.com>
Date: Wed, 16 Sep 2009 03:56:17 -0400
Subject: 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>
---
 arch/x86/xen/setup.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

(limited to 'arch/x86/xen/setup.c')

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 @@
 #include <xen/page.h>
 #include <xen/interface/callback.h>
 #include <xen/interface/physdev.h>
+#include <xen/interface/memory.h>
 #include <xen/features.h>
 
 #include "xen-ops.h"
@@ -32,6 +33,56 @@ extern void xen_sysenter_target(void);
 extern void xen_syscall_target(void);
 extern void xen_syscall32_target(void);
 
+static unsigned long __init xen_release_chunk(phys_addr_t start_addr, phys_addr_t end_addr)
+{
+	struct xen_memory_reservation reservation = {
+		.address_bits = 0,
+		.extent_order = 0,
+		.domid        = DOMID_SELF
+	};
+	unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
+	unsigned long start, end;
+	unsigned long len;
+	unsigned long pfn;
+	int ret;
+
+	start = PFN_UP(start_addr);
+	end = PFN_UP(end_addr);
+
+	if (end <= start)
+		return 0;
+
+	len = end - start;
+
+	set_xen_guest_handle(reservation.extent_start, &mfn_list[start]);
+	reservation.nr_extents = len;
+
+	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+	WARN(ret != (end - start), "Failed to release memory %lx-%lx err=%d\n",
+	     start, end, ret);
+
+	for(pfn = start; pfn < end; pfn++)
+		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+
+	return len;
+}
+
+static unsigned long __init xen_return_unused_memory(const struct e820map *e820)
+{
+	unsigned long last_end = 0;
+	unsigned long released = 0;
+	int i;
+
+	for (i = 0; i < e820->nr_map; i++) {
+		released += xen_release_chunk(last_end, e820->map[i].addr);
+		last_end = e820->map[i].addr + e820->map[i].size;
+	}
+
+	released += xen_release_chunk(last_end, PFN_PHYS(xen_start_info->nr_pages));
+
+	printk(KERN_INFO "released %ld pages of unused memory\n", released);
+	return released;
+}
 
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
@@ -67,6 +118,8 @@ char * __init xen_memory_setup(void)
 
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
+	xen_return_unused_memory(&e820);
+
 	return "Xen";
 }
 
-- 
cgit 


From f89e048e76da7ac0b4c89e75606ca7a3422886b1 Mon Sep 17 00:00:00 2001
From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Date: Wed, 16 Sep 2009 12:38:33 -0700
Subject: xen: make sure pages are really part of domain before freeing

Scan the set of pages we're freeing and make sure they're actually
owned by the domain before freeing.  This generally won't happen on a
domU (since Xen gives us contigious memory), but it could happen if
there are some hardware mappings passed through.

We only bother going up to the highest page Xen actually claimed to
give us, since there's definitely nothing of ours above that.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 arch/x86/xen/setup.c | 59 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 21 deletions(-)

(limited to 'arch/x86/xen/setup.c')

diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index e0942630d47a..9deb6bab6c78 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -33,52 +33,69 @@ extern void xen_sysenter_target(void);
 extern void xen_syscall_target(void);
 extern void xen_syscall32_target(void);
 
-static unsigned long __init xen_release_chunk(phys_addr_t start_addr, phys_addr_t end_addr)
+static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
+					      phys_addr_t end_addr)
 {
 	struct xen_memory_reservation reservation = {
 		.address_bits = 0,
 		.extent_order = 0,
 		.domid        = DOMID_SELF
 	};
-	unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
 	unsigned long start, end;
-	unsigned long len;
+	unsigned long len = 0;
 	unsigned long pfn;
 	int ret;
 
 	start = PFN_UP(start_addr);
-	end = PFN_UP(end_addr);
+	end = PFN_DOWN(end_addr);
 
 	if (end <= start)
 		return 0;
 
-	len = end - start;
-
-	set_xen_guest_handle(reservation.extent_start, &mfn_list[start]);
-	reservation.nr_extents = len;
-
-	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
-	WARN(ret != (end - start), "Failed to release memory %lx-%lx err=%d\n",
-	     start, end, ret);
-
-	for(pfn = start; pfn < end; pfn++)
-		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+	printk(KERN_INFO "xen_release_chunk: looking at area pfn %lx-%lx: ",
+	       start, end);
+	for(pfn = start; pfn < end; pfn++) {
+		unsigned long mfn = pfn_to_mfn(pfn);
+
+		/* Make sure pfn exists to start with */
+		if (mfn == INVALID_P2M_ENTRY || mfn_to_pfn(mfn) != pfn)
+			continue;
+
+		set_xen_guest_handle(reservation.extent_start, &mfn);
+		reservation.nr_extents = 1;
+
+		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					   &reservation);
+		WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
+		     start, end, ret);
+		if (ret == 1) {
+			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+			len++;
+		}
+	}
+	printk(KERN_CONT "%ld pages freed\n", len);
 
 	return len;
 }
 
-static unsigned long __init xen_return_unused_memory(const struct e820map *e820)
+static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
+						     const struct e820map *e820)
 {
-	unsigned long last_end = 0;
+	phys_addr_t max_addr = PFN_PHYS(max_pfn);
+	phys_addr_t last_end = 0;
 	unsigned long released = 0;
 	int i;
 
-	for (i = 0; i < e820->nr_map; i++) {
-		released += xen_release_chunk(last_end, e820->map[i].addr);
+	for (i = 0; i < e820->nr_map && last_end < max_addr; i++) {
+		phys_addr_t end = e820->map[i].addr;
+		end = min(max_addr, end);
+
+		released += xen_release_chunk(last_end, end);
 		last_end = e820->map[i].addr + e820->map[i].size;
 	}
 
-	released += xen_release_chunk(last_end, PFN_PHYS(xen_start_info->nr_pages));
+	if (last_end < max_addr)
+		released += xen_release_chunk(last_end, max_addr);
 
 	printk(KERN_INFO "released %ld pages of unused memory\n", released);
 	return released;
@@ -118,7 +135,7 @@ char * __init xen_memory_setup(void)
 
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
-	xen_return_unused_memory(&e820);
+	xen_return_unused_memory(xen_start_info->nr_pages, &e820);
 
 	return "Xen";
 }
-- 
cgit 


From f09f6d194d85043e0eb105a577e7ad6d8170ab66 Mon Sep 17 00:00:00 2001
From: Donald Dutile <ddutile@redhat.com>
Date: Thu, 15 Jul 2010 14:56:49 -0400
Subject: Xen: register panic notifier to take crashes of xen guests on panic

Register a panic notifier so that when the guest crashes it can shut
down the domain and indicate it was a crash to the host.

Signed-off-by: Donald Dutile <ddutile@redhat.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 arch/x86/xen/setup.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'arch/x86/xen/setup.c')

diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 9deb6bab6c78..328b00305426 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -226,6 +226,8 @@ void __init xen_arch_setup(void)
 	struct physdev_set_iopl set_iopl;
 	int rc;
 
+	xen_panic_handler_init();
+
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
 
-- 
cgit