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