svn commit: r185803 - in user/dfr/xenhvm/6/sys: conf dev/xen/blkfront dev/xen/console dev/xen/netfront dev/xen/xenpci i386/include/xen i386/xen xen xen/xenbus

Doug Rabson dfr at FreeBSD.org
Tue Dec 9 09:47:07 PST 2008


Author: dfr
Date: Tue Dec  9 17:47:05 2008
New Revision: 185803
URL: http://svn.freebsd.org/changeset/base/185803

Log:
  Add support for suspend and resume. This currently only works for 64bit HV
  mode kernels. A 32bit PV mode kernel will suspend but fails to restore because
  Xen gets confused by the magic recursive mappings in the virtual address space.

Added:
  user/dfr/xenhvm/6/sys/dev/xen/xenpci/machine_reboot.c
Modified:
  user/dfr/xenhvm/6/sys/conf/files
  user/dfr/xenhvm/6/sys/dev/xen/blkfront/blkfront.c
  user/dfr/xenhvm/6/sys/dev/xen/console/xencons_ring.c
  user/dfr/xenhvm/6/sys/dev/xen/netfront/netfront.c
  user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c
  user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c
  user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h
  user/dfr/xenhvm/6/sys/i386/include/xen/xenvar.h
  user/dfr/xenhvm/6/sys/i386/xen/clock.c
  user/dfr/xenhvm/6/sys/i386/xen/mp_machdep.c
  user/dfr/xenhvm/6/sys/i386/xen/xen_machdep.c
  user/dfr/xenhvm/6/sys/xen/reboot.c
  user/dfr/xenhvm/6/sys/xen/xenbus/xenbus_probe.c

Modified: user/dfr/xenhvm/6/sys/conf/files
==============================================================================
--- user/dfr/xenhvm/6/sys/conf/files	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/conf/files	Tue Dec  9 17:47:05 2008	(r185803)
@@ -2069,6 +2069,7 @@ dev/xen/netfront/netfront.c    optional 
 xen/gnttab.c                    optional xenhvm
 xen/features.c                  optional xenhvm
 dev/xen/xenpci/evtchn.c         optional xenhvm
+dev/xen/xenpci/machine_reboot.c optional xenhvm
 xen/evtchn/evtchn_dev.c         optional xenhvm
 xen/reboot.c			optional xenhvm
 xen/xenbus/xenbus_client.c      optional xenhvm

Modified: user/dfr/xenhvm/6/sys/dev/xen/blkfront/blkfront.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/blkfront/blkfront.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/blkfront/blkfront.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -377,13 +377,12 @@ blkfront_resume(device_t dev)
 
 	DPRINTK("blkfront_resume: %s\n", xenbus_get_node(dev));
 
-	blkif_free(info, 1);
-
+	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
 	err = talk_to_backend(dev, info);
-	if (!err)
+	if (info->connected == BLKIF_STATE_SUSPENDED && !err)
 		blkif_recover(info);
 
-	return err;
+	return (err);
 }
 
 /* Common code used when first setting up, and when resuming. */
@@ -427,7 +426,7 @@ talk_to_backend(device_t dev, struct blk
 
 	err = xenbus_transaction_end(xbt, 0);
 	if (err) {
-		if (err == -EAGAIN)
+		if (err == EAGAIN)
 			goto again;
 		xenbus_dev_fatal(dev, err, "completing transaction");
 		goto destroy_blkring;

Modified: user/dfr/xenhvm/6/sys/dev/xen/console/xencons_ring.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/console/xencons_ring.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/console/xencons_ring.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -26,6 +26,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/xen/console/xencons_ring.h>
 
 #define console_evtchn	console.domU.evtchn
+static unsigned int console_irq;
 extern char *console_page;
  
 static inline struct xencons_interface *
@@ -118,14 +119,17 @@ xencons_ring_init(void)
 
 	err = bind_caller_port_to_irqhandler(xen_start_info->console_evtchn,
 		"xencons", xencons_handle_input, NULL,
-		INTR_TYPE_MISC | INTR_MPSAFE, NULL);
+		INTR_TYPE_MISC | INTR_MPSAFE, &console_irq);
 	if (err) {
 		return err;
 	}
 
 	return 0;
 }
-#ifdef notyet
+
+extern void xencons_suspend(void);
+extern void xencons_resume(void);
+
 void 
 xencons_suspend(void)
 {
@@ -133,7 +137,7 @@ xencons_suspend(void)
 	if (!xen_start_info->console_evtchn)
 		return;
 
-	unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn, NULL);
+	unbind_from_irqhandler(console_irq);
 }
 
 void 
@@ -142,7 +146,7 @@ xencons_resume(void)
 
 	(void)xencons_ring_init();
 }
-#endif
+
 /*
  * Local variables:
  * mode: C

Modified: user/dfr/xenhvm/6/sys/dev/xen/netfront/netfront.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/netfront/netfront.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/netfront/netfront.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -430,13 +430,11 @@ netfront_attach(device_t dev)
  * leave the device-layer structures intact so that this is transparent to the
  * rest of the kernel.
  */
-static int 
+static int
 netfront_resume(device_t dev)
 {
 	struct netfront_info *info = device_get_softc(dev);
-	
-	DPRINTK("%s\n", xenbus_get_node(dev));
-	
+
 	netif_disconnect_backend(info);
 	return (0);
 }
@@ -576,9 +574,6 @@ setup_device(device_t dev, struct netfro
 	if (error)
 		goto fail;
 
-#if 0	
-	network_connect(info);
-#endif
 	error = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
 		"xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, &info->irq);
 
@@ -1596,6 +1591,7 @@ network_connect(struct netfront_info *np
 	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
 	for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
 		struct mbuf *m;
+		u_long pfn;
 
 		if (np->rx_mbufs[i] == NULL)
 			continue;
@@ -1603,15 +1599,16 @@ network_connect(struct netfront_info *np
 		m = np->rx_mbufs[requeue_idx] = xennet_get_rx_mbuf(np, i);
 		ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
 		req = RING_GET_REQUEST(&np->rx, requeue_idx);
+		pfn = vtophys(mtod(m, vm_offset_t)) >> PAGE_SHIFT;
 
 		if (!np->copying_receiver) {
 			gnttab_grant_foreign_transfer_ref(ref,
 			    xenbus_get_otherend_id(np->xbdev),
-			    vtophys(mtod(m, vm_offset_t)));
+			    pfn);
 		} else {
 			gnttab_grant_foreign_access_ref(ref,
 			    xenbus_get_otherend_id(np->xbdev),
-			    vtophys(mtod(m, vm_offset_t)), 0);
+			    PFNTOMFN(pfn), 0);
 		}
 		req->gref = ref;
 		req->id   = requeue_idx;
@@ -1786,7 +1783,12 @@ static void netif_free(struct netfront_i
 
 static void netif_disconnect_backend(struct netfront_info *info)
 {
-	xn_stop(info);
+	XN_RX_LOCK(info);
+	XN_TX_LOCK(info);
+	netfront_carrier_off(info);
+	XN_TX_UNLOCK(info);
+	XN_RX_UNLOCK(info);
+
 	end_access(info->tx_ring_ref, info->tx.sring);
 	end_access(info->rx_ring_ref, info->rx.sring);
 	info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1794,12 +1796,8 @@ static void netif_disconnect_backend(str
 	info->tx.sring = NULL;
 	info->rx.sring = NULL;
 
-#if 0
 	if (info->irq)
 		unbind_from_irqhandler(info->irq);
-#else 
-	panic("FIX ME");
-#endif
 	info->irq = 0;
 }
 

Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -75,6 +75,7 @@ static int evtchn_to_irq[NR_EVENT_CHANNE
 	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
 
 static struct mtx irq_alloc_lock;
+static device_t xenpci_device;
 
 #define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
 
@@ -317,7 +318,7 @@ evtchn_interrupt(void *arg)
 			handler = irq_evtchn[irq].handler;
 			handler_arg = irq_evtchn[irq].arg;
 			if (unlikely(handler == NULL)) {
-				printk("Xen IRQ%d (port %d) has no handler!\n",
+				printf("Xen IRQ%d (port %d) has no handler!\n",
 				       irq, port);
 				mtx_unlock(&irq_evtchn[irq].lock);
 				continue;
@@ -345,8 +346,27 @@ evtchn_interrupt(void *arg)
 	}
 }
 
-void irq_resume(void)
+void
+irq_suspend(void)
 {
+	struct xenpci_softc *scp = device_get_softc(xenpci_device);
+
+	/*
+	 * Take our interrupt handler out of the list of handlers
+	 * that can handle this irq.
+	 */
+	if (scp->intr_cookie != NULL) {
+		if (BUS_TEARDOWN_INTR(device_get_parent(xenpci_device),
+			xenpci_device, scp->res_irq, scp->intr_cookie) != 0)
+			printf("intr teardown failed.. continuing\n");
+		scp->intr_cookie = NULL;
+	}
+}
+
+void
+irq_resume(void)
+{
+	struct xenpci_softc *scp = device_get_softc(xenpci_device);
 	int evtchn, irq;
 
 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) {
@@ -356,6 +376,10 @@ void irq_resume(void)
 
 	for (irq = 0; irq < ARRAY_SIZE(irq_evtchn); irq++)
 		irq_evtchn[irq].evtchn = 0;
+
+	BUS_SETUP_INTR(device_get_parent(xenpci_device),
+	    xenpci_device, scp->res_irq, INTR_TYPE_MISC,
+	    evtchn_interrupt, NULL, &scp->intr_cookie);
 }
 
 int
@@ -380,5 +404,7 @@ xenpci_irq_init(device_t device, struct 
 	if (error)
 		return (error);
 
+	xenpci_device = device;
+
 	return (0);
 }

Added: user/dfr/xenhvm/6/sys/dev/xen/xenpci/machine_reboot.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/machine_reboot.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -0,0 +1,125 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: user/dfr/xenhvm/6/sys/xen/evtchn/evtchn.c 184235 2008-10-25 00:25:25Z kmacy $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/interrupt.h>
+#include <sys/pcpu.h>
+
+#include <machine/xen/xen-os.h>
+#include <machine/xen/xenvar.h>
+#include <xen/hypervisor.h>
+#include <xen/xen_intr.h>
+#include <xen/evtchn.h>
+#include <sys/smp.h>
+
+#include <dev/xen/xenpci/xenpcivar.h>
+
+struct ap_suspend_info {
+	int      do_spin;
+	atomic_t nr_spinning;
+};
+
+#ifdef CONFIG_SMP
+
+/*
+ * Spinning prevents, for example, APs touching grant table entries while
+ * the shared grant table is not mapped into the address space imemdiately
+ * after resume.
+ */
+static void ap_suspend(void *_info)
+{
+	struct ap_suspend_info *info = _info;
+
+	BUG_ON(!irqs_disabled());
+
+	atomic_inc(&info->nr_spinning);
+	mb();
+
+	while (info->do_spin)
+		cpu_relax();
+
+	mb();
+	atomic_dec(&info->nr_spinning);
+}
+
+#define initiate_ap_suspend(i)	smp_call_function(ap_suspend, i, 0, 0)
+
+#else /* !defined(CONFIG_SMP) */
+
+#define initiate_ap_suspend(i)	0
+
+#endif
+
+static int bp_suspend(void)
+{
+	int suspend_cancelled;
+
+	suspend_cancelled = HYPERVISOR_suspend(0);
+	if (!suspend_cancelled)
+		xenpci_resume();
+
+	return suspend_cancelled;
+}
+
+void
+xen_suspend()
+{
+	int suspend_cancelled;
+	//struct ap_suspend_info info;
+
+	if (DEVICE_SUSPEND(root_bus)) {
+		printf("xen_suspend: device_suspend failed\n");
+		return;
+	}
+
+	critical_enter();
+
+	/* Prevent any races with evtchn_interrupt() handler. */
+	irq_suspend();
+
+#if 0
+	info.do_spin = 1;
+	atomic_set(&info.nr_spinning, 0);
+	smp_mb();
+
+	nr_cpus = num_online_cpus() - 1;
+
+	err = initiate_ap_suspend(&info);
+	if (err < 0) {
+		critical_exit();
+		//xenbus_suspend_cancel();
+		return err;
+	}
+
+	while (atomic_read(&info.nr_spinning) != nr_cpus)
+		cpu_relax();
+#endif
+
+	disable_intr();
+	suspend_cancelled = bp_suspend();
+	//resume_notifier(suspend_cancelled);
+	enable_intr();
+
+#if 0
+	smp_mb();
+	info.do_spin = 0;
+	while (atomic_read(&info.nr_spinning) != 0)
+		cpu_relax();
+#endif
+
+	critical_exit();
+
+	if (!suspend_cancelled)
+		DEVICE_RESUME(root_bus);
+#if 0
+	else
+		xenbus_suspend_cancel();
+#endif
+}

Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/xen/xen-os.h>
 #include <xen/features.h>
 #include <xen/hypervisor.h>
+#include <xen/gnttab.h>
+#include <xen/xen_intr.h>
 #include <xen/interface/memory.h>
 #include <xen/interface/hvm/params.h>
 
@@ -63,6 +65,7 @@ __FBSDID("$FreeBSD$");
  */
 char *hypercall_stubs;
 shared_info_t *HYPERVISOR_shared_info;
+static vm_paddr_t shared_info_pa;
 
 /*
  * The softc is automatically allocated by the parent bus using the
@@ -75,7 +78,6 @@ static int xenpci_deallocate_resources(d
 static int xenpci_allocate_resources(device_t device);
 static int xenpci_attach(device_t device, struct xenpci_softc *scp);
 static int xenpci_detach(device_t device, struct xenpci_softc *scp);
-static int xenpci_resume(device_t device, struct xenpci_softc *scp);
 
 static int xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz,
     u_long *pa);
@@ -155,9 +157,8 @@ xenpci_pci_detach (device_t device)
 static int
 xenpci_pci_resume(device_t device)
 {
-	struct xenpci_softc *scp = DEVICE2SOFTC(device);
 
-        return (xenpci_resume(device, scp));
+	return (bus_generic_resume(device));
 }
 
 /*
@@ -251,7 +252,6 @@ xenpci_attach(device_t device, struct xe
 {
 	struct xen_add_to_physmap xatp;
 	vm_offset_t shared_va;
-	vm_paddr_t shared_pa;
 
 	if (xenpci_allocate_resources(device))
 		goto errexit;
@@ -263,17 +263,17 @@ xenpci_attach(device_t device, struct xe
 
 	setup_xen_features();
 
-	xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_pa); 
+	xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa); 
 
 	xatp.domid = DOMID_SELF;
 	xatp.idx = 0;
 	xatp.space = XENMAPSPACE_shared_info;
-	xatp.gpfn = shared_pa >> PAGE_SHIFT;
+	xatp.gpfn = shared_info_pa >> PAGE_SHIFT;
 	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
 		panic("HYPERVISOR_memory_op failed");
 
 	shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
-	pmap_kenter(shared_va, shared_pa);
+	pmap_kenter(shared_va, shared_info_pa);
 	HYPERVISOR_shared_info = (void *) shared_va;
 
 	/*
@@ -316,13 +316,6 @@ xenpci_detach(device_t device, struct xe
 }
 
 static int
-xenpci_resume(device_t device, struct xenpci_softc *scp)
-{
-
-	xenpci_resume_hypercall_stubs(device, scp);
-}
-
-static int
 xenpci_allocate_resources(device_t device)
 {
 	int error;
@@ -412,11 +405,26 @@ xenpci_alloc_space(size_t sz, vm_paddr_t
 }
 
 void
-printk(const char *fmt, ...)
+xenpci_resume()
 {
-        __va_list ap;
+	device_t device = devclass_get_device(xenpci_devclass, 0);
+	struct xenpci_softc *scp = DEVICE2SOFTC(device);
+	struct xen_add_to_physmap xatp;
+
+	xenpci_resume_hypercall_stubs(device, scp);
 
-        va_start(ap, fmt);
-        vprintf(fmt, ap);
-        va_end(ap);
+	xatp.domid = DOMID_SELF;
+	xatp.idx = 0;
+	xatp.space = XENMAPSPACE_shared_info;
+	xatp.gpfn = shared_info_pa >> PAGE_SHIFT;
+	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+		panic("HYPERVISOR_memory_op failed");
+
+	pmap_kenter((vm_offset_t) HYPERVISOR_shared_info, shared_info_pa);
+
+	xenpci_set_callback(device);
+
+	gnttab_resume();
+	irq_resume();
 }
+

Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h	Tue Dec  9 17:47:05 2008	(r185803)
@@ -41,3 +41,5 @@ struct xenpci_softc {
 
 extern int xenpci_irq_init(device_t device, struct xenpci_softc *scp);
 extern int xenpci_alloc_space(size_t sz, vm_paddr_t *pa);
+extern void xenpci_resume(void);
+extern void xen_suspend(void);

Modified: user/dfr/xenhvm/6/sys/i386/include/xen/xenvar.h
==============================================================================
--- user/dfr/xenhvm/6/sys/i386/include/xen/xenvar.h	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/i386/include/xen/xenvar.h	Tue Dec  9 17:47:05 2008	(r185803)
@@ -39,6 +39,8 @@ extern int xendebug_flags;
 #endif
 
 extern	xen_pfn_t *xen_phys_machine;
+extern	xen_pfn_t *xen_pfn_to_mfn_frame_list[16];
+extern	xen_pfn_t *xen_pfn_to_mfn_frame_list_list;
 
 #if 0
 #define TRACE_ENTER XENPRINTF("(file=%s, line=%d) entered %s\n", __FILE__, __LINE__, __FUNCTION__)

Modified: user/dfr/xenhvm/6/sys/i386/xen/clock.c
==============================================================================
--- user/dfr/xenhvm/6/sys/i386/xen/clock.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/i386/xen/clock.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -131,7 +131,7 @@ static u_char timer2_state = RELEASED;
 static struct timespec shadow_tv;
 static uint32_t shadow_tv_version;	/* XXX: lazy locking */
 static uint64_t processed_system_time;	/* stime (ns) at last processing. */
-
+static unsigned int time_irq;
 
 #ifdef XEN_PRIVILEGED_GUEST
 static struct mtx clock_lock;
@@ -839,23 +839,25 @@ static struct vcpu_set_periodic_timer xe
 void
 cpu_initclocks(void)
 {
-	int time_irq;
 
 	xen_set_periodic_tick.period_ns = NS_PER_TICK;
 
 	HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
 			   &xen_set_periodic_tick);
 
-        if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk", 
-		    (driver_intr_t *)clkintr, INTR_TYPE_CLK | INTR_FAST,
-		    NULL)) < 0) {
+	if (time_irq)
+		unbind_from_irqhandler(time_irq);
+	time_irq = 0;
+
+        if (bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk", 
+		(driver_intr_t *)clkintr, INTR_TYPE_CLK | INTR_FAST,
+		&time_irq)) {
 		panic("failed to register clock interrupt\n");
 	}
 
 	/* should fast clock be enabled ? */
 }
 
-
 int
 ap_cpu_initclocks(int cpu)
 {

Modified: user/dfr/xenhvm/6/sys/i386/xen/mp_machdep.c
==============================================================================
--- user/dfr/xenhvm/6/sys/i386/xen/mp_machdep.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/i386/xen/mp_machdep.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -567,7 +567,7 @@ xen_smp_intr_init(unsigned int cpu)
 	    INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE, &pc->pc_resched_irq);
 
 	printf("cpu=%d irq=%d vector=%d\n",
-	    cpu, rc, RESCHEDULE_VECTOR);
+	    cpu, pc->pc_resched_irq, RESCHEDULE_VECTOR);
 	
 	sprintf(callfunc_name[cpu], "callfunc%u", cpu);
 	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, cpu,
@@ -578,7 +578,7 @@ xen_smp_intr_init(unsigned int cpu)
 		goto fail;
 
 	printf("cpu=%d irq=%d vector=%d\n",
-	    cpu, rc, CALL_FUNCTION_VECTOR);
+	    cpu, pc->pc_callfunc_irq, CALL_FUNCTION_VECTOR);
 
 	if ((cpu != 0) && ((rc = ap_cpu_initclocks(cpu)) != 0))
 		goto fail;

Modified: user/dfr/xenhvm/6/sys/i386/xen/xen_machdep.c
==============================================================================
--- user/dfr/xenhvm/6/sys/i386/xen/xen_machdep.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/i386/xen/xen_machdep.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -88,6 +88,8 @@ start_info_t *xen_start_info;
 shared_info_t *HYPERVISOR_shared_info;
 xen_pfn_t *xen_machine_phys = machine_to_phys_mapping;
 xen_pfn_t *xen_phys_machine;
+xen_pfn_t *xen_pfn_to_mfn_frame_list[16];
+xen_pfn_t *xen_pfn_to_mfn_frame_list_list;
 int preemptable, init_first;
 extern unsigned int avail_space;
 
@@ -842,6 +844,39 @@ shift_phys_machine(unsigned long *phys_m
 }
 #endif /* ADD_ISA_HOLE */
 
+/*
+ * Build a directory of the pages that make up our Physical to Machine
+ * mapping table. The Xen suspend/restore code uses this to find our
+ * mapping table.
+ */
+static void
+init_frame_list_list(void *arg)
+{
+	unsigned long nr_pages = xen_start_info->nr_pages;
+#define FPP	(PAGE_SIZE/sizeof(xen_pfn_t))
+	int i, j, k;
+
+	xen_pfn_to_mfn_frame_list_list = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
+	for (i = 0, j = 0, k = -1; i < nr_pages;
+	     i += FPP, j++) {
+		if ((j & (FPP - 1)) == 0) {
+			k++;
+			xen_pfn_to_mfn_frame_list[k] =
+				malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
+			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 = nr_pages;
+	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list
+		= VTOMFN(xen_pfn_to_mfn_frame_list_list);
+}	
+SYSINIT(init_fll, SI_SUB_DEVFS, SI_ORDER_ANY, init_frame_list_list, NULL);
+
 extern unsigned long physfree;
 
 int pdir, curoffset;
@@ -975,7 +1010,7 @@ initvalues(start_info_t *startinfo)
 	IdlePTDnew = (pd_entry_t *)cur_space; cur_space += 4*PAGE_SIZE;
 	bzero(IdlePTDnew, 4*PAGE_SIZE);
 
-	for (i = 0; i < 4; i++) 
+	for (i = 0; i < 4; i++)
 		IdlePTDnewma[i] =
 		    xpmap_ptom(VTOP((uint8_t *)IdlePTDnew + i*PAGE_SIZE));
 	/*
@@ -1020,8 +1055,6 @@ initvalues(start_info_t *startinfo)
 	
 	PT_UPDATES_FLUSH();
 
-		
-
 	memcpy(((uint8_t *)IdlePTDnew) + ((unsigned int)(KERNBASE >> 18)),
 	    ((uint8_t *)IdlePTD) + ((KERNBASE >> 18) & PAGE_MASK),
 	    l1_pages*sizeof(pt_entry_t));
@@ -1082,14 +1115,12 @@ initvalues(start_info_t *startinfo)
 	
 	printk("#4\n");
 
-	
 	xen_store_ma = (((vm_paddr_t)xen_start_info->store_mfn) << PAGE_SHIFT);
 	PT_SET_MA(xen_store, xen_store_ma | PG_KERNEL);
 	console_page_ma = (((vm_paddr_t)xen_start_info->console.domU.mfn) << PAGE_SHIFT);
 	PT_SET_MA(console_page, console_page_ma | PG_KERNEL);
 
 	printk("#5\n");
-	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = (unsigned long)xen_phys_machine;
 
 	set_iopl.iopl = 1;
 	err = HYPERVISOR_physdev_op(PHYSDEVOP_SET_IOPL, &set_iopl);

Modified: user/dfr/xenhvm/6/sys/xen/reboot.c
==============================================================================
--- user/dfr/xenhvm/6/sys/xen/reboot.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/xen/reboot.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -34,13 +34,34 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
-#include <sys/systm.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)
@@ -91,22 +112,35 @@ shutdown_handler(struct xenbus_watch *wa
 		printf("Ignoring shutdown request: %s\n", str);
 		goto done;
 	}
-#ifdef notyet
-	if (howto == -1) {
-		do_suspend(NULL);
-		goto done;
-	}
-#else 
+
 	if (howto == -1) {
-		printf("suspend not currently supported\n");
+		xen_suspend();
 		goto done;
 	}
-#endif
+
 	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
@@ -118,80 +152,61 @@ 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);
 
-#ifdef notyet
+#ifndef XENHVM
+
+extern void xencons_suspend(void);
+extern void xencons_resume(void);
 
 static void 
-xen_suspend(void *ignore)
+xen_suspend()
 {
 	int i, j, k, fpp;
+	unsigned long max_pfn;
 
-	extern void time_resume(void);
-	extern unsigned long max_pfn;
-	extern unsigned long *pfn_to_mfn_frame_list_list;
-	extern unsigned long *pfn_to_mfn_frame_list[];
-
-#ifdef CONFIG_SMP
-#error "do_suspend must be run cpu 0 - need to create separate thread"
-	cpumask_t prev_online_cpus;
-	int vcpu_prepare(int vcpu);
-#endif
-
-	int err = 0;
-
-	PANIC_IF(smp_processor_id() != 0);
-
-#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
-	if (num_online_cpus() > 1) {
-		printk(KERN_WARNING "Can't suspend SMP guests "
-		       "without CONFIG_HOTPLUG_CPU\n");
-		return -EOPNOTSUPP;
-	}
-#endif
-
-	xenbus_suspend();
-
-#ifdef CONFIG_SMP
-	lock_cpu_hotplug();
+#ifdef SMP
+	cpumask_t map;
 	/*
-	 * Take all other CPUs offline. We hold the hotplug semaphore to
-	 * avoid other processes bringing up CPUs under our feet.
+	 * Bind us to CPU 0 and stop any other VCPUs.
 	 */
-	cpus_clear(prev_online_cpus);
-	while (num_online_cpus() > 1) {
-		for_each_online_cpu(i) {
-			if (i == 0)
-				continue;
-			unlock_cpu_hotplug();
-			err = cpu_down(i);
-			lock_cpu_hotplug();
-			if (err != 0) {
-				printk(KERN_CRIT "Failed to take all CPUs "
-				       "down: %d.\n", err);
-				goto out_reenable_cpus;
-			}
-			cpu_set(i, prev_online_cpus);
-		}
-	}
-#endif /* CONFIG_SMP */
+	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
 
-	preempt_disable();
+	if (DEVICE_SUSPEND(root_bus) != 0) {
+		printf("xen_suspend: device_suspend failed\n");
+		if (map)
+			restart_cpus(map);
+		return;
+	}
 
+	local_irq_disable();
 
-	__cli();
-	preempt_enable();
-#ifdef SMP
-	unlock_cpu_hotplug();
-#endif
+	xencons_suspend();
 	gnttab_suspend();
 
-	pmap_kremove(HYPERVISOR_shared_info);
+	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 = mfn_to_pfn(xen_start_info->store_mfn);
-	xen_start_info->console.domU.mfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
+	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,
@@ -199,38 +214,33 @@ xen_suspend(void *ignore)
 	 */
 	HYPERVISOR_suspend(VTOMFN(xen_start_info));
 
-	pmap_kenter_ma(HYPERVISOR_shared_info, xen_start_info->shared_info);
-	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+	pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info);
+	HYPERVISOR_shared_info = shared_info;
 
-#if 0
-	memset(empty_zero_page, 0, PAGE_SIZE);
-#endif     
 	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
-		VTOMFN(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++;
-			pfn_to_mfn_frame_list_list[k] = 
-				VTOMFN(pfn_to_mfn_frame_list[k]);
+			xen_pfn_to_mfn_frame_list_list[k] = 
+				VTOMFN(xen_pfn_to_mfn_frame_list[k]);
 			j = 0;
 		}
-		pfn_to_mfn_frame_list[k][j] = 
-			VTOMFN(&phys_to_machine_mapping[i]);
+		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();
-
-	time_resume();
-
-	__sti();
-
+	cpu_initclocks();
+	local_irq_enable();
 	xencons_resume();
 
+	printf("UP\n");
+
 #ifdef CONFIG_SMP
 	for_each_cpu(i)
 		vcpu_prepare(i);
@@ -240,21 +250,13 @@ xen_suspend(void *ignore)
 	 * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
 	 * the VCPU hotplug callback can race with our vcpu_prepare
 	 */
-	xenbus_resume();
+	DEVICE_RESUME(root_bus);
 
-#ifdef CONFIG_SMP
- out_reenable_cpus:
-	for_each_cpu_mask(i, prev_online_cpus) {
-		j = cpu_up(i);
-		if ((j != 0) && !cpu_online(i)) {
-			printk(KERN_CRIT "Failed to bring cpu "
-			       "%d back up (%d).\n",
-			       i, j);
-			err = j;
-		}
-	}
+#ifdef SMP
+	sched_unbind(curthread);
+	if (map)
+		restart_cpus(map);
 #endif
-	return err;
 }
 
-#endif /* notyet */
+#endif

Modified: user/dfr/xenhvm/6/sys/xen/xenbus/xenbus_probe.c
==============================================================================
--- user/dfr/xenhvm/6/sys/xen/xenbus/xenbus_probe.c	Tue Dec  9 17:47:00 2008	(r185802)
+++ user/dfr/xenhvm/6/sys/xen/xenbus/xenbus_probe.c	Tue Dec  9 17:47:05 2008	(r185803)
@@ -389,28 +389,90 @@ xenbus_attach(device_t dev)
 	return (0);
 }
 
-static void
+static int
 xenbus_suspend(device_t dev)
 {
+	int error;
+
 	DPRINTK("");
-	panic("implement me");
-#if 0
-	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
-	bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
-#endif
+
+	error = bus_generic_suspend(dev);
+	if (error)
+		return (error);
+
 	xs_suspend();
+
+	return (0);
 }
 
-static void
+static int
 xenbus_resume(device_t dev)
 {
+	device_t *kids;
+	struct xenbus_device_ivars *ivars;
+	int i, count, error;
+	char *statepath;
+
 	xb_init_comms();
 	xs_resume();
-	panic("implement me");
+
+	/*
+	 * We must re-examine each device and find the new path for
+	 * its backend.
+	 */
+	if (device_get_children(dev, &kids, &count) == 0) {
+		for (i = 0; i < count; i++) {
+			if (device_get_state(kids[i]) == DS_NOTPRESENT)
+				continue;
+
+			ivars = device_get_ivars(kids[i]);
+
+			unregister_xenbus_watch(
+				&ivars->xd_otherend_watch);
+			ivars->xd_state = XenbusStateInitialising;
+
+			/*
+			 * Find the new backend details and
+			 * re-register our watch.
+			 */
+			free(ivars->xd_otherend_path, M_DEVBUF);
+			error = xenbus_gather(XBT_NIL, ivars->xd_node,
+			    "backend-id", "%i", &ivars->xd_otherend_id,
+			    "backend", NULL, &ivars->xd_otherend_path,
+			    NULL);
+			if (error)
+				return (error);
+
+			DEVICE_RESUME(kids[i]);
+
+			statepath = malloc(strlen(ivars->xd_otherend_path)
+			    + strlen("/state") + 1, M_DEVBUF, M_WAITOK);
+			sprintf(statepath, "%s/state", ivars->xd_otherend_path);
+
+			free(ivars->xd_otherend_watch.node, M_DEVBUF);
+			ivars->xd_otherend_watch.node = statepath;
+			register_xenbus_watch(
+				&ivars->xd_otherend_watch);
+
 #if 0

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list