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