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 #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 151 /*--------------------------- Forward Declarations --------------------------*/ 152 /** Function signature for shutdown event handlers. */ 153 typedef void (xctrl_shutdown_handler_t)(void); 154 155 static xctrl_shutdown_handler_t xctrl_poweroff; 156 static xctrl_shutdown_handler_t xctrl_reboot; 157 static xctrl_shutdown_handler_t xctrl_suspend; 158 static xctrl_shutdown_handler_t xctrl_crash; 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 const 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_poweroff }, 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 static void 194 xctrl_suspend() 195 { 196 #ifdef SMP 197 cpuset_t cpu_suspend_map; 198 #endif 199 int suspend_cancelled; 200 201 EVENTHANDLER_INVOKE(power_suspend_early); 202 stop_all_proc(); 203 EVENTHANDLER_INVOKE(power_suspend); 204 205 if (smp_started) { 206 thread_lock(curthread); 207 sched_bind(curthread, 0); 208 thread_unlock(curthread); 209 } 210 KASSERT((PCPU_GET(cpuid) == 0), ("Not running on CPU#0")); 211 212 /* 213 * Clear our XenStore node so the toolstack knows we are 214 * responding to the suspend request. 215 */ 216 xs_write(XST_NIL, "control", "shutdown", ""); 217 218 /* 219 * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE 220 * drivers need this. 221 */ 222 mtx_lock(&Giant); 223 if (DEVICE_SUSPEND(root_bus) != 0) { 224 mtx_unlock(&Giant); 225 printf("%s: device_suspend failed\n", __func__); 226 return; 227 } 228 229 #ifdef SMP 230 CPU_ZERO(&cpu_suspend_map); /* silence gcc */ 231 if (smp_started) { 232 /* 233 * Suspend other CPUs. This prevents IPIs while we 234 * are resuming, and will allow us to reset per-cpu 235 * vcpu_info on resume. 236 */ 237 cpu_suspend_map = all_cpus; 238 CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 239 if (!CPU_EMPTY(&cpu_suspend_map)) 240 suspend_cpus(cpu_suspend_map); 241 } 242 #endif 243 244 /* 245 * Prevent any races with evtchn_interrupt() handler. 246 */ 247 disable_intr(); 248 intr_suspend(); 249 xen_hvm_suspend(); 250 251 suspend_cancelled = HYPERVISOR_suspend(0); 252 253 xen_hvm_resume(suspend_cancelled != 0); 254 intr_resume(suspend_cancelled != 0); 255 enable_intr(); 256 257 /* 258 * Reset grant table info. 259 */ 260 gnttab_resume(NULL); 261 262 #ifdef SMP 263 if (!CPU_EMPTY(&cpu_suspend_map)) { 264 /* 265 * Now that event channels have been initialized, 266 * resume CPUs. 267 */ 268 resume_cpus(cpu_suspend_map); 269 /* Send an IPI_BITMAP in case there are pending bitmap IPIs. */ 270 lapic_ipi_vectored(IPI_BITMAP_VECTOR, APIC_IPI_DEST_ALL); 271 } 272 #endif 273 274 /* 275 * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or 276 * similar. 277 */ 278 DEVICE_RESUME(root_bus); 279 mtx_unlock(&Giant); 280 281 /* 282 * Warm up timecounter again and reset system clock. 283 */ 284 timecounter->tc_get_timecount(timecounter); 285 timecounter->tc_get_timecount(timecounter); 286 inittodr(time_second); 287 288 if (smp_started) { 289 thread_lock(curthread); 290 sched_unbind(curthread); 291 thread_unlock(curthread); 292 } 293 294 resume_all_proc(); 295 296 EVENTHANDLER_INVOKE(power_resume); 297 298 if (bootverbose) 299 printf("System resumed after suspension\n"); 300 301 } 302 303 static void 304 xctrl_crash() 305 { 306 panic("Xen directed crash"); 307 } 308 309 static void 310 xen_pv_shutdown_final(void *arg, int howto) 311 { 312 /* 313 * Inform the hypervisor that shutdown is complete. 314 * This is not necessary in HVM domains since Xen 315 * emulates ACPI in that mode and FreeBSD's ACPI 316 * support will request this transition. 317 */ 318 if (howto & (RB_HALT | RB_POWEROFF)) 319 HYPERVISOR_shutdown(SHUTDOWN_poweroff); 320 else 321 HYPERVISOR_shutdown(SHUTDOWN_reboot); 322 } 323 324 /*------------------------------ Event Reception -----------------------------*/ 325 static void 326 xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) 327 { 328 const struct xctrl_shutdown_reason *reason; 329 const struct xctrl_shutdown_reason *last_reason; 330 char *result; 331 int error; 332 int result_len; 333 334 error = xs_read(XST_NIL, "control", "shutdown", 335 &result_len, (void **)&result); 336 if (error != 0) 337 return; 338 339 reason = xctrl_shutdown_reasons; 340 last_reason = reason + nitems(xctrl_shutdown_reasons); 341 while (reason < last_reason) { 342 343 if (!strcmp(result, reason->name)) { 344 reason->handler(); 345 break; 346 } 347 reason++; 348 } 349 350 free(result, M_XENSTORE); 351 } 352 353 /*------------------ Private Device Attachment Functions --------------------*/ 354 /** 355 * \brief Identify instances of this device type in the system. 356 * 357 * \param driver The driver performing this identify action. 358 * \param parent The NewBus parent device for any devices this method adds. 359 */ 360 static void 361 xctrl_identify(driver_t *driver __unused, device_t parent) 362 { 363 /* 364 * A single device instance for our driver is always present 365 * in a system operating under Xen. 366 */ 367 BUS_ADD_CHILD(parent, 0, driver->name, 0); 368 } 369 370 /** 371 * \brief Probe for the existence of the Xen Control device 372 * 373 * \param dev NewBus device_t for this Xen control instance. 374 * 375 * \return Always returns 0 indicating success. 376 */ 377 static int 378 xctrl_probe(device_t dev) 379 { 380 device_set_desc(dev, "Xen Control Device"); 381 382 return (BUS_PROBE_NOWILDCARD); 383 } 384 385 /** 386 * \brief Attach the Xen control device. 387 * 388 * \param dev NewBus device_t for this Xen control instance. 389 * 390 * \return On success, 0. Otherwise an errno value indicating the 391 * type of failure. 392 */ 393 static int 394 xctrl_attach(device_t dev) 395 { 396 struct xctrl_softc *xctrl; 397 398 xctrl = device_get_softc(dev); 399 400 /* Activate watch */ 401 xctrl->xctrl_watch.node = "control/shutdown"; 402 xctrl->xctrl_watch.callback = xctrl_on_watch_event; 403 xctrl->xctrl_watch.callback_data = (uintptr_t)xctrl; 404 xs_register_watch(&xctrl->xctrl_watch); 405 406 if (xen_pv_domain()) 407 EVENTHANDLER_REGISTER(shutdown_final, xen_pv_shutdown_final, NULL, 408 SHUTDOWN_PRI_LAST); 409 410 return (0); 411 } 412 413 /** 414 * \brief Detach the Xen control device. 415 * 416 * \param dev NewBus device_t for this Xen control device instance. 417 * 418 * \return On success, 0. Otherwise an errno value indicating the 419 * type of failure. 420 */ 421 static int 422 xctrl_detach(device_t dev) 423 { 424 struct xctrl_softc *xctrl; 425 426 xctrl = device_get_softc(dev); 427 428 /* Release watch */ 429 xs_unregister_watch(&xctrl->xctrl_watch); 430 431 return (0); 432 } 433 434 /*-------------------- Private Device Attachment Data -----------------------*/ 435 static device_method_t xctrl_methods[] = { 436 /* Device interface */ 437 DEVMETHOD(device_identify, xctrl_identify), 438 DEVMETHOD(device_probe, xctrl_probe), 439 DEVMETHOD(device_attach, xctrl_attach), 440 DEVMETHOD(device_detach, xctrl_detach), 441 442 DEVMETHOD_END 443 }; 444 445 DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc)); 446 devclass_t xctrl_devclass; 447 448 DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, NULL, NULL); 449