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