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