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