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$"); 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 123 #ifndef XENHVM 124 #include <sys/sched.h> 125 #include <sys/smp.h> 126 #endif 127 128 129 #include <geom/geom.h> 130 131 #include <machine/_inttypes.h> 132 #include <machine/xen/xen-os.h> 133 134 #include <vm/vm.h> 135 #include <vm/vm_extern.h> 136 #include <vm/vm_kern.h> 137 138 #include <xen/blkif.h> 139 #include <xen/evtchn.h> 140 #include <xen/gnttab.h> 141 #include <xen/xen_intr.h> 142 143 #include <xen/interface/event_channel.h> 144 #include <xen/interface/grant_table.h> 145 146 #include <xen/xenbus/xenbusvar.h> 147 148 #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*(x))) 149 150 /*--------------------------- Forward Declarations --------------------------*/ 151 /** Function signature for shutdown event handlers. */ 152 typedef void (xctrl_shutdown_handler_t)(void); 153 154 static xctrl_shutdown_handler_t xctrl_poweroff; 155 static xctrl_shutdown_handler_t xctrl_reboot; 156 static xctrl_shutdown_handler_t xctrl_suspend; 157 static xctrl_shutdown_handler_t xctrl_crash; 158 static xctrl_shutdown_handler_t xctrl_halt; 159 160 /*-------------------------- Private Data Structures -------------------------*/ 161 /** Element type for lookup table of event name to handler. */ 162 struct xctrl_shutdown_reason { 163 const char *name; 164 xctrl_shutdown_handler_t *handler; 165 }; 166 167 /** Lookup table for shutdown event name to handler. */ 168 static struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = { 169 { "poweroff", xctrl_poweroff }, 170 { "reboot", xctrl_reboot }, 171 { "suspend", xctrl_suspend }, 172 { "crash", xctrl_crash }, 173 { "halt", xctrl_halt }, 174 }; 175 176 struct xctrl_softc { 177 struct xs_watch xctrl_watch; 178 }; 179 180 /*------------------------------ Event Handlers ------------------------------*/ 181 static void 182 xctrl_poweroff() 183 { 184 shutdown_nice(RB_POWEROFF|RB_HALT); 185 } 186 187 static void 188 xctrl_reboot() 189 { 190 shutdown_nice(0); 191 } 192 193 #ifndef XENHVM 194 extern void xencons_suspend(void); 195 extern void xencons_resume(void); 196 197 /* Full PV mode suspension. */ 198 static void 199 xctrl_suspend() 200 { 201 u_int cpuid; 202 int i, j, k, fpp; 203 unsigned long max_pfn, start_info_mfn; 204 205 EVENTHANDLER_INVOKE(power_suspend); 206 207 #ifdef SMP 208 struct thread *td; 209 cpuset_t map; 210 /* 211 * Bind us to CPU 0 and stop any other VCPUs. 212 */ 213 td = curthread; 214 thread_lock(td); 215 sched_bind(td, 0); 216 thread_unlock(td); 217 cpuid = PCPU_GET(cpuid); 218 KASSERT(cpuid == 0, ("xen_suspend: not running on cpu 0")); 219 220 map = all_cpus; 221 CPU_CLR(cpuid, &map); 222 CPU_NAND(&map, &stopped_cpus); 223 if (!CPU_EMPTY(&map)) 224 stop_cpus(map); 225 #endif 226 227 /* 228 * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE 229 * drivers need this. 230 */ 231 mtx_lock(&Giant); 232 if (DEVICE_SUSPEND(root_bus) != 0) { 233 mtx_unlock(&Giant); 234 printf("xen_suspend: device_suspend failed\n"); 235 #ifdef SMP 236 if (!CPU_EMPTY(&map)) 237 restart_cpus(map); 238 #endif 239 return; 240 } 241 mtx_unlock(&Giant); 242 243 local_irq_disable(); 244 245 xencons_suspend(); 246 gnttab_suspend(); 247 248 max_pfn = HYPERVISOR_shared_info->arch.max_pfn; 249 250 void *shared_info = HYPERVISOR_shared_info; 251 HYPERVISOR_shared_info = NULL; 252 pmap_kremove((vm_offset_t) shared_info); 253 PT_UPDATES_FLUSH(); 254 255 xen_start_info->store_mfn = MFNTOPFN(xen_start_info->store_mfn); 256 xen_start_info->console.domU.mfn = MFNTOPFN(xen_start_info->console.domU.mfn); 257 258 /* 259 * We'll stop somewhere inside this hypercall. When it returns, 260 * we'll start resuming after the restore. 261 */ 262 start_info_mfn = VTOMFN(xen_start_info); 263 pmap_suspend(); 264 HYPERVISOR_suspend(start_info_mfn); 265 pmap_resume(); 266 267 pmap_kenter_ma((vm_offset_t) shared_info, xen_start_info->shared_info); 268 HYPERVISOR_shared_info = shared_info; 269 270 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = 271 VTOMFN(xen_pfn_to_mfn_frame_list_list); 272 273 fpp = PAGE_SIZE/sizeof(unsigned long); 274 for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) { 275 if ((j % fpp) == 0) { 276 k++; 277 xen_pfn_to_mfn_frame_list_list[k] = 278 VTOMFN(xen_pfn_to_mfn_frame_list[k]); 279 j = 0; 280 } 281 xen_pfn_to_mfn_frame_list[k][j] = 282 VTOMFN(&xen_phys_machine[i]); 283 } 284 HYPERVISOR_shared_info->arch.max_pfn = max_pfn; 285 286 gnttab_resume(); 287 irq_resume(); 288 local_irq_enable(); 289 xencons_resume(); 290 291 #ifdef CONFIG_SMP 292 for_each_cpu(i) 293 vcpu_prepare(i); 294 295 #endif 296 297 /* 298 * Only resume xenbus /after/ we've prepared our VCPUs; otherwise 299 * the VCPU hotplug callback can race with our vcpu_prepare 300 */ 301 mtx_lock(&Giant); 302 DEVICE_RESUME(root_bus); 303 mtx_unlock(&Giant); 304 305 #ifdef SMP 306 thread_lock(curthread); 307 sched_unbind(curthread); 308 thread_unlock(curthread); 309 if (!CPU_EMPTY(&map)) 310 restart_cpus(map); 311 #endif 312 EVENTHANDLER_INVOKE(power_resume); 313 } 314 315 static void 316 xen_pv_shutdown_final(void *arg, int howto) 317 { 318 /* 319 * Inform the hypervisor that shutdown is complete. 320 * This is not necessary in HVM domains since Xen 321 * emulates ACPI in that mode and FreeBSD's ACPI 322 * support will request this transition. 323 */ 324 if (howto & (RB_HALT | RB_POWEROFF)) 325 HYPERVISOR_shutdown(SHUTDOWN_poweroff); 326 else 327 HYPERVISOR_shutdown(SHUTDOWN_reboot); 328 } 329 330 #else 331 extern void xenpci_resume(void); 332 333 /* HVM mode suspension. */ 334 static void 335 xctrl_suspend() 336 { 337 int suspend_cancelled; 338 339 EVENTHANDLER_INVOKE(power_suspend); 340 341 /* 342 * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE 343 * drivers need this. 344 */ 345 mtx_lock(&Giant); 346 if (DEVICE_SUSPEND(root_bus)) { 347 mtx_unlock(&Giant); 348 printf("xen_suspend: device_suspend failed\n"); 349 return; 350 } 351 mtx_unlock(&Giant); 352 353 /* 354 * Prevent any races with evtchn_interrupt() handler. 355 */ 356 disable_intr(); 357 irq_suspend(); 358 359 suspend_cancelled = HYPERVISOR_suspend(0); 360 if (suspend_cancelled) 361 irq_resume(); 362 else 363 xenpci_resume(); 364 365 /* 366 * Re-enable interrupts and put the scheduler back to normal. 367 */ 368 enable_intr(); 369 370 /* 371 * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or 372 * similar. 373 */ 374 mtx_lock(&Giant); 375 if (!suspend_cancelled) 376 DEVICE_RESUME(root_bus); 377 mtx_unlock(&Giant); 378 379 EVENTHANDLER_INVOKE(power_resume); 380 } 381 #endif 382 383 static void 384 xctrl_crash() 385 { 386 panic("Xen directed crash"); 387 } 388 389 static void 390 xctrl_halt() 391 { 392 shutdown_nice(RB_HALT); 393 } 394 395 /*------------------------------ Event Reception -----------------------------*/ 396 static void 397 xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) 398 { 399 struct xctrl_shutdown_reason *reason; 400 struct xctrl_shutdown_reason *last_reason; 401 char *result; 402 int error; 403 int result_len; 404 405 error = xs_read(XST_NIL, "control", "shutdown", 406 &result_len, (void **)&result); 407 if (error != 0) 408 return; 409 410 reason = xctrl_shutdown_reasons; 411 last_reason = reason + NUM_ELEMENTS(xctrl_shutdown_reasons); 412 while (reason < last_reason) { 413 414 if (!strcmp(result, reason->name)) { 415 reason->handler(); 416 break; 417 } 418 reason++; 419 } 420 421 free(result, M_XENSTORE); 422 } 423 424 /*------------------ Private Device Attachment Functions --------------------*/ 425 /** 426 * \brief Identify instances of this device type in the system. 427 * 428 * \param driver The driver performing this identify action. 429 * \param parent The NewBus parent device for any devices this method adds. 430 */ 431 static void 432 xctrl_identify(driver_t *driver __unused, device_t parent) 433 { 434 /* 435 * A single device instance for our driver is always present 436 * in a system operating under Xen. 437 */ 438 BUS_ADD_CHILD(parent, 0, driver->name, 0); 439 } 440 441 /** 442 * \brief Probe for the existance of the Xen Control device 443 * 444 * \param dev NewBus device_t for this Xen control instance. 445 * 446 * \return Always returns 0 indicating success. 447 */ 448 static int 449 xctrl_probe(device_t dev) 450 { 451 device_set_desc(dev, "Xen Control Device"); 452 453 return (0); 454 } 455 456 /** 457 * \brief Attach the Xen control device. 458 * 459 * \param dev NewBus device_t for this Xen control instance. 460 * 461 * \return On success, 0. Otherwise an errno value indicating the 462 * type of failure. 463 */ 464 static int 465 xctrl_attach(device_t dev) 466 { 467 struct xctrl_softc *xctrl; 468 469 xctrl = device_get_softc(dev); 470 471 /* Activate watch */ 472 xctrl->xctrl_watch.node = "control/shutdown"; 473 xctrl->xctrl_watch.callback = xctrl_on_watch_event; 474 xctrl->xctrl_watch.callback_data = (uintptr_t)xctrl; 475 xs_register_watch(&xctrl->xctrl_watch); 476 477 #ifndef XENHVM 478 EVENTHANDLER_REGISTER(shutdown_final, xen_pv_shutdown_final, NULL, 479 SHUTDOWN_PRI_LAST); 480 #endif 481 482 return (0); 483 } 484 485 /** 486 * \brief Detach the Xen control device. 487 * 488 * \param dev NewBus device_t for this Xen control device instance. 489 * 490 * \return On success, 0. Otherwise an errno value indicating the 491 * type of failure. 492 */ 493 static int 494 xctrl_detach(device_t dev) 495 { 496 struct xctrl_softc *xctrl; 497 498 xctrl = device_get_softc(dev); 499 500 /* Release watch */ 501 xs_unregister_watch(&xctrl->xctrl_watch); 502 503 return (0); 504 } 505 506 /*-------------------- Private Device Attachment Data -----------------------*/ 507 static device_method_t xctrl_methods[] = { 508 /* Device interface */ 509 DEVMETHOD(device_identify, xctrl_identify), 510 DEVMETHOD(device_probe, xctrl_probe), 511 DEVMETHOD(device_attach, xctrl_attach), 512 DEVMETHOD(device_detach, xctrl_detach), 513 514 { 0, 0 } 515 }; 516 517 DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc)); 518 devclass_t xctrl_devclass; 519 520 DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, 0, 0); 521