svn commit: r188684 - user/dfr/xenhvm/7/sys/xen

Doug Rabson dfr at FreeBSD.org
Mon Feb 16 09:16:27 PST 2009


Author: dfr
Date: Mon Feb 16 17:16:26 2009
New Revision: 188684
URL: http://svn.freebsd.org/changeset/base/188684

Log:
  Diff reduction with user/dfr/xenhvm/6.

Added:
  user/dfr/xenhvm/7/sys/xen/features.h
  user/dfr/xenhvm/7/sys/xen/reboot.c
Modified:
  user/dfr/xenhvm/7/sys/xen/evtchn.h
  user/dfr/xenhvm/7/sys/xen/features.c
  user/dfr/xenhvm/7/sys/xen/gnttab.c
  user/dfr/xenhvm/7/sys/xen/gnttab.h
  user/dfr/xenhvm/7/sys/xen/hypervisor.h
  user/dfr/xenhvm/7/sys/xen/xen_intr.h

Modified: user/dfr/xenhvm/7/sys/xen/evtchn.h
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/evtchn.h	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/evtchn.h	Mon Feb 16 17:16:26 2009	(r188684)
@@ -28,7 +28,7 @@ void notify_remote_via_irq(int irq);
 
 
 /* Entry point for notifications into Linux subsystems. */
-void evtchn_do_upcall(struct trapframe *frame);
+void evtchn_do_upcall(struct intrframe *frame);
 
 /* Entry point for notifications into the userland character device. */
 void evtchn_device_upcall(int port);

Modified: user/dfr/xenhvm/7/sys/xen/features.c
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/features.c	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/features.c	Mon Feb 16 17:16:26 2009	(r188684)
@@ -1,10 +1,12 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
 #include <machine/xen/xen-os.h>
 #include <xen/hypervisor.h>
-#include <machine/xen/features.h>
+#include <xen/features.h>
 
 uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32] /* __read_mostly */;
 

Added: user/dfr/xenhvm/7/sys/xen/features.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/dfr/xenhvm/7/sys/xen/features.h	Mon Feb 16 17:16:26 2009	(r188684)
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * features.h
+ *
+ * Query the features reported by Xen.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+
+#ifndef __ASM_XEN_FEATURES_H__
+#define __ASM_XEN_FEATURES_H__
+
+#include <xen/interface/version.h>
+
+extern void setup_xen_features(void);
+
+extern uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32];
+
+#define xen_feature(flag)	(xen_features[flag])
+
+#endif /* __ASM_XEN_FEATURES_H__ */

Modified: user/dfr/xenhvm/7/sys/xen/gnttab.c
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/gnttab.c	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/gnttab.c	Mon Feb 16 17:16:26 2009	(r188684)
@@ -25,28 +25,20 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mman.h>
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <vm/vm_page.h>
-#include <vm/vm_kern.h>
 
+#include <machine/xen/xen-os.h>
 #include <xen/hypervisor.h>
 #include <machine/xen/synch_bitops.h>
-#include <xen/gnttab.h>
 
-#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c))
+#include <xen/hypervisor.h>
+#include <xen/gnttab.h>
 
-#if 1
-#define ASSERT(_p) \
-    if ( !(_p) ) { printk("Assertion '%s': line %d, file %s\n", \
-    #_p , __LINE__, __FILE__); *(int*)0=0; }
-#else
-#define ASSERT(_p) ((void)0)
-#endif
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
 
-#define WPRINTK(fmt, args...) \
-    printk("xen_grant: " fmt, ##args)
+#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c))
 
 /* External tools reserve first few grant table entries. */
 #define NR_RESERVED_ENTRIES 8
@@ -72,14 +64,14 @@ static int gnttab_expand(unsigned int re
 static int
 get_free_entries(int count, int *entries)
 {
-	int ref, rc;
+	int ref, error;
 	grant_ref_t head;
 	
 	mtx_lock(&gnttab_list_lock);
 	if ((gnttab_free_count < count) &&
-	    ((rc = gnttab_expand(count - gnttab_free_count)) != 0)) {
+	    ((error = gnttab_expand(count - gnttab_free_count)) != 0)) {
 		mtx_unlock(&gnttab_list_lock);
-		return (rc);
+		return (error);
 	}
 	ref = head = gnttab_free_head;
 	gnttab_free_count -= count;
@@ -163,6 +155,7 @@ void
 gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
 				unsigned long frame, int readonly)
 {
+
 	shared[ref].frame = frame;
 	shared[ref].domid = domid;
 	wmb();
@@ -213,7 +206,8 @@ gnttab_end_foreign_access(grant_ref_t re
 }
 
 int
-gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
+gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn,
+    grant_ref_t *result)
 {
 	int error, ref;
 
@@ -223,7 +217,8 @@ gnttab_grant_foreign_transfer(domid_t do
 
 	gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
 	
-	return (ref);
+	*result = ref;
+	return (0);
 }
 
 void
@@ -261,7 +256,7 @@ gnttab_end_foreign_transfer_ref(grant_re
 	/* Read the frame number /after/ reading completion status. */
 	rmb();
 	frame = shared[ref].frame;
-	PANIC_IF(frame == 0);
+	KASSERT(frame != 0, ("grant table inconsistent"));
 
 	return (frame);
 }
@@ -320,6 +315,7 @@ gnttab_alloc_grant_references(uint16_t c
 int
 gnttab_empty_grant_references(const grant_ref_t *private_head)
 {
+
 	return (*private_head == GNTTAB_LIST_END);
 }
 
@@ -331,20 +327,20 @@ gnttab_claim_grant_reference(grant_ref_t
 	if (unlikely(g == GNTTAB_LIST_END))
 		return (ENOSPC);
 	*private_head = gnttab_entry(g);
-
 	return (g);
 }
 
 void
 gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t  release)
 {
+
 	gnttab_entry(release) = *private_head;
 	*private_head = release;
 }
 
 void
 gnttab_request_free_callback(struct gnttab_free_callback *callback,
-			     void (*fn)(void *), void *arg, uint16_t count)
+    void (*fn)(void *), void *arg, uint16_t count)
 {
 
 	mtx_lock(&gnttab_list_lock);
@@ -387,7 +383,8 @@ grow_gnttab_list(unsigned int more_frame
 
 	for (i = nr_grant_frames; i < new_nr_grant_frames; i++)
 	{
-		gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+		gnttab_list[i] = (grant_ref_t *)
+			malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
 
 		if (!gnttab_list[i])
 			goto grow_nomem;
@@ -405,12 +402,12 @@ grow_gnttab_list(unsigned int more_frame
 
 	check_free_callbacks();
 
-	return 0;
+	return (0);
 	
 grow_nomem:
 	for ( ; i >= nr_grant_frames; i--)
 		free(gnttab_list[i], M_DEVBUF);
-	return (-ENOMEM);
+	return (ENOMEM);
 }
 
 static unsigned int
@@ -464,6 +461,8 @@ unmap_pte_fn(pte_t *pte, struct page *pm
 }
 #endif
 
+#ifndef XENHVM
+
 static int
 gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
@@ -486,50 +485,117 @@ gnttab_map(unsigned int start_idx, unsig
 		free(frames, M_DEVBUF);
 		return (ENOSYS);
 	}
-	PANIC_IF(rc || setup.status);
+	KASSERT(!(rc || setup.status),
+	    ("unexpected result from grant_table_op"));
 
 	if (shared == NULL) {
 		vm_offset_t area;
 		
 		area = kmem_alloc_nofault(kernel_map,
 		    PAGE_SIZE * max_nr_grant_frames());
-		PANIC_IF(area == 0);
+		KASSERT(area, ("can't allocate VM space for grant table"));
 		shared = (grant_entry_t *)area;
 	}
+
 	for (i = 0; i < nr_gframes; i++)
 		PT_SET_MA(((caddr_t)shared) + i*PAGE_SIZE, 
 		    ((vm_paddr_t)frames[i]) << PAGE_SHIFT | PG_RW | PG_V);
 
 	free(frames, M_DEVBUF);
 	
-	return 0;
+	return (0);
 }
 
 int
 gnttab_resume(void)
 {
+
 	if (max_nr_grant_frames() < nr_grant_frames)
-		return -ENOSYS;
-	return gnttab_map(0, nr_grant_frames - 1);
+		return (ENOSYS);
+	return (gnttab_map(0, nr_grant_frames - 1));
 }
 
 int
 gnttab_suspend(void)
 {	
-	int i, pages;
+	int i;
+
+	for (i = 0; i < nr_grant_frames; i++)
+		pmap_kremove((vm_offset_t) shared + i * PAGE_SIZE);
+
+	return (0);
+}
+
+#else /* XENHVM */
 
-	pages = (PAGE_SIZE*nr_grant_frames) >> PAGE_SHIFT;
+#include <dev/xen/xenpci/xenpcivar.h>
 
-	for (i = 0; i < pages; i++)
-		PT_SET_MA(shared + (i*PAGE_SIZE), (vm_paddr_t)0);
+static vm_paddr_t resume_frames;
+
+static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+{
+	struct xen_add_to_physmap xatp;
+	unsigned int i = end_idx;
+
+	/*
+	 * Loop backwards, so that the first hypercall has the largest index,
+	 * ensuring that the table will grow only once.
+	 */
+	do {
+		xatp.domid = DOMID_SELF;
+		xatp.idx = i;
+		xatp.space = XENMAPSPACE_grant_table;
+		xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i;
+		if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+			panic("HYPERVISOR_memory_op failed to map gnttab");
+	} while (i-- > start_idx);
+
+	if (shared == NULL) {
+		vm_offset_t area;
+		
+		area = kmem_alloc_nofault(kernel_map,
+		    PAGE_SIZE * max_nr_grant_frames());
+		KASSERT(area, ("can't allocate VM space for grant table"));
+		shared = (grant_entry_t *)area;
+	}
+
+	for (i = start_idx; i <= end_idx; i++) {
+		pmap_kenter((vm_offset_t) shared + i * PAGE_SIZE,
+		    resume_frames + i * PAGE_SIZE);
+	}
 
 	return (0);
 }
 
+int
+gnttab_resume(void)
+{
+	int error;
+	unsigned int max_nr_gframes, nr_gframes;
+
+	nr_gframes = nr_grant_frames;
+	max_nr_gframes = max_nr_grant_frames();
+	if (max_nr_gframes < nr_gframes)
+		return (ENOSYS);
+
+	if (!resume_frames) {
+		error = xenpci_alloc_space(PAGE_SIZE * max_nr_gframes,
+		    &resume_frames);
+		if (error) {
+			printf("error mapping gnttab share frames\n");
+			return (error);
+		}
+	}
+
+	return (gnttab_map(0, nr_gframes - 1));
+}
+
+#endif
+
 static int
 gnttab_expand(unsigned int req_entries)
 {
-	int rc;
+	int error;
 	unsigned int cur, extra;
 
 	cur = nr_grant_frames;
@@ -538,10 +604,11 @@ gnttab_expand(unsigned int req_entries)
 	if (cur + extra > max_nr_grant_frames())
 		return (ENOSPC);
 
-	if ((rc = gnttab_map(cur, cur + extra - 1)) == 0)
-		rc = grow_gnttab_list(extra);
+	error = gnttab_map(cur, cur + extra - 1);
+	if (!error)
+		error = grow_gnttab_list(extra);
 
-	return rc;
+	return (error);
 }
 
 int 
@@ -552,7 +619,7 @@ gnttab_init()
 	unsigned int nr_init_grefs;
 
 	if (!is_running_on_xen())
-		return -ENODEV;
+		return (ENODEV);
 
 	nr_grant_frames = 1;
 	boot_max_nr_grant_frames = __max_nr_grant_frames();
@@ -571,7 +638,8 @@ gnttab_init()
 		return (ENOMEM);
 
 	for (i = 0; i < nr_grant_frames; i++) {
-		gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+		gnttab_list[i] = (grant_ref_t *)
+			malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
 		if (gnttab_list[i] == NULL)
 			goto ini_nomem;
 	}
@@ -588,8 +656,10 @@ gnttab_init()
 	gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
 	gnttab_free_head  = NR_RESERVED_ENTRIES;
 
-	printk("Grant table initialized\n");
-	return 0;
+	if (bootverbose)
+		printf("Grant table initialized\n");
+
+	return (0);
 
 ini_nomem:
 	for (i--; i >= 0; i--)

Modified: user/dfr/xenhvm/7/sys/xen/gnttab.h
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/gnttab.h	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/gnttab.h	Mon Feb 16 17:16:26 2009	(r188684)
@@ -36,10 +36,12 @@
 
 #ifndef __ASM_GNTTAB_H__
 
+#include <xen/interface/grant_table.h>
+
 #include <xen/hypervisor.h>
 #include <xen/interface/grant_table.h>
 #include <machine/xen/xen-os.h>
-#include <machine/xen/features.h>
+#include <xen/features.h>
 
 struct gnttab_free_callback {
 	struct gnttab_free_callback *next;
@@ -50,6 +52,10 @@ struct gnttab_free_callback {
 
 int gnttab_init(void);
 
+/*
+ * Allocate a grant table reference and return it in *result. Returns
+ * zero on success or errno on error.
+ */
 int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
     int flags, grant_ref_t *result);
 
@@ -68,7 +74,7 @@ int gnttab_end_foreign_access_ref(grant_
  */
 void gnttab_end_foreign_access(grant_ref_t ref, void *page);
 
-int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
+int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn, grant_ref_t *result);
 
 unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
 unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
@@ -104,6 +110,10 @@ void gnttab_grant_foreign_transfer_ref(g
 int gnttab_suspend(void);
 int gnttab_resume(void);
 
+#if 0
+
+#include <xen/features.h>
+
 static inline void
 gnttab_set_map_op(struct gnttab_map_grant_ref *map, vm_paddr_t addr,
 		  uint32_t flags, grant_ref_t ref, domid_t domid)
@@ -149,5 +159,6 @@ gnttab_set_replace_op(struct gnttab_unma
 
 	unmap->handle = handle;
 }
+#endif
 
 #endif /* __ASM_GNTTAB_H__ */

Modified: user/dfr/xenhvm/7/sys/xen/hypervisor.h
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/hypervisor.h	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/hypervisor.h	Mon Feb 16 17:16:26 2009	(r188684)
@@ -6,11 +6,19 @@
  * Copyright (c) 2002, K A Fraser
  */
 
-#ifndef __HYPERVISOR_H__
-#define __HYPERVISOR_H__
+#ifndef __XEN_HYPERVISOR_H__
+#define __XEN_HYPERVISOR_H__
+
+#ifdef XENHVM
+
+#define is_running_on_xen()	(HYPERVISOR_shared_info != NULL)
+
+#else
 
 #define is_running_on_xen() 1
 
+#endif
+
 #ifdef PAE
 #ifndef CONFIG_X86_PAE
 #define CONFIG_X86_PAE
@@ -25,6 +33,7 @@
 #include <xen/interface/physdev.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/callback.h>
+#include <xen/interface/memory.h>
 #include <machine/xen/hypercall.h>
 
 #if defined(__amd64__)
@@ -129,7 +138,7 @@ MULTI_update_va_mapping(
     mcl->op = __HYPERVISOR_update_va_mapping;
     mcl->args[0] = va;
 #if defined(__amd64__)
-    mcl->args[1] = new_val.pte;
+    mcl->args[1] = new_val;
 #elif defined(PAE)
     mcl->args[1] = (uint32_t)(new_val & 0xffffffff) ;
     mcl->args[2] = (uint32_t)(new_val >> 32);
@@ -140,4 +149,4 @@ MULTI_update_va_mapping(
     mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
 }
 
-#endif /* __HYPERVISOR_H__ */
+#endif /* __XEN_HYPERVISOR_H__ */

Added: user/dfr/xenhvm/7/sys/xen/reboot.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/dfr/xenhvm/7/sys/xen/reboot.c	Mon Feb 16 17:16:26 2009	(r188684)
@@ -0,0 +1,262 @@
+/*
+ *
+ * Copyright (c) 2004 Christian Limpach.
+ * Copyright (c) 2004-2006,2008 Kip Macy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christian Limpach.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+
+#include <machine/xen/xen-os.h>
+#include <xen/hypervisor.h>
+#include <xen/gnttab.h>
+#include <xen/xen_intr.h>
+#include <xen/xenbus/xenbusvar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#ifdef XENHVM
+
+#include <dev/xen/xenpci/xenpcivar.h>
+
+#else
+
+static void xen_suspend(void);
+
+#endif
+
+static void 
+shutdown_handler(struct xenbus_watch *watch,
+		 const char **vec, unsigned int len)
+{
+	char *str;
+	struct xenbus_transaction xbt;
+	int error, howto;
+	
+	howto = 0;
+
+ again:
+	error = xenbus_transaction_start(&xbt);
+	if (error)
+		return;
+
+	error = xenbus_read(xbt, "control", "shutdown", NULL, (void **) &str);
+
+	/* Ignore read errors and empty reads. */
+	if (error || strlen(str) == 0) {
+		xenbus_transaction_end(xbt, 1);
+		return;
+	}
+
+	xenbus_write(xbt, "control", "shutdown", "");
+
+	error = xenbus_transaction_end(xbt, 0);
+	if (error == EAGAIN) {
+		free(str, M_DEVBUF);
+		goto again;
+	}
+
+	if (strcmp(str, "reboot") == 0)
+		howto = 0;
+	else if (strcmp(str, "poweroff") == 0)
+		howto |= (RB_POWEROFF | RB_HALT);
+	else if (strcmp(str, "halt") == 0)
+#ifdef XENHVM
+		/*
+		 * We rely on acpi powerdown to halt the VM.
+		 */
+		howto |= (RB_POWEROFF | RB_HALT);
+#else
+		howto |= RB_HALT;
+#endif
+	else if (strcmp(str, "suspend") == 0)
+		howto = -1;
+	else {
+		printf("Ignoring shutdown request: %s\n", str);
+		goto done;
+	}
+
+	if (howto == -1) {
+		xen_suspend();
+		goto done;
+	}
+
+	shutdown_nice(howto);
+ done:
+	free(str, M_DEVBUF);
+}
+
+#ifndef XENHVM
+
+/*
+ * In HV mode, we let acpi take care of halts and reboots.
+ */
+
+static void
+xen_shutdown_final(void *arg, int howto)
+{
+
+	if (howto & (RB_HALT | RB_POWEROFF))
+		HYPERVISOR_shutdown(SHUTDOWN_poweroff);
+	else
+		HYPERVISOR_shutdown(SHUTDOWN_reboot);
+}
+
+#endif
+
+static struct xenbus_watch shutdown_watch = {
+	.node = "control/shutdown",
+	.callback = shutdown_handler
+};
+
+static void
+setup_shutdown_watcher(void *unused)
+{
+
+	if (register_xenbus_watch(&shutdown_watch))
+		printf("Failed to set shutdown watcher\n");
+#ifndef XENHVM
+	EVENTHANDLER_REGISTER(shutdown_final, xen_shutdown_final, NULL,
+	    SHUTDOWN_PRI_LAST);
+#endif
+}
+
+SYSINIT(shutdown, SI_SUB_PSEUDO, SI_ORDER_ANY, setup_shutdown_watcher, NULL);
+
+#ifndef XENHVM
+
+extern void xencons_suspend(void);
+extern void xencons_resume(void);
+
+static void 
+xen_suspend()
+{
+	int i, j, k, fpp;
+	unsigned long max_pfn, start_info_mfn;
+
+#ifdef SMP
+	cpumask_t map;
+	/*
+	 * Bind us to CPU 0 and stop any other VCPUs.
+	 */
+	mtx_lock_spin(&sched_lock);
+	sched_bind(curthread, 0);
+	mtx_unlock_spin(&sched_lock);
+	KASSERT(PCPU_GET(cpuid) == 0, ("xen_suspend: not running on cpu 0"));
+
+	map = PCPU_GET(other_cpus) & ~stopped_cpus;
+	if (map)
+		stop_cpus(map);
+#endif
+
+	if (DEVICE_SUSPEND(root_bus) != 0) {
+		printf("xen_suspend: device_suspend failed\n");
+		if (map)
+			restart_cpus(map);
+		return;
+	}
+
+	local_irq_disable();
+
+	xencons_suspend();
+	gnttab_suspend();
+
+	max_pfn = HYPERVISOR_shared_info->arch.max_pfn;
+
+	void *shared_info = HYPERVISOR_shared_info;
+	HYPERVISOR_shared_info = NULL;
+	pmap_kremove((vm_offset_t) shared_info);
+	PT_UPDATES_FLUSH();
+
+	xen_start_info->store_mfn = MFNTOPFN(xen_start_info->store_mfn);
+	xen_start_info->console.domU.mfn = MFNTOPFN(xen_start_info->console.domU.mfn);
+
+	/*
+	 * We'll stop somewhere inside this hypercall. When it returns,
+	 * we'll start resuming after the restore.
+	 */
+	start_info_mfn = VTOMFN(xen_start_info);
+	pmap_suspend();
+	HYPERVISOR_suspend(start_info_mfn);
+	pmap_resume();
+
+	pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info);
+	HYPERVISOR_shared_info = shared_info;
+
+	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+		VTOMFN(xen_pfn_to_mfn_frame_list_list);
+  
+	fpp = PAGE_SIZE/sizeof(unsigned long);
+	for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
+		if ((j % fpp) == 0) {
+			k++;
+			xen_pfn_to_mfn_frame_list_list[k] = 
+				VTOMFN(xen_pfn_to_mfn_frame_list[k]);
+			j = 0;
+		}
+		xen_pfn_to_mfn_frame_list[k][j] = 
+			VTOMFN(&xen_phys_machine[i]);
+	}
+	HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+
+	gnttab_resume();
+	irq_resume();
+	local_irq_enable();
+	xencons_resume();
+
+#ifdef CONFIG_SMP
+	for_each_cpu(i)
+		vcpu_prepare(i);
+
+#endif
+	/* 
+	 * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
+	 * the VCPU hotplug callback can race with our vcpu_prepare
+	 */
+	DEVICE_RESUME(root_bus);
+
+#ifdef SMP
+	sched_unbind(curthread);
+	if (map)
+		restart_cpus(map);
+#endif
+}
+
+#endif

Modified: user/dfr/xenhvm/7/sys/xen/xen_intr.h
==============================================================================
--- user/dfr/xenhvm/7/sys/xen/xen_intr.h	Mon Feb 16 17:13:00 2009	(r188683)
+++ user/dfr/xenhvm/7/sys/xen/xen_intr.h	Mon Feb 16 17:16:26 2009	(r188684)
@@ -29,37 +29,62 @@
 #define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
 #define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
 
-/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
-extern void unbind_from_irq(int irq);
-
+/* 
+ * Dynamic binding of event channels and VIRQ sources to guest IRQ space.
+ */
+
+/*
+ * Bind a caller port event channel to an interrupt handler. If
+ * successful, the guest IRQ number is returned in *irqp. Return zero
+ * on success or errno otherwise.
+ */
 extern int bind_caller_port_to_irqhandler(unsigned int caller_port,
 	const char *devname, driver_intr_t handler, void *arg,
 	unsigned long irqflags, unsigned int *irqp);
+
+/*
+ * Bind a listening port to an interrupt handler. If successful, the
+ * guest IRQ number is returned in *irqp. Return zero on success or
+ * errno otherwise.
+ */
 extern int bind_listening_port_to_irqhandler(unsigned int remote_domain,
-	const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags,
-	unsigned int *irqp);
+	const char *devname, driver_intr_t handler, void *arg,
+	unsigned long irqflags, unsigned int *irqp);
+
+/*
+ * Bind a VIRQ to an interrupt handler. If successful, the guest IRQ
+ * number is returned in *irqp. Return zero on success or errno
+ * otherwise.
+ */
 extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
-	const char *devname, driver_filter_t filter, driver_intr_t handler,
+	const char *devname, driver_intr_t handler,
 	unsigned long irqflags,	unsigned int *irqp);
-extern int bind_ipi_to_irqhandler(unsigned int ipi,
-	unsigned int cpu,
-	const char *devname,
-	driver_filter_t handler,
-	unsigned long irqflags,
-	unsigned int *irqp);
 
-extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
-	                                             unsigned int remote_port,
-	                                             const char *devname,
-	                                             driver_filter_t filter,
-	                                             driver_intr_t handler,
-	                                             unsigned long irqflags,
-	                                             unsigned int *irqp);
+/*
+ * Bind an IPI to an interrupt handler. If successful, the guest
+ * IRQ number is returned in *irqp. Return zero on success or errno
+ * otherwise.
+ */
+extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu,
+	const char *devname, driver_intr_t handler,
+	unsigned long irqflags, unsigned int *irqp);
 
+/*
+ * Bind an interdomain event channel to an interrupt handler. If
+ * successful, the guest IRQ number is returned in *irqp. Return zero
+ * on success or errno otherwise.
+ */
+extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
+	unsigned int remote_port, const char *devname, driver_intr_t handler,
+	unsigned long irqflags, unsigned int *irqp);
 
+/*
+ * Unbind an interrupt handler using the guest IRQ number returned
+ * when it was bound.
+ */
+extern void unbind_from_irqhandler(unsigned int irq);
 
-extern void unbind_from_irqhandler(unsigned int evtchn);
-static __inline__ int irq_cannonicalize(int irq)
+static __inline__ int irq_cannonicalize(unsigned int irq)
 {
     return (irq == 2) ? 9 : irq;
 }


More information about the svn-src-user mailing list