1ff662b5cSJustin T. Gibbs /*- 2ff662b5cSJustin T. Gibbs * Copyright (c) 2010 Justin T. Gibbs, Spectra Logic Corporation 3ff662b5cSJustin T. Gibbs * All rights reserved. 4ff662b5cSJustin T. Gibbs * 5ff662b5cSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 6ff662b5cSJustin T. Gibbs * modification, are permitted provided that the following conditions 7ff662b5cSJustin T. Gibbs * are met: 8ff662b5cSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 9ff662b5cSJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 10ff662b5cSJustin T. Gibbs * without modification. 11ff662b5cSJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12ff662b5cSJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 13ff662b5cSJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 14ff662b5cSJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 15ff662b5cSJustin T. Gibbs * binary redistribution. 16ff662b5cSJustin T. Gibbs * 17ff662b5cSJustin T. Gibbs * NO WARRANTY 18ff662b5cSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19ff662b5cSJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20ff662b5cSJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21ff662b5cSJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22ff662b5cSJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23ff662b5cSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24ff662b5cSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25ff662b5cSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26ff662b5cSJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27ff662b5cSJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28ff662b5cSJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 29ff662b5cSJustin T. Gibbs */ 30ff662b5cSJustin T. Gibbs 31ff662b5cSJustin T. Gibbs /*- 32ff662b5cSJustin T. Gibbs * PV suspend/resume support: 33ff662b5cSJustin T. Gibbs * 34ff662b5cSJustin T. Gibbs * Copyright (c) 2004 Christian Limpach. 35ff662b5cSJustin T. Gibbs * Copyright (c) 2004-2006,2008 Kip Macy 36ff662b5cSJustin T. Gibbs * All rights reserved. 37ff662b5cSJustin T. Gibbs * 38ff662b5cSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 39ff662b5cSJustin T. Gibbs * modification, are permitted provided that the following conditions 40ff662b5cSJustin T. Gibbs * are met: 41ff662b5cSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 42ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 43ff662b5cSJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 44ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 45ff662b5cSJustin T. Gibbs * documentation and/or other materials provided with the distribution. 46ff662b5cSJustin T. Gibbs * 3. All advertising materials mentioning features or use of this software 47ff662b5cSJustin T. Gibbs * must display the following acknowledgement: 48ff662b5cSJustin T. Gibbs * This product includes software developed by Christian Limpach. 49ff662b5cSJustin T. Gibbs * 4. The name of the author may not be used to endorse or promote products 50ff662b5cSJustin T. Gibbs * derived from this software without specific prior written permission. 51ff662b5cSJustin T. Gibbs * 52ff662b5cSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53ff662b5cSJustin T. Gibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54ff662b5cSJustin T. Gibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55ff662b5cSJustin T. Gibbs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56ff662b5cSJustin T. Gibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57ff662b5cSJustin T. Gibbs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58ff662b5cSJustin T. Gibbs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59ff662b5cSJustin T. Gibbs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60ff662b5cSJustin T. Gibbs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61ff662b5cSJustin T. Gibbs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62ff662b5cSJustin T. Gibbs */ 63ff662b5cSJustin T. Gibbs 64ff662b5cSJustin T. Gibbs /*- 65ff662b5cSJustin T. Gibbs * HVM suspend/resume support: 66ff662b5cSJustin T. Gibbs * 67ff662b5cSJustin T. Gibbs * Copyright (c) 2008 Citrix Systems, Inc. 68ff662b5cSJustin T. Gibbs * All rights reserved. 69ff662b5cSJustin T. Gibbs * 70ff662b5cSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 71ff662b5cSJustin T. Gibbs * modification, are permitted provided that the following conditions 72ff662b5cSJustin T. Gibbs * are met: 73ff662b5cSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 74ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 75ff662b5cSJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 76ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 77ff662b5cSJustin T. Gibbs * documentation and/or other materials provided with the distribution. 78ff662b5cSJustin T. Gibbs * 79ff662b5cSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 80ff662b5cSJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 81ff662b5cSJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 82ff662b5cSJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 83ff662b5cSJustin T. Gibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 84ff662b5cSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 85ff662b5cSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 86ff662b5cSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 87ff662b5cSJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 88ff662b5cSJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 89ff662b5cSJustin T. Gibbs * SUCH DAMAGE. 90ff662b5cSJustin T. Gibbs */ 91ff662b5cSJustin T. Gibbs #include <sys/cdefs.h> 92ff662b5cSJustin T. Gibbs __FBSDID("$FreeBSD$"); 93ff662b5cSJustin T. Gibbs 94ff662b5cSJustin T. Gibbs /** 95ff662b5cSJustin T. Gibbs * \file control.c 96ff662b5cSJustin T. Gibbs * 97ff662b5cSJustin T. Gibbs * \brief Device driver to repond to control domain events that impact 98ff662b5cSJustin T. Gibbs * this VM. 99ff662b5cSJustin T. Gibbs */ 100ff662b5cSJustin T. Gibbs 101ff662b5cSJustin T. Gibbs #include <sys/param.h> 102ff662b5cSJustin T. Gibbs #include <sys/systm.h> 103ff662b5cSJustin T. Gibbs #include <sys/kernel.h> 104ff662b5cSJustin T. Gibbs #include <sys/malloc.h> 105ff662b5cSJustin T. Gibbs 106ff662b5cSJustin T. Gibbs #include <sys/bio.h> 107ff662b5cSJustin T. Gibbs #include <sys/bus.h> 108ff662b5cSJustin T. Gibbs #include <sys/conf.h> 109ff662b5cSJustin T. Gibbs #include <sys/disk.h> 110ff662b5cSJustin T. Gibbs #include <sys/fcntl.h> 111ff662b5cSJustin T. Gibbs #include <sys/filedesc.h> 112ff662b5cSJustin T. Gibbs #include <sys/kdb.h> 113ff662b5cSJustin T. Gibbs #include <sys/module.h> 114ff662b5cSJustin T. Gibbs #include <sys/namei.h> 115ff662b5cSJustin T. Gibbs #include <sys/proc.h> 116ff662b5cSJustin T. Gibbs #include <sys/reboot.h> 117ff662b5cSJustin T. Gibbs #include <sys/rman.h> 1182ca7463bSJustin T. Gibbs #include <sys/sched.h> 119ff662b5cSJustin T. Gibbs #include <sys/taskqueue.h> 120ff662b5cSJustin T. Gibbs #include <sys/types.h> 121ff662b5cSJustin T. Gibbs #include <sys/vnode.h> 122ff662b5cSJustin T. Gibbs #include <sys/sched.h> 123ff662b5cSJustin T. Gibbs #include <sys/smp.h> 124428b7ca2SJustin T. Gibbs #include <sys/eventhandler.h> 1256e2a4a5fSRoger Pau Monné #include <sys/timetc.h> 126ff662b5cSJustin T. Gibbs 127ff662b5cSJustin T. Gibbs #include <geom/geom.h> 128ff662b5cSJustin T. Gibbs 129ff662b5cSJustin T. Gibbs #include <machine/_inttypes.h> 13076acc41fSJustin T. Gibbs #include <machine/intr_machdep.h> 131ff662b5cSJustin T. Gibbs 13215226522SRoger Pau Monné #include <x86/apicvar.h> 13315226522SRoger Pau Monné 134ff662b5cSJustin T. Gibbs #include <vm/vm.h> 135ff662b5cSJustin T. Gibbs #include <vm/vm_extern.h> 136ff662b5cSJustin T. Gibbs #include <vm/vm_kern.h> 137ff662b5cSJustin T. Gibbs 13876acc41fSJustin T. Gibbs #include <xen/xen-os.h> 139ff662b5cSJustin T. Gibbs #include <xen/blkif.h> 140ff662b5cSJustin T. Gibbs #include <xen/evtchn.h> 141ff662b5cSJustin T. Gibbs #include <xen/gnttab.h> 142ff662b5cSJustin T. Gibbs #include <xen/xen_intr.h> 143ff662b5cSJustin T. Gibbs 144428b7ca2SJustin T. Gibbs #include <xen/hvm.h> 145428b7ca2SJustin T. Gibbs 146ff662b5cSJustin T. Gibbs #include <xen/interface/event_channel.h> 147ff662b5cSJustin T. Gibbs #include <xen/interface/grant_table.h> 148ff662b5cSJustin T. Gibbs 149ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h> 150ff662b5cSJustin T. Gibbs 151ff662b5cSJustin T. Gibbs /*--------------------------- Forward Declarations --------------------------*/ 152ff662b5cSJustin T. Gibbs /** Function signature for shutdown event handlers. */ 153ff662b5cSJustin T. Gibbs typedef void (xctrl_shutdown_handler_t)(void); 154ff662b5cSJustin T. Gibbs 155ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_poweroff; 156ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_reboot; 157ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_suspend; 158ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_crash; 159ff662b5cSJustin T. Gibbs 160ff662b5cSJustin T. Gibbs /*-------------------------- Private Data Structures -------------------------*/ 161ff662b5cSJustin T. Gibbs /** Element type for lookup table of event name to handler. */ 162ff662b5cSJustin T. Gibbs struct xctrl_shutdown_reason { 163ff662b5cSJustin T. Gibbs const char *name; 164ff662b5cSJustin T. Gibbs xctrl_shutdown_handler_t *handler; 165ff662b5cSJustin T. Gibbs }; 166ff662b5cSJustin T. Gibbs 167ff662b5cSJustin T. Gibbs /** Lookup table for shutdown event name to handler. */ 168dcceabd3SMarius Strobl static const struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = { 169ff662b5cSJustin T. Gibbs { "poweroff", xctrl_poweroff }, 170ff662b5cSJustin T. Gibbs { "reboot", xctrl_reboot }, 171ff662b5cSJustin T. Gibbs { "suspend", xctrl_suspend }, 172ff662b5cSJustin T. Gibbs { "crash", xctrl_crash }, 1734c85fcfaSJustin T. Gibbs { "halt", xctrl_poweroff }, 174ff662b5cSJustin T. Gibbs }; 175ff662b5cSJustin T. Gibbs 176ff662b5cSJustin T. Gibbs struct xctrl_softc { 177ff662b5cSJustin T. Gibbs struct xs_watch xctrl_watch; 178ff662b5cSJustin T. Gibbs }; 179ff662b5cSJustin T. Gibbs 180ff662b5cSJustin T. Gibbs /*------------------------------ Event Handlers ------------------------------*/ 181ff662b5cSJustin T. Gibbs static void 182ff662b5cSJustin T. Gibbs xctrl_poweroff() 183ff662b5cSJustin T. Gibbs { 184ff662b5cSJustin T. Gibbs shutdown_nice(RB_POWEROFF|RB_HALT); 185ff662b5cSJustin T. Gibbs } 186ff662b5cSJustin T. Gibbs 187ff662b5cSJustin T. Gibbs static void 188ff662b5cSJustin T. Gibbs xctrl_reboot() 189ff662b5cSJustin T. Gibbs { 190ff662b5cSJustin T. Gibbs shutdown_nice(0); 191ff662b5cSJustin T. Gibbs } 192ff662b5cSJustin T. Gibbs 193ff662b5cSJustin T. Gibbs static void 194ff662b5cSJustin T. Gibbs xctrl_suspend() 195ff662b5cSJustin T. Gibbs { 196428b7ca2SJustin T. Gibbs #ifdef SMP 197428b7ca2SJustin T. Gibbs cpuset_t cpu_suspend_map; 198428b7ca2SJustin T. Gibbs #endif 199ff662b5cSJustin T. Gibbs int suspend_cancelled; 200ff662b5cSJustin T. Gibbs 2016e2a4a5fSRoger Pau Monné EVENTHANDLER_INVOKE(power_suspend_early); 2026e2a4a5fSRoger Pau Monné stop_all_proc(); 2032ca7463bSJustin T. Gibbs EVENTHANDLER_INVOKE(power_suspend); 2042ca7463bSJustin T. Gibbs 205*fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 206*fdce57a0SJohn Baldwin MPASS(mp_ncpus == 1 || smp_started); 207*fdce57a0SJohn Baldwin thread_lock(curthread); 208*fdce57a0SJohn Baldwin sched_bind(curthread, 0); 209*fdce57a0SJohn Baldwin thread_unlock(curthread); 210*fdce57a0SJohn Baldwin #else 211428b7ca2SJustin T. Gibbs if (smp_started) { 212428b7ca2SJustin T. Gibbs thread_lock(curthread); 213428b7ca2SJustin T. Gibbs sched_bind(curthread, 0); 214428b7ca2SJustin T. Gibbs thread_unlock(curthread); 215428b7ca2SJustin T. Gibbs } 216*fdce57a0SJohn Baldwin #endif 217428b7ca2SJustin T. Gibbs KASSERT((PCPU_GET(cpuid) == 0), ("Not running on CPU#0")); 218428b7ca2SJustin T. Gibbs 219428b7ca2SJustin T. Gibbs /* 220428b7ca2SJustin T. Gibbs * Clear our XenStore node so the toolstack knows we are 221428b7ca2SJustin T. Gibbs * responding to the suspend request. 222428b7ca2SJustin T. Gibbs */ 223428b7ca2SJustin T. Gibbs xs_write(XST_NIL, "control", "shutdown", ""); 224428b7ca2SJustin T. Gibbs 2252ca7463bSJustin T. Gibbs /* 2262ca7463bSJustin T. Gibbs * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE 2272ca7463bSJustin T. Gibbs * drivers need this. 2282ca7463bSJustin T. Gibbs */ 2292ca7463bSJustin T. Gibbs mtx_lock(&Giant); 230dcceabd3SMarius Strobl if (DEVICE_SUSPEND(root_bus) != 0) { 2312ca7463bSJustin T. Gibbs mtx_unlock(&Giant); 232dcceabd3SMarius Strobl printf("%s: device_suspend failed\n", __func__); 233ff662b5cSJustin T. Gibbs return; 234ff662b5cSJustin T. Gibbs } 235ff662b5cSJustin T. Gibbs 236428b7ca2SJustin T. Gibbs #ifdef SMP 237*fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 238*fdce57a0SJohn Baldwin /* 239*fdce57a0SJohn Baldwin * Suspend other CPUs. This prevents IPIs while we 240*fdce57a0SJohn Baldwin * are resuming, and will allow us to reset per-cpu 241*fdce57a0SJohn Baldwin * vcpu_info on resume. 242*fdce57a0SJohn Baldwin */ 243*fdce57a0SJohn Baldwin cpu_suspend_map = all_cpus; 244*fdce57a0SJohn Baldwin CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 245*fdce57a0SJohn Baldwin if (!CPU_EMPTY(&cpu_suspend_map)) 246*fdce57a0SJohn Baldwin suspend_cpus(cpu_suspend_map); 247*fdce57a0SJohn Baldwin #else 248faf8ff5fSDimitry Andric CPU_ZERO(&cpu_suspend_map); /* silence gcc */ 249428b7ca2SJustin T. Gibbs if (smp_started) { 250428b7ca2SJustin T. Gibbs /* 251428b7ca2SJustin T. Gibbs * Suspend other CPUs. This prevents IPIs while we 252428b7ca2SJustin T. Gibbs * are resuming, and will allow us to reset per-cpu 253428b7ca2SJustin T. Gibbs * vcpu_info on resume. 254428b7ca2SJustin T. Gibbs */ 255428b7ca2SJustin T. Gibbs cpu_suspend_map = all_cpus; 256428b7ca2SJustin T. Gibbs CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 257428b7ca2SJustin T. Gibbs if (!CPU_EMPTY(&cpu_suspend_map)) 258428b7ca2SJustin T. Gibbs suspend_cpus(cpu_suspend_map); 259428b7ca2SJustin T. Gibbs } 260428b7ca2SJustin T. Gibbs #endif 261*fdce57a0SJohn Baldwin #endif 262428b7ca2SJustin T. Gibbs 263ff662b5cSJustin T. Gibbs /* 264ff662b5cSJustin T. Gibbs * Prevent any races with evtchn_interrupt() handler. 265ff662b5cSJustin T. Gibbs */ 266ff662b5cSJustin T. Gibbs disable_intr(); 26776acc41fSJustin T. Gibbs intr_suspend(); 268428b7ca2SJustin T. Gibbs xen_hvm_suspend(); 269ff662b5cSJustin T. Gibbs 270ff662b5cSJustin T. Gibbs suspend_cancelled = HYPERVISOR_suspend(0); 27176acc41fSJustin T. Gibbs 272428b7ca2SJustin T. Gibbs xen_hvm_resume(suspend_cancelled != 0); 273428b7ca2SJustin T. Gibbs intr_resume(suspend_cancelled != 0); 274428b7ca2SJustin T. Gibbs enable_intr(); 275ff662b5cSJustin T. Gibbs 276ff662b5cSJustin T. Gibbs /* 277428b7ca2SJustin T. Gibbs * Reset grant table info. 278ff662b5cSJustin T. Gibbs */ 279a8f2f559SRoger Pau Monné gnttab_resume(NULL); 280428b7ca2SJustin T. Gibbs 281428b7ca2SJustin T. Gibbs #ifdef SMP 282b406166fSJohn Baldwin if (!CPU_EMPTY(&cpu_suspend_map)) { 283428b7ca2SJustin T. Gibbs /* 284428b7ca2SJustin T. Gibbs * Now that event channels have been initialized, 285428b7ca2SJustin T. Gibbs * resume CPUs. 286428b7ca2SJustin T. Gibbs */ 287428b7ca2SJustin T. Gibbs resume_cpus(cpu_suspend_map); 2884ea0b4adSRoger Pau Monné /* Send an IPI_BITMAP in case there are pending bitmap IPIs. */ 2894ea0b4adSRoger Pau Monné lapic_ipi_vectored(IPI_BITMAP_VECTOR, APIC_IPI_DEST_ALL); 290428b7ca2SJustin T. Gibbs } 291428b7ca2SJustin T. Gibbs #endif 292ff662b5cSJustin T. Gibbs 293ff662b5cSJustin T. Gibbs /* 294ff662b5cSJustin T. Gibbs * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or 295ff662b5cSJustin T. Gibbs * similar. 296ff662b5cSJustin T. Gibbs */ 297ff662b5cSJustin T. Gibbs DEVICE_RESUME(root_bus); 2982ca7463bSJustin T. Gibbs mtx_unlock(&Giant); 2992ca7463bSJustin T. Gibbs 3006e2a4a5fSRoger Pau Monné /* 3016e2a4a5fSRoger Pau Monné * Warm up timecounter again and reset system clock. 3026e2a4a5fSRoger Pau Monné */ 3036e2a4a5fSRoger Pau Monné timecounter->tc_get_timecount(timecounter); 3046e2a4a5fSRoger Pau Monné timecounter->tc_get_timecount(timecounter); 3056e2a4a5fSRoger Pau Monné inittodr(time_second); 3066e2a4a5fSRoger Pau Monné 307*fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 308*fdce57a0SJohn Baldwin thread_lock(curthread); 309*fdce57a0SJohn Baldwin sched_unbind(curthread); 310*fdce57a0SJohn Baldwin thread_unlock(curthread); 311*fdce57a0SJohn Baldwin #else 312428b7ca2SJustin T. Gibbs if (smp_started) { 313428b7ca2SJustin T. Gibbs thread_lock(curthread); 314428b7ca2SJustin T. Gibbs sched_unbind(curthread); 315428b7ca2SJustin T. Gibbs thread_unlock(curthread); 316428b7ca2SJustin T. Gibbs } 317*fdce57a0SJohn Baldwin #endif 318428b7ca2SJustin T. Gibbs 3196e2a4a5fSRoger Pau Monné resume_all_proc(); 3206e2a4a5fSRoger Pau Monné 3212ca7463bSJustin T. Gibbs EVENTHANDLER_INVOKE(power_resume); 322428b7ca2SJustin T. Gibbs 323428b7ca2SJustin T. Gibbs if (bootverbose) 324428b7ca2SJustin T. Gibbs printf("System resumed after suspension\n"); 325428b7ca2SJustin T. Gibbs 326ff662b5cSJustin T. Gibbs } 327ff662b5cSJustin T. Gibbs 328ff662b5cSJustin T. Gibbs static void 329ff662b5cSJustin T. Gibbs xctrl_crash() 330ff662b5cSJustin T. Gibbs { 331ff662b5cSJustin T. Gibbs panic("Xen directed crash"); 332ff662b5cSJustin T. Gibbs } 333ff662b5cSJustin T. Gibbs 334bd851e63SRoger Pau Monné static void 335bd851e63SRoger Pau Monné xen_pv_shutdown_final(void *arg, int howto) 336bd851e63SRoger Pau Monné { 337bd851e63SRoger Pau Monné /* 338bd851e63SRoger Pau Monné * Inform the hypervisor that shutdown is complete. 339bd851e63SRoger Pau Monné * This is not necessary in HVM domains since Xen 340bd851e63SRoger Pau Monné * emulates ACPI in that mode and FreeBSD's ACPI 341bd851e63SRoger Pau Monné * support will request this transition. 342bd851e63SRoger Pau Monné */ 343bd851e63SRoger Pau Monné if (howto & (RB_HALT | RB_POWEROFF)) 344bd851e63SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_poweroff); 345bd851e63SRoger Pau Monné else 346bd851e63SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_reboot); 347bd851e63SRoger Pau Monné } 348bd851e63SRoger Pau Monné 349ff662b5cSJustin T. Gibbs /*------------------------------ Event Reception -----------------------------*/ 350ff662b5cSJustin T. Gibbs static void 351ff662b5cSJustin T. Gibbs xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) 352ff662b5cSJustin T. Gibbs { 353dcceabd3SMarius Strobl const struct xctrl_shutdown_reason *reason; 354dcceabd3SMarius Strobl const struct xctrl_shutdown_reason *last_reason; 355ff662b5cSJustin T. Gibbs char *result; 356ff662b5cSJustin T. Gibbs int error; 357ff662b5cSJustin T. Gibbs int result_len; 358ff662b5cSJustin T. Gibbs 359ff662b5cSJustin T. Gibbs error = xs_read(XST_NIL, "control", "shutdown", 360ff662b5cSJustin T. Gibbs &result_len, (void **)&result); 361ff662b5cSJustin T. Gibbs if (error != 0) 362ff662b5cSJustin T. Gibbs return; 363ff662b5cSJustin T. Gibbs 364ff662b5cSJustin T. Gibbs reason = xctrl_shutdown_reasons; 365dcceabd3SMarius Strobl last_reason = reason + nitems(xctrl_shutdown_reasons); 366ff662b5cSJustin T. Gibbs while (reason < last_reason) { 367ff662b5cSJustin T. Gibbs 368ff662b5cSJustin T. Gibbs if (!strcmp(result, reason->name)) { 369ff662b5cSJustin T. Gibbs reason->handler(); 370ff662b5cSJustin T. Gibbs break; 371ff662b5cSJustin T. Gibbs } 372ff662b5cSJustin T. Gibbs reason++; 373ff662b5cSJustin T. Gibbs } 374ff662b5cSJustin T. Gibbs 375ff662b5cSJustin T. Gibbs free(result, M_XENSTORE); 376ff662b5cSJustin T. Gibbs } 377ff662b5cSJustin T. Gibbs 378ff662b5cSJustin T. Gibbs /*------------------ Private Device Attachment Functions --------------------*/ 379ff662b5cSJustin T. Gibbs /** 380ff662b5cSJustin T. Gibbs * \brief Identify instances of this device type in the system. 381ff662b5cSJustin T. Gibbs * 382ff662b5cSJustin T. Gibbs * \param driver The driver performing this identify action. 383ff662b5cSJustin T. Gibbs * \param parent The NewBus parent device for any devices this method adds. 384ff662b5cSJustin T. Gibbs */ 385ff662b5cSJustin T. Gibbs static void 386ff662b5cSJustin T. Gibbs xctrl_identify(driver_t *driver __unused, device_t parent) 387ff662b5cSJustin T. Gibbs { 388ff662b5cSJustin T. Gibbs /* 389ff662b5cSJustin T. Gibbs * A single device instance for our driver is always present 390ff662b5cSJustin T. Gibbs * in a system operating under Xen. 391ff662b5cSJustin T. Gibbs */ 392ff662b5cSJustin T. Gibbs BUS_ADD_CHILD(parent, 0, driver->name, 0); 393ff662b5cSJustin T. Gibbs } 394ff662b5cSJustin T. Gibbs 395ff662b5cSJustin T. Gibbs /** 396453130d9SPedro F. Giffuni * \brief Probe for the existence of the Xen Control device 397ff662b5cSJustin T. Gibbs * 398ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control instance. 399ff662b5cSJustin T. Gibbs * 400ff662b5cSJustin T. Gibbs * \return Always returns 0 indicating success. 401ff662b5cSJustin T. Gibbs */ 402ff662b5cSJustin T. Gibbs static int 403ff662b5cSJustin T. Gibbs xctrl_probe(device_t dev) 404ff662b5cSJustin T. Gibbs { 405ff662b5cSJustin T. Gibbs device_set_desc(dev, "Xen Control Device"); 406ff662b5cSJustin T. Gibbs 4072f9ec994SRoger Pau Monné return (BUS_PROBE_NOWILDCARD); 408ff662b5cSJustin T. Gibbs } 409ff662b5cSJustin T. Gibbs 410ff662b5cSJustin T. Gibbs /** 411ff662b5cSJustin T. Gibbs * \brief Attach the Xen control device. 412ff662b5cSJustin T. Gibbs * 413ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control instance. 414ff662b5cSJustin T. Gibbs * 415ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the 416ff662b5cSJustin T. Gibbs * type of failure. 417ff662b5cSJustin T. Gibbs */ 418ff662b5cSJustin T. Gibbs static int 419ff662b5cSJustin T. Gibbs xctrl_attach(device_t dev) 420ff662b5cSJustin T. Gibbs { 421ff662b5cSJustin T. Gibbs struct xctrl_softc *xctrl; 422ff662b5cSJustin T. Gibbs 423ff662b5cSJustin T. Gibbs xctrl = device_get_softc(dev); 424ff662b5cSJustin T. Gibbs 425ff662b5cSJustin T. Gibbs /* Activate watch */ 426ff662b5cSJustin T. Gibbs xctrl->xctrl_watch.node = "control/shutdown"; 427ff662b5cSJustin T. Gibbs xctrl->xctrl_watch.callback = xctrl_on_watch_event; 428283d6f72SJustin T. Gibbs xctrl->xctrl_watch.callback_data = (uintptr_t)xctrl; 429ff662b5cSJustin T. Gibbs xs_register_watch(&xctrl->xctrl_watch); 430ff662b5cSJustin T. Gibbs 431bd851e63SRoger Pau Monné if (xen_pv_domain()) 432ff662b5cSJustin T. Gibbs EVENTHANDLER_REGISTER(shutdown_final, xen_pv_shutdown_final, NULL, 433ff662b5cSJustin T. Gibbs SHUTDOWN_PRI_LAST); 434ff662b5cSJustin T. Gibbs 435ff662b5cSJustin T. Gibbs return (0); 436ff662b5cSJustin T. Gibbs } 437ff662b5cSJustin T. Gibbs 438ff662b5cSJustin T. Gibbs /** 439ff662b5cSJustin T. Gibbs * \brief Detach the Xen control device. 440ff662b5cSJustin T. Gibbs * 441ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control device instance. 442ff662b5cSJustin T. Gibbs * 443ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the 444ff662b5cSJustin T. Gibbs * type of failure. 445ff662b5cSJustin T. Gibbs */ 446ff662b5cSJustin T. Gibbs static int 447ff662b5cSJustin T. Gibbs xctrl_detach(device_t dev) 448ff662b5cSJustin T. Gibbs { 449ff662b5cSJustin T. Gibbs struct xctrl_softc *xctrl; 450ff662b5cSJustin T. Gibbs 451ff662b5cSJustin T. Gibbs xctrl = device_get_softc(dev); 452ff662b5cSJustin T. Gibbs 453ff662b5cSJustin T. Gibbs /* Release watch */ 454ff662b5cSJustin T. Gibbs xs_unregister_watch(&xctrl->xctrl_watch); 455ff662b5cSJustin T. Gibbs 456ff662b5cSJustin T. Gibbs return (0); 457ff662b5cSJustin T. Gibbs } 458ff662b5cSJustin T. Gibbs 459ff662b5cSJustin T. Gibbs /*-------------------- Private Device Attachment Data -----------------------*/ 460ff662b5cSJustin T. Gibbs static device_method_t xctrl_methods[] = { 461ff662b5cSJustin T. Gibbs /* Device interface */ 462ff662b5cSJustin T. Gibbs DEVMETHOD(device_identify, xctrl_identify), 463ff662b5cSJustin T. Gibbs DEVMETHOD(device_probe, xctrl_probe), 464ff662b5cSJustin T. Gibbs DEVMETHOD(device_attach, xctrl_attach), 465ff662b5cSJustin T. Gibbs DEVMETHOD(device_detach, xctrl_detach), 466ff662b5cSJustin T. Gibbs 467dcceabd3SMarius Strobl DEVMETHOD_END 468ff662b5cSJustin T. Gibbs }; 469ff662b5cSJustin T. Gibbs 470ff662b5cSJustin T. Gibbs DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc)); 471ff662b5cSJustin T. Gibbs devclass_t xctrl_devclass; 472ff662b5cSJustin T. Gibbs 473dcceabd3SMarius Strobl DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, NULL, NULL); 474