xref: /freebsd/sys/dev/xen/control/control.c (revision ff662b5c9814043f1fb93ab7b16eaa0d77515959)
1*ff662b5cSJustin T. Gibbs /*-
2*ff662b5cSJustin T. Gibbs  * Copyright (c) 2010 Justin T. Gibbs, Spectra Logic Corporation
3*ff662b5cSJustin T. Gibbs  * All rights reserved.
4*ff662b5cSJustin T. Gibbs  *
5*ff662b5cSJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
6*ff662b5cSJustin T. Gibbs  * modification, are permitted provided that the following conditions
7*ff662b5cSJustin T. Gibbs  * are met:
8*ff662b5cSJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
9*ff662b5cSJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
10*ff662b5cSJustin T. Gibbs  *    without modification.
11*ff662b5cSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12*ff662b5cSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
13*ff662b5cSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
14*ff662b5cSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
15*ff662b5cSJustin T. Gibbs  *    binary redistribution.
16*ff662b5cSJustin T. Gibbs  *
17*ff662b5cSJustin T. Gibbs  * NO WARRANTY
18*ff662b5cSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*ff662b5cSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*ff662b5cSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21*ff662b5cSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22*ff662b5cSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*ff662b5cSJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*ff662b5cSJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*ff662b5cSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26*ff662b5cSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27*ff662b5cSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*ff662b5cSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
29*ff662b5cSJustin T. Gibbs  */
30*ff662b5cSJustin T. Gibbs 
31*ff662b5cSJustin T. Gibbs /*-
32*ff662b5cSJustin T. Gibbs  * PV suspend/resume support:
33*ff662b5cSJustin T. Gibbs  *
34*ff662b5cSJustin T. Gibbs  * Copyright (c) 2004 Christian Limpach.
35*ff662b5cSJustin T. Gibbs  * Copyright (c) 2004-2006,2008 Kip Macy
36*ff662b5cSJustin T. Gibbs  * All rights reserved.
37*ff662b5cSJustin T. Gibbs  *
38*ff662b5cSJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
39*ff662b5cSJustin T. Gibbs  * modification, are permitted provided that the following conditions
40*ff662b5cSJustin T. Gibbs  * are met:
41*ff662b5cSJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
42*ff662b5cSJustin T. Gibbs  *    notice, this list of conditions and the following disclaimer.
43*ff662b5cSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce the above copyright
44*ff662b5cSJustin T. Gibbs  *    notice, this list of conditions and the following disclaimer in the
45*ff662b5cSJustin T. Gibbs  *    documentation and/or other materials provided with the distribution.
46*ff662b5cSJustin T. Gibbs  * 3. All advertising materials mentioning features or use of this software
47*ff662b5cSJustin T. Gibbs  *    must display the following acknowledgement:
48*ff662b5cSJustin T. Gibbs  *      This product includes software developed by Christian Limpach.
49*ff662b5cSJustin T. Gibbs  * 4. The name of the author may not be used to endorse or promote products
50*ff662b5cSJustin T. Gibbs  *    derived from this software without specific prior written permission.
51*ff662b5cSJustin T. Gibbs  *
52*ff662b5cSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53*ff662b5cSJustin T. Gibbs  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54*ff662b5cSJustin T. Gibbs  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55*ff662b5cSJustin T. Gibbs  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56*ff662b5cSJustin T. Gibbs  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57*ff662b5cSJustin T. Gibbs  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58*ff662b5cSJustin T. Gibbs  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59*ff662b5cSJustin T. Gibbs  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60*ff662b5cSJustin T. Gibbs  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61*ff662b5cSJustin T. Gibbs  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62*ff662b5cSJustin T. Gibbs  */
63*ff662b5cSJustin T. Gibbs 
64*ff662b5cSJustin T. Gibbs /*-
65*ff662b5cSJustin T. Gibbs  * HVM suspend/resume support:
66*ff662b5cSJustin T. Gibbs  *
67*ff662b5cSJustin T. Gibbs  * Copyright (c) 2008 Citrix Systems, Inc.
68*ff662b5cSJustin T. Gibbs  * All rights reserved.
69*ff662b5cSJustin T. Gibbs  *
70*ff662b5cSJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
71*ff662b5cSJustin T. Gibbs  * modification, are permitted provided that the following conditions
72*ff662b5cSJustin T. Gibbs  * are met:
73*ff662b5cSJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
74*ff662b5cSJustin T. Gibbs  *    notice, this list of conditions and the following disclaimer.
75*ff662b5cSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce the above copyright
76*ff662b5cSJustin T. Gibbs  *    notice, this list of conditions and the following disclaimer in the
77*ff662b5cSJustin T. Gibbs  *    documentation and/or other materials provided with the distribution.
78*ff662b5cSJustin T. Gibbs  *
79*ff662b5cSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
80*ff662b5cSJustin T. Gibbs  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81*ff662b5cSJustin T. Gibbs  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82*ff662b5cSJustin T. Gibbs  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
83*ff662b5cSJustin T. Gibbs  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84*ff662b5cSJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85*ff662b5cSJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86*ff662b5cSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87*ff662b5cSJustin T. Gibbs  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88*ff662b5cSJustin T. Gibbs  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89*ff662b5cSJustin T. Gibbs  * SUCH DAMAGE.
90*ff662b5cSJustin T. Gibbs  */
91*ff662b5cSJustin T. Gibbs #include <sys/cdefs.h>
92*ff662b5cSJustin T. Gibbs __FBSDID("$FreeBSD$");
93*ff662b5cSJustin T. Gibbs 
94*ff662b5cSJustin T. Gibbs /**
95*ff662b5cSJustin T. Gibbs  * \file control.c
96*ff662b5cSJustin T. Gibbs  *
97*ff662b5cSJustin T. Gibbs  * \brief Device driver to repond to control domain events that impact
98*ff662b5cSJustin T. Gibbs  *        this VM.
99*ff662b5cSJustin T. Gibbs  */
100*ff662b5cSJustin T. Gibbs 
101*ff662b5cSJustin T. Gibbs #include <sys/param.h>
102*ff662b5cSJustin T. Gibbs #include <sys/systm.h>
103*ff662b5cSJustin T. Gibbs #include <sys/kernel.h>
104*ff662b5cSJustin T. Gibbs #include <sys/malloc.h>
105*ff662b5cSJustin T. Gibbs 
106*ff662b5cSJustin T. Gibbs #include <sys/bio.h>
107*ff662b5cSJustin T. Gibbs #include <sys/bus.h>
108*ff662b5cSJustin T. Gibbs #include <sys/conf.h>
109*ff662b5cSJustin T. Gibbs #include <sys/disk.h>
110*ff662b5cSJustin T. Gibbs #include <sys/fcntl.h>
111*ff662b5cSJustin T. Gibbs #include <sys/filedesc.h>
112*ff662b5cSJustin T. Gibbs #include <sys/kdb.h>
113*ff662b5cSJustin T. Gibbs #include <sys/module.h>
114*ff662b5cSJustin T. Gibbs #include <sys/namei.h>
115*ff662b5cSJustin T. Gibbs #include <sys/proc.h>
116*ff662b5cSJustin T. Gibbs #include <sys/reboot.h>
117*ff662b5cSJustin T. Gibbs #include <sys/rman.h>
118*ff662b5cSJustin T. Gibbs #include <sys/taskqueue.h>
119*ff662b5cSJustin T. Gibbs #include <sys/types.h>
120*ff662b5cSJustin T. Gibbs #include <sys/vnode.h>
121*ff662b5cSJustin T. Gibbs 
122*ff662b5cSJustin T. Gibbs #ifndef XENHVM
123*ff662b5cSJustin T. Gibbs #include <sys/sched.h>
124*ff662b5cSJustin T. Gibbs #include <sys/smp.h>
125*ff662b5cSJustin T. Gibbs #endif
126*ff662b5cSJustin T. Gibbs 
127*ff662b5cSJustin T. Gibbs 
128*ff662b5cSJustin T. Gibbs #include <geom/geom.h>
129*ff662b5cSJustin T. Gibbs 
130*ff662b5cSJustin T. Gibbs #include <machine/_inttypes.h>
131*ff662b5cSJustin T. Gibbs #include <machine/xen/xen-os.h>
132*ff662b5cSJustin T. Gibbs 
133*ff662b5cSJustin T. Gibbs #include <vm/vm.h>
134*ff662b5cSJustin T. Gibbs #include <vm/vm_extern.h>
135*ff662b5cSJustin T. Gibbs #include <vm/vm_kern.h>
136*ff662b5cSJustin T. Gibbs 
137*ff662b5cSJustin T. Gibbs #include <xen/blkif.h>
138*ff662b5cSJustin T. Gibbs #include <xen/evtchn.h>
139*ff662b5cSJustin T. Gibbs #include <xen/gnttab.h>
140*ff662b5cSJustin T. Gibbs #include <xen/xen_intr.h>
141*ff662b5cSJustin T. Gibbs 
142*ff662b5cSJustin T. Gibbs #include <xen/interface/event_channel.h>
143*ff662b5cSJustin T. Gibbs #include <xen/interface/grant_table.h>
144*ff662b5cSJustin T. Gibbs 
145*ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h>
146*ff662b5cSJustin T. Gibbs 
147*ff662b5cSJustin T. Gibbs #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*(x)))
148*ff662b5cSJustin T. Gibbs 
149*ff662b5cSJustin T. Gibbs /*--------------------------- Forward Declarations --------------------------*/
150*ff662b5cSJustin T. Gibbs /** Function signature for shutdown event handlers. */
151*ff662b5cSJustin T. Gibbs typedef	void (xctrl_shutdown_handler_t)(void);
152*ff662b5cSJustin T. Gibbs 
153*ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_poweroff;
154*ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_reboot;
155*ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_suspend;
156*ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_crash;
157*ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_halt;
158*ff662b5cSJustin T. Gibbs 
159*ff662b5cSJustin T. Gibbs /*-------------------------- Private Data Structures -------------------------*/
160*ff662b5cSJustin T. Gibbs /** Element type for lookup table of event name to handler. */
161*ff662b5cSJustin T. Gibbs struct xctrl_shutdown_reason {
162*ff662b5cSJustin T. Gibbs 	const char		 *name;
163*ff662b5cSJustin T. Gibbs 	xctrl_shutdown_handler_t *handler;
164*ff662b5cSJustin T. Gibbs };
165*ff662b5cSJustin T. Gibbs 
166*ff662b5cSJustin T. Gibbs /** Lookup table for shutdown event name to handler. */
167*ff662b5cSJustin T. Gibbs static struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = {
168*ff662b5cSJustin T. Gibbs 	{ "poweroff", xctrl_poweroff },
169*ff662b5cSJustin T. Gibbs 	{ "reboot",   xctrl_reboot   },
170*ff662b5cSJustin T. Gibbs 	{ "suspend",  xctrl_suspend  },
171*ff662b5cSJustin T. Gibbs 	{ "crash",    xctrl_crash    },
172*ff662b5cSJustin T. Gibbs 	{ "halt",     xctrl_halt     },
173*ff662b5cSJustin T. Gibbs };
174*ff662b5cSJustin T. Gibbs 
175*ff662b5cSJustin T. Gibbs struct xctrl_softc {
176*ff662b5cSJustin T. Gibbs 
177*ff662b5cSJustin T. Gibbs 	/** Must be first */
178*ff662b5cSJustin T. Gibbs 	struct xs_watch    xctrl_watch;
179*ff662b5cSJustin T. Gibbs };
180*ff662b5cSJustin T. Gibbs 
181*ff662b5cSJustin T. Gibbs /*------------------------------ Event Handlers ------------------------------*/
182*ff662b5cSJustin T. Gibbs static void
183*ff662b5cSJustin T. Gibbs xctrl_poweroff()
184*ff662b5cSJustin T. Gibbs {
185*ff662b5cSJustin T. Gibbs 	shutdown_nice(RB_POWEROFF|RB_HALT);
186*ff662b5cSJustin T. Gibbs }
187*ff662b5cSJustin T. Gibbs 
188*ff662b5cSJustin T. Gibbs static void
189*ff662b5cSJustin T. Gibbs xctrl_reboot()
190*ff662b5cSJustin T. Gibbs {
191*ff662b5cSJustin T. Gibbs 	shutdown_nice(0);
192*ff662b5cSJustin T. Gibbs }
193*ff662b5cSJustin T. Gibbs 
194*ff662b5cSJustin T. Gibbs #ifndef XENHVM
195*ff662b5cSJustin T. Gibbs extern void xencons_suspend(void);
196*ff662b5cSJustin T. Gibbs extern void xencons_resume(void);
197*ff662b5cSJustin T. Gibbs 
198*ff662b5cSJustin T. Gibbs /* Full PV mode suspension. */
199*ff662b5cSJustin T. Gibbs static void
200*ff662b5cSJustin T. Gibbs xctrl_suspend()
201*ff662b5cSJustin T. Gibbs {
202*ff662b5cSJustin T. Gibbs 	int i, j, k, fpp;
203*ff662b5cSJustin T. Gibbs 	unsigned long max_pfn, start_info_mfn;
204*ff662b5cSJustin T. Gibbs 
205*ff662b5cSJustin T. Gibbs #ifdef SMP
206*ff662b5cSJustin T. Gibbs 	cpumask_t map;
207*ff662b5cSJustin T. Gibbs 	/*
208*ff662b5cSJustin T. Gibbs 	 * Bind us to CPU 0 and stop any other VCPUs.
209*ff662b5cSJustin T. Gibbs 	 */
210*ff662b5cSJustin T. Gibbs 	thread_lock(curthread);
211*ff662b5cSJustin T. Gibbs 	sched_bind(curthread, 0);
212*ff662b5cSJustin T. Gibbs 	thread_unlock(curthread);
213*ff662b5cSJustin T. Gibbs 	KASSERT(PCPU_GET(cpuid) == 0, ("xen_suspend: not running on cpu 0"));
214*ff662b5cSJustin T. Gibbs 
215*ff662b5cSJustin T. Gibbs 	map = PCPU_GET(other_cpus) & ~stopped_cpus;
216*ff662b5cSJustin T. Gibbs 	if (map)
217*ff662b5cSJustin T. Gibbs 		stop_cpus(map);
218*ff662b5cSJustin T. Gibbs #endif
219*ff662b5cSJustin T. Gibbs 
220*ff662b5cSJustin T. Gibbs 	if (DEVICE_SUSPEND(root_bus) != 0) {
221*ff662b5cSJustin T. Gibbs 		printf("xen_suspend: device_suspend failed\n");
222*ff662b5cSJustin T. Gibbs #ifdef SMP
223*ff662b5cSJustin T. Gibbs 		if (map)
224*ff662b5cSJustin T. Gibbs 			restart_cpus(map);
225*ff662b5cSJustin T. Gibbs #endif
226*ff662b5cSJustin T. Gibbs 		return;
227*ff662b5cSJustin T. Gibbs 	}
228*ff662b5cSJustin T. Gibbs 
229*ff662b5cSJustin T. Gibbs 	local_irq_disable();
230*ff662b5cSJustin T. Gibbs 
231*ff662b5cSJustin T. Gibbs 	xencons_suspend();
232*ff662b5cSJustin T. Gibbs 	gnttab_suspend();
233*ff662b5cSJustin T. Gibbs 
234*ff662b5cSJustin T. Gibbs 	max_pfn = HYPERVISOR_shared_info->arch.max_pfn;
235*ff662b5cSJustin T. Gibbs 
236*ff662b5cSJustin T. Gibbs 	void *shared_info = HYPERVISOR_shared_info;
237*ff662b5cSJustin T. Gibbs 	HYPERVISOR_shared_info = NULL;
238*ff662b5cSJustin T. Gibbs 	pmap_kremove((vm_offset_t) shared_info);
239*ff662b5cSJustin T. Gibbs 	PT_UPDATES_FLUSH();
240*ff662b5cSJustin T. Gibbs 
241*ff662b5cSJustin T. Gibbs 	xen_start_info->store_mfn = MFNTOPFN(xen_start_info->store_mfn);
242*ff662b5cSJustin T. Gibbs 	xen_start_info->console.domU.mfn = MFNTOPFN(xen_start_info->console.domU.mfn);
243*ff662b5cSJustin T. Gibbs 
244*ff662b5cSJustin T. Gibbs 	/*
245*ff662b5cSJustin T. Gibbs 	 * We'll stop somewhere inside this hypercall. When it returns,
246*ff662b5cSJustin T. Gibbs 	 * we'll start resuming after the restore.
247*ff662b5cSJustin T. Gibbs 	 */
248*ff662b5cSJustin T. Gibbs 	start_info_mfn = VTOMFN(xen_start_info);
249*ff662b5cSJustin T. Gibbs 	pmap_suspend();
250*ff662b5cSJustin T. Gibbs 	HYPERVISOR_suspend(start_info_mfn);
251*ff662b5cSJustin T. Gibbs 	pmap_resume();
252*ff662b5cSJustin T. Gibbs 
253*ff662b5cSJustin T. Gibbs 	pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info);
254*ff662b5cSJustin T. Gibbs 	HYPERVISOR_shared_info = shared_info;
255*ff662b5cSJustin T. Gibbs 
256*ff662b5cSJustin T. Gibbs 	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
257*ff662b5cSJustin T. Gibbs 		VTOMFN(xen_pfn_to_mfn_frame_list_list);
258*ff662b5cSJustin T. Gibbs 
259*ff662b5cSJustin T. Gibbs 	fpp = PAGE_SIZE/sizeof(unsigned long);
260*ff662b5cSJustin T. Gibbs 	for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
261*ff662b5cSJustin T. Gibbs 		if ((j % fpp) == 0) {
262*ff662b5cSJustin T. Gibbs 			k++;
263*ff662b5cSJustin T. Gibbs 			xen_pfn_to_mfn_frame_list_list[k] =
264*ff662b5cSJustin T. Gibbs 				VTOMFN(xen_pfn_to_mfn_frame_list[k]);
265*ff662b5cSJustin T. Gibbs 			j = 0;
266*ff662b5cSJustin T. Gibbs 		}
267*ff662b5cSJustin T. Gibbs 		xen_pfn_to_mfn_frame_list[k][j] =
268*ff662b5cSJustin T. Gibbs 			VTOMFN(&xen_phys_machine[i]);
269*ff662b5cSJustin T. Gibbs 	}
270*ff662b5cSJustin T. Gibbs 	HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
271*ff662b5cSJustin T. Gibbs 
272*ff662b5cSJustin T. Gibbs 	gnttab_resume();
273*ff662b5cSJustin T. Gibbs 	irq_resume();
274*ff662b5cSJustin T. Gibbs 	local_irq_enable();
275*ff662b5cSJustin T. Gibbs 	xencons_resume();
276*ff662b5cSJustin T. Gibbs 
277*ff662b5cSJustin T. Gibbs #ifdef CONFIG_SMP
278*ff662b5cSJustin T. Gibbs 	for_each_cpu(i)
279*ff662b5cSJustin T. Gibbs 		vcpu_prepare(i);
280*ff662b5cSJustin T. Gibbs 
281*ff662b5cSJustin T. Gibbs #endif
282*ff662b5cSJustin T. Gibbs 	/*
283*ff662b5cSJustin T. Gibbs 	 * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
284*ff662b5cSJustin T. Gibbs 	 * the VCPU hotplug callback can race with our vcpu_prepare
285*ff662b5cSJustin T. Gibbs 	 */
286*ff662b5cSJustin T. Gibbs 	DEVICE_RESUME(root_bus);
287*ff662b5cSJustin T. Gibbs 
288*ff662b5cSJustin T. Gibbs #ifdef SMP
289*ff662b5cSJustin T. Gibbs 	thread_lock(curthread);
290*ff662b5cSJustin T. Gibbs 	sched_unbind(curthread);
291*ff662b5cSJustin T. Gibbs 	thread_unlock(curthread);
292*ff662b5cSJustin T. Gibbs 	if (map)
293*ff662b5cSJustin T. Gibbs 		restart_cpus(map);
294*ff662b5cSJustin T. Gibbs #endif
295*ff662b5cSJustin T. Gibbs }
296*ff662b5cSJustin T. Gibbs 
297*ff662b5cSJustin T. Gibbs static void
298*ff662b5cSJustin T. Gibbs xen_pv_shutdown_final(void *arg, int howto)
299*ff662b5cSJustin T. Gibbs {
300*ff662b5cSJustin T. Gibbs 	/*
301*ff662b5cSJustin T. Gibbs 	 * Inform the hypervisor that shutdown is complete.
302*ff662b5cSJustin T. Gibbs 	 * This is not necessary in HVM domains since Xen
303*ff662b5cSJustin T. Gibbs 	 * emulates ACPI in that mode and FreeBSD's ACPI
304*ff662b5cSJustin T. Gibbs 	 * support will request this transition.
305*ff662b5cSJustin T. Gibbs 	 */
306*ff662b5cSJustin T. Gibbs 	if (howto & (RB_HALT | RB_POWEROFF))
307*ff662b5cSJustin T. Gibbs 		HYPERVISOR_shutdown(SHUTDOWN_poweroff);
308*ff662b5cSJustin T. Gibbs 	else
309*ff662b5cSJustin T. Gibbs 		HYPERVISOR_shutdown(SHUTDOWN_reboot);
310*ff662b5cSJustin T. Gibbs }
311*ff662b5cSJustin T. Gibbs 
312*ff662b5cSJustin T. Gibbs #else
313*ff662b5cSJustin T. Gibbs extern void xenpci_resume(void);
314*ff662b5cSJustin T. Gibbs 
315*ff662b5cSJustin T. Gibbs /* HVM mode suspension. */
316*ff662b5cSJustin T. Gibbs static void
317*ff662b5cSJustin T. Gibbs xctrl_suspend()
318*ff662b5cSJustin T. Gibbs {
319*ff662b5cSJustin T. Gibbs 	int suspend_cancelled;
320*ff662b5cSJustin T. Gibbs 
321*ff662b5cSJustin T. Gibbs 	if (DEVICE_SUSPEND(root_bus)) {
322*ff662b5cSJustin T. Gibbs 		printf("xen_suspend: device_suspend failed\n");
323*ff662b5cSJustin T. Gibbs 		return;
324*ff662b5cSJustin T. Gibbs 	}
325*ff662b5cSJustin T. Gibbs 
326*ff662b5cSJustin T. Gibbs 	/*
327*ff662b5cSJustin T. Gibbs 	 * Make sure we don't change cpus or switch to some other
328*ff662b5cSJustin T. Gibbs 	 * thread. for the duration.
329*ff662b5cSJustin T. Gibbs 	 */
330*ff662b5cSJustin T. Gibbs 	critical_enter();
331*ff662b5cSJustin T. Gibbs 
332*ff662b5cSJustin T. Gibbs 	/*
333*ff662b5cSJustin T. Gibbs 	 * Prevent any races with evtchn_interrupt() handler.
334*ff662b5cSJustin T. Gibbs 	 */
335*ff662b5cSJustin T. Gibbs 	irq_suspend();
336*ff662b5cSJustin T. Gibbs 	disable_intr();
337*ff662b5cSJustin T. Gibbs 
338*ff662b5cSJustin T. Gibbs 	suspend_cancelled = HYPERVISOR_suspend(0);
339*ff662b5cSJustin T. Gibbs 	if (!suspend_cancelled)
340*ff662b5cSJustin T. Gibbs 		xenpci_resume();
341*ff662b5cSJustin T. Gibbs 
342*ff662b5cSJustin T. Gibbs 	/*
343*ff662b5cSJustin T. Gibbs 	 * Re-enable interrupts and put the scheduler back to normal.
344*ff662b5cSJustin T. Gibbs 	 */
345*ff662b5cSJustin T. Gibbs 	enable_intr();
346*ff662b5cSJustin T. Gibbs 	critical_exit();
347*ff662b5cSJustin T. Gibbs 
348*ff662b5cSJustin T. Gibbs 	/*
349*ff662b5cSJustin T. Gibbs 	 * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or
350*ff662b5cSJustin T. Gibbs 	 * similar.
351*ff662b5cSJustin T. Gibbs 	 */
352*ff662b5cSJustin T. Gibbs 	if (!suspend_cancelled)
353*ff662b5cSJustin T. Gibbs 		DEVICE_RESUME(root_bus);
354*ff662b5cSJustin T. Gibbs }
355*ff662b5cSJustin T. Gibbs #endif
356*ff662b5cSJustin T. Gibbs 
357*ff662b5cSJustin T. Gibbs static void
358*ff662b5cSJustin T. Gibbs xctrl_crash()
359*ff662b5cSJustin T. Gibbs {
360*ff662b5cSJustin T. Gibbs 	panic("Xen directed crash");
361*ff662b5cSJustin T. Gibbs }
362*ff662b5cSJustin T. Gibbs 
363*ff662b5cSJustin T. Gibbs static void
364*ff662b5cSJustin T. Gibbs xctrl_halt()
365*ff662b5cSJustin T. Gibbs {
366*ff662b5cSJustin T. Gibbs 	shutdown_nice(RB_HALT);
367*ff662b5cSJustin T. Gibbs }
368*ff662b5cSJustin T. Gibbs 
369*ff662b5cSJustin T. Gibbs /*------------------------------ Event Reception -----------------------------*/
370*ff662b5cSJustin T. Gibbs static void
371*ff662b5cSJustin T. Gibbs xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
372*ff662b5cSJustin T. Gibbs {
373*ff662b5cSJustin T. Gibbs 	struct xctrl_shutdown_reason *reason;
374*ff662b5cSJustin T. Gibbs 	struct xctrl_shutdown_reason *last_reason;
375*ff662b5cSJustin T. Gibbs 	char *result;
376*ff662b5cSJustin T. Gibbs 	int   error;
377*ff662b5cSJustin T. Gibbs 	int   result_len;
378*ff662b5cSJustin T. Gibbs 
379*ff662b5cSJustin T. Gibbs 	error = xs_read(XST_NIL, "control", "shutdown",
380*ff662b5cSJustin T. Gibbs 			&result_len, (void **)&result);
381*ff662b5cSJustin T. Gibbs 	if (error != 0)
382*ff662b5cSJustin T. Gibbs 		return;
383*ff662b5cSJustin T. Gibbs 
384*ff662b5cSJustin T. Gibbs 	reason = xctrl_shutdown_reasons;
385*ff662b5cSJustin T. Gibbs 	last_reason = reason + NUM_ELEMENTS(xctrl_shutdown_reasons);
386*ff662b5cSJustin T. Gibbs 	while (reason < last_reason) {
387*ff662b5cSJustin T. Gibbs 
388*ff662b5cSJustin T. Gibbs 		if (!strcmp(result, reason->name)) {
389*ff662b5cSJustin T. Gibbs 			reason->handler();
390*ff662b5cSJustin T. Gibbs 			break;
391*ff662b5cSJustin T. Gibbs 		}
392*ff662b5cSJustin T. Gibbs 		reason++;
393*ff662b5cSJustin T. Gibbs 	}
394*ff662b5cSJustin T. Gibbs 
395*ff662b5cSJustin T. Gibbs 	free(result, M_XENSTORE);
396*ff662b5cSJustin T. Gibbs }
397*ff662b5cSJustin T. Gibbs 
398*ff662b5cSJustin T. Gibbs /*------------------ Private Device Attachment Functions  --------------------*/
399*ff662b5cSJustin T. Gibbs /**
400*ff662b5cSJustin T. Gibbs  * \brief Identify instances of this device type in the system.
401*ff662b5cSJustin T. Gibbs  *
402*ff662b5cSJustin T. Gibbs  * \param driver  The driver performing this identify action.
403*ff662b5cSJustin T. Gibbs  * \param parent  The NewBus parent device for any devices this method adds.
404*ff662b5cSJustin T. Gibbs  */
405*ff662b5cSJustin T. Gibbs static void
406*ff662b5cSJustin T. Gibbs xctrl_identify(driver_t *driver __unused, device_t parent)
407*ff662b5cSJustin T. Gibbs {
408*ff662b5cSJustin T. Gibbs 	/*
409*ff662b5cSJustin T. Gibbs 	 * A single device instance for our driver is always present
410*ff662b5cSJustin T. Gibbs 	 * in a system operating under Xen.
411*ff662b5cSJustin T. Gibbs 	 */
412*ff662b5cSJustin T. Gibbs 	BUS_ADD_CHILD(parent, 0, driver->name, 0);
413*ff662b5cSJustin T. Gibbs }
414*ff662b5cSJustin T. Gibbs 
415*ff662b5cSJustin T. Gibbs /**
416*ff662b5cSJustin T. Gibbs  * \brief Probe for the existance of the Xen Control device
417*ff662b5cSJustin T. Gibbs  *
418*ff662b5cSJustin T. Gibbs  * \param dev  NewBus device_t for this Xen control instance.
419*ff662b5cSJustin T. Gibbs  *
420*ff662b5cSJustin T. Gibbs  * \return  Always returns 0 indicating success.
421*ff662b5cSJustin T. Gibbs  */
422*ff662b5cSJustin T. Gibbs static int
423*ff662b5cSJustin T. Gibbs xctrl_probe(device_t dev)
424*ff662b5cSJustin T. Gibbs {
425*ff662b5cSJustin T. Gibbs 	device_set_desc(dev, "Xen Control Device");
426*ff662b5cSJustin T. Gibbs 
427*ff662b5cSJustin T. Gibbs 	return (0);
428*ff662b5cSJustin T. Gibbs }
429*ff662b5cSJustin T. Gibbs 
430*ff662b5cSJustin T. Gibbs /**
431*ff662b5cSJustin T. Gibbs  * \brief Attach the Xen control device.
432*ff662b5cSJustin T. Gibbs  *
433*ff662b5cSJustin T. Gibbs  * \param dev  NewBus device_t for this Xen control instance.
434*ff662b5cSJustin T. Gibbs  *
435*ff662b5cSJustin T. Gibbs  * \return  On success, 0. Otherwise an errno value indicating the
436*ff662b5cSJustin T. Gibbs  *          type of failure.
437*ff662b5cSJustin T. Gibbs  */
438*ff662b5cSJustin T. Gibbs static int
439*ff662b5cSJustin T. Gibbs xctrl_attach(device_t dev)
440*ff662b5cSJustin T. Gibbs {
441*ff662b5cSJustin T. Gibbs 	struct xctrl_softc *xctrl;
442*ff662b5cSJustin T. Gibbs 
443*ff662b5cSJustin T. Gibbs 	xctrl = device_get_softc(dev);
444*ff662b5cSJustin T. Gibbs 
445*ff662b5cSJustin T. Gibbs 	/* Activate watch */
446*ff662b5cSJustin T. Gibbs 	xctrl->xctrl_watch.node = "control/shutdown";
447*ff662b5cSJustin T. Gibbs 	xctrl->xctrl_watch.callback = xctrl_on_watch_event;
448*ff662b5cSJustin T. Gibbs 	xs_register_watch(&xctrl->xctrl_watch);
449*ff662b5cSJustin T. Gibbs 
450*ff662b5cSJustin T. Gibbs #ifndef XENHVM
451*ff662b5cSJustin T. Gibbs 	EVENTHANDLER_REGISTER(shutdown_final, xen_pv_shutdown_final, NULL,
452*ff662b5cSJustin T. Gibbs 			      SHUTDOWN_PRI_LAST);
453*ff662b5cSJustin T. Gibbs #endif
454*ff662b5cSJustin T. Gibbs 
455*ff662b5cSJustin T. Gibbs 	return (0);
456*ff662b5cSJustin T. Gibbs }
457*ff662b5cSJustin T. Gibbs 
458*ff662b5cSJustin T. Gibbs /**
459*ff662b5cSJustin T. Gibbs  * \brief Detach the Xen control device.
460*ff662b5cSJustin T. Gibbs  *
461*ff662b5cSJustin T. Gibbs  * \param dev  NewBus device_t for this Xen control device instance.
462*ff662b5cSJustin T. Gibbs  *
463*ff662b5cSJustin T. Gibbs  * \return  On success, 0. Otherwise an errno value indicating the
464*ff662b5cSJustin T. Gibbs  *          type of failure.
465*ff662b5cSJustin T. Gibbs  */
466*ff662b5cSJustin T. Gibbs static int
467*ff662b5cSJustin T. Gibbs xctrl_detach(device_t dev)
468*ff662b5cSJustin T. Gibbs {
469*ff662b5cSJustin T. Gibbs 	struct xctrl_softc *xctrl;
470*ff662b5cSJustin T. Gibbs 
471*ff662b5cSJustin T. Gibbs 	xctrl = device_get_softc(dev);
472*ff662b5cSJustin T. Gibbs 
473*ff662b5cSJustin T. Gibbs 	/* Release watch */
474*ff662b5cSJustin T. Gibbs 	xs_unregister_watch(&xctrl->xctrl_watch);
475*ff662b5cSJustin T. Gibbs 
476*ff662b5cSJustin T. Gibbs 	return (0);
477*ff662b5cSJustin T. Gibbs }
478*ff662b5cSJustin T. Gibbs 
479*ff662b5cSJustin T. Gibbs /*-------------------- Private Device Attachment Data  -----------------------*/
480*ff662b5cSJustin T. Gibbs static device_method_t xctrl_methods[] = {
481*ff662b5cSJustin T. Gibbs 	/* Device interface */
482*ff662b5cSJustin T. Gibbs 	DEVMETHOD(device_identify,	xctrl_identify),
483*ff662b5cSJustin T. Gibbs 	DEVMETHOD(device_probe,         xctrl_probe),
484*ff662b5cSJustin T. Gibbs 	DEVMETHOD(device_attach,        xctrl_attach),
485*ff662b5cSJustin T. Gibbs 	DEVMETHOD(device_detach,        xctrl_detach),
486*ff662b5cSJustin T. Gibbs 
487*ff662b5cSJustin T. Gibbs 	{ 0, 0 }
488*ff662b5cSJustin T. Gibbs };
489*ff662b5cSJustin T. Gibbs 
490*ff662b5cSJustin T. Gibbs DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc));
491*ff662b5cSJustin T. Gibbs devclass_t xctrl_devclass;
492*ff662b5cSJustin T. Gibbs 
493*ff662b5cSJustin T. Gibbs DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, 0, 0);
494