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$"); 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/mount.h> 117 #include <sys/namei.h> 118 #include <sys/proc.h> 119 #include <sys/reboot.h> 120 #include <sys/rman.h> 121 #include <sys/sched.h> 122 #include <sys/taskqueue.h> 123 #include <sys/types.h> 124 #include <sys/vnode.h> 125 #include <sys/sched.h> 126 #include <sys/smp.h> 127 #include <sys/eventhandler.h> 128 #include <sys/timetc.h> 129 130 #include <geom/geom.h> 131 132 #include <machine/_inttypes.h> 133 #if defined(__amd64__) || defined(__i386__) 134 #include <machine/intr_machdep.h> 135 136 #include <x86/apicvar.h> 137 #endif 138 139 #include <vm/vm.h> 140 #include <vm/vm_extern.h> 141 #include <vm/vm_kern.h> 142 143 #include <xen/xen-os.h> 144 #include <xen/blkif.h> 145 #include <xen/evtchn.h> 146 #include <xen/gnttab.h> 147 #include <xen/xen_intr.h> 148 149 #include <xen/hvm.h> 150 151 #include <xen/interface/event_channel.h> 152 #include <xen/interface/grant_table.h> 153 154 #include <xen/xenbus/xenbusvar.h> 155 156 bool xen_suspend_cancelled; 157 /*--------------------------- Forward Declarations --------------------------*/ 158 /** Function signature for shutdown event handlers. */ 159 typedef void (xctrl_shutdown_handler_t)(void); 160 161 static xctrl_shutdown_handler_t xctrl_poweroff; 162 static xctrl_shutdown_handler_t xctrl_reboot; 163 static xctrl_shutdown_handler_t xctrl_suspend; 164 static xctrl_shutdown_handler_t xctrl_crash; 165 166 /*-------------------------- Private Data Structures -------------------------*/ 167 /** Element type for lookup table of event name to handler. */ 168 struct xctrl_shutdown_reason { 169 const char *name; 170 xctrl_shutdown_handler_t *handler; 171 }; 172 173 /** Lookup table for shutdown event name to handler. */ 174 static const struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = { 175 { "poweroff", xctrl_poweroff }, 176 { "reboot", xctrl_reboot }, 177 { "suspend", xctrl_suspend }, 178 { "crash", xctrl_crash }, 179 { "halt", xctrl_poweroff }, 180 }; 181 182 struct xctrl_softc { 183 struct xs_watch xctrl_watch; 184 }; 185 186 /*------------------------------ Event Handlers ------------------------------*/ 187 static void 188 xctrl_poweroff() 189 { 190 shutdown_nice(RB_POWEROFF|RB_HALT); 191 } 192 193 static void 194 xctrl_reboot() 195 { 196 shutdown_nice(0); 197 } 198 199 #if !defined(__amd64__) && !defined(__i386__) 200 static void 201 xctrl_suspend() 202 { 203 printf("WARNING: xen/control: Suspend not supported!\n"); 204 } 205 #else /* __amd64__ || __i386__ */ 206 static void 207 xctrl_suspend() 208 { 209 #ifdef SMP 210 cpuset_t cpu_suspend_map; 211 #endif 212 213 EVENTHANDLER_INVOKE(power_suspend_early); 214 xs_lock(); 215 stop_all_proc(); 216 xs_unlock(); 217 suspend_all_fs(); 218 EVENTHANDLER_INVOKE(power_suspend); 219 220 #ifdef EARLY_AP_STARTUP 221 MPASS(mp_ncpus == 1 || smp_started); 222 thread_lock(curthread); 223 sched_bind(curthread, 0); 224 thread_unlock(curthread); 225 #else 226 if (smp_started) { 227 thread_lock(curthread); 228 sched_bind(curthread, 0); 229 thread_unlock(curthread); 230 } 231 #endif 232 KASSERT((PCPU_GET(cpuid) == 0), ("Not running on CPU#0")); 233 234 /* 235 * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE 236 * drivers need this. 237 */ 238 mtx_lock(&Giant); 239 if (DEVICE_SUSPEND(root_bus) != 0) { 240 mtx_unlock(&Giant); 241 printf("%s: device_suspend failed\n", __func__); 242 return; 243 } 244 245 #ifdef SMP 246 #ifdef EARLY_AP_STARTUP 247 /* 248 * Suspend other CPUs. This prevents IPIs while we 249 * are resuming, and will allow us to reset per-cpu 250 * vcpu_info on resume. 251 */ 252 cpu_suspend_map = all_cpus; 253 CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 254 if (!CPU_EMPTY(&cpu_suspend_map)) 255 suspend_cpus(cpu_suspend_map); 256 #else 257 CPU_ZERO(&cpu_suspend_map); /* silence gcc */ 258 if (smp_started) { 259 /* 260 * Suspend other CPUs. This prevents IPIs while we 261 * are resuming, and will allow us to reset per-cpu 262 * vcpu_info on resume. 263 */ 264 cpu_suspend_map = all_cpus; 265 CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 266 if (!CPU_EMPTY(&cpu_suspend_map)) 267 suspend_cpus(cpu_suspend_map); 268 } 269 #endif 270 #endif 271 272 /* 273 * Prevent any races with evtchn_interrupt() handler. 274 */ 275 disable_intr(); 276 intr_suspend(); 277 xen_hvm_suspend(); 278 279 xen_suspend_cancelled = !!HYPERVISOR_suspend(0); 280 281 if (!xen_suspend_cancelled) { 282 xen_hvm_resume(false); 283 } 284 intr_resume(xen_suspend_cancelled != 0); 285 enable_intr(); 286 287 /* 288 * Reset grant table info. 289 */ 290 if (!xen_suspend_cancelled) { 291 gnttab_resume(NULL); 292 } 293 294 #ifdef SMP 295 if (!CPU_EMPTY(&cpu_suspend_map)) { 296 /* 297 * Now that event channels have been initialized, 298 * resume CPUs. 299 */ 300 resume_cpus(cpu_suspend_map); 301 #if defined(__amd64__) || defined(__i386__) 302 /* Send an IPI_BITMAP in case there are pending bitmap IPIs. */ 303 lapic_ipi_vectored(IPI_BITMAP_VECTOR, APIC_IPI_DEST_ALL); 304 #endif 305 } 306 #endif 307 308 /* 309 * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or 310 * similar. 311 */ 312 DEVICE_RESUME(root_bus); 313 mtx_unlock(&Giant); 314 315 /* 316 * Warm up timecounter again and reset system clock. 317 */ 318 timecounter->tc_get_timecount(timecounter); 319 inittodr(time_second); 320 321 #ifdef EARLY_AP_STARTUP 322 thread_lock(curthread); 323 sched_unbind(curthread); 324 thread_unlock(curthread); 325 #else 326 if (smp_started) { 327 thread_lock(curthread); 328 sched_unbind(curthread); 329 thread_unlock(curthread); 330 } 331 #endif 332 333 resume_all_fs(); 334 resume_all_proc(); 335 336 EVENTHANDLER_INVOKE(power_resume); 337 338 if (bootverbose) 339 printf("System resumed after suspension\n"); 340 341 } 342 #endif /* __amd64__ || __i386__ */ 343 344 static void 345 xctrl_crash() 346 { 347 panic("Xen directed crash"); 348 } 349 350 static void 351 xen_pv_shutdown_final(void *arg, int howto) 352 { 353 /* 354 * Inform the hypervisor that shutdown is complete. 355 * This is not necessary in HVM domains since Xen 356 * emulates ACPI in that mode and FreeBSD's ACPI 357 * support will request this transition. 358 */ 359 if (howto & (RB_HALT | RB_POWEROFF)) 360 HYPERVISOR_shutdown(SHUTDOWN_poweroff); 361 else 362 HYPERVISOR_shutdown(SHUTDOWN_reboot); 363 } 364 365 /*------------------------------ Event Reception -----------------------------*/ 366 static void 367 xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) 368 { 369 const struct xctrl_shutdown_reason *reason; 370 const struct xctrl_shutdown_reason *last_reason; 371 char *result; 372 int error; 373 int result_len; 374 375 error = xs_read(XST_NIL, "control", "shutdown", 376 &result_len, (void **)&result); 377 if (error != 0 || result_len == 0) 378 return; 379 380 /* Acknowledge the request by writing back an empty string. */ 381 error = xs_write(XST_NIL, "control", "shutdown", ""); 382 if (error != 0) 383 printf("unable to ack shutdown request, proceeding anyway\n"); 384 385 reason = xctrl_shutdown_reasons; 386 last_reason = reason + nitems(xctrl_shutdown_reasons); 387 while (reason < last_reason) { 388 if (!strcmp(result, reason->name)) { 389 reason->handler(); 390 break; 391 } 392 reason++; 393 } 394 395 free(result, M_XENSTORE); 396 } 397 398 /*------------------ Private Device Attachment Functions --------------------*/ 399 /** 400 * \brief Identify instances of this device type in the system. 401 * 402 * \param driver The driver performing this identify action. 403 * \param parent The NewBus parent device for any devices this method adds. 404 */ 405 static void 406 xctrl_identify(driver_t *driver __unused, device_t parent) 407 { 408 /* 409 * A single device instance for our driver is always present 410 * in a system operating under Xen. 411 */ 412 BUS_ADD_CHILD(parent, 0, driver->name, 0); 413 } 414 415 /** 416 * \brief Probe for the existence of the Xen Control device 417 * 418 * \param dev NewBus device_t for this Xen control instance. 419 * 420 * \return Always returns 0 indicating success. 421 */ 422 static int 423 xctrl_probe(device_t dev) 424 { 425 device_set_desc(dev, "Xen Control Device"); 426 427 return (BUS_PROBE_NOWILDCARD); 428 } 429 430 /** 431 * \brief Attach the Xen control device. 432 * 433 * \param dev NewBus device_t for this Xen control instance. 434 * 435 * \return On success, 0. Otherwise an errno value indicating the 436 * type of failure. 437 */ 438 static int 439 xctrl_attach(device_t dev) 440 { 441 struct xctrl_softc *xctrl; 442 443 xctrl = device_get_softc(dev); 444 445 /* Activate watch */ 446 xctrl->xctrl_watch.node = "control/shutdown"; 447 xctrl->xctrl_watch.callback = xctrl_on_watch_event; 448 xctrl->xctrl_watch.callback_data = (uintptr_t)xctrl; 449 /* 450 * We don't care about the path updated, just about the value changes 451 * on that single node, hence there's no need to queue more that one 452 * event. 453 */ 454 xctrl->xctrl_watch.max_pending = 1; 455 xs_register_watch(&xctrl->xctrl_watch); 456 457 if (xen_pv_shutdown_handler()) 458 EVENTHANDLER_REGISTER(shutdown_final, xen_pv_shutdown_final, NULL, 459 SHUTDOWN_PRI_LAST); 460 461 return (0); 462 } 463 464 /** 465 * \brief Detach the Xen control device. 466 * 467 * \param dev NewBus device_t for this Xen control device instance. 468 * 469 * \return On success, 0. Otherwise an errno value indicating the 470 * type of failure. 471 */ 472 static int 473 xctrl_detach(device_t dev) 474 { 475 struct xctrl_softc *xctrl; 476 477 xctrl = device_get_softc(dev); 478 479 /* Release watch */ 480 xs_unregister_watch(&xctrl->xctrl_watch); 481 482 return (0); 483 } 484 485 /*-------------------- Private Device Attachment Data -----------------------*/ 486 static device_method_t xctrl_methods[] = { 487 /* Device interface */ 488 DEVMETHOD(device_identify, xctrl_identify), 489 DEVMETHOD(device_probe, xctrl_probe), 490 DEVMETHOD(device_attach, xctrl_attach), 491 DEVMETHOD(device_detach, xctrl_detach), 492 493 DEVMETHOD_END 494 }; 495 496 DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc)); 497 devclass_t xctrl_devclass; 498 499 DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, NULL, NULL); 500