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