1ff662b5cSJustin T. Gibbs /*- 2*9a73b5b1SRoger Pau Monné * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4ff662b5cSJustin T. Gibbs * Copyright (c) 2010 Justin T. Gibbs, Spectra Logic Corporation 5ff662b5cSJustin T. Gibbs * All rights reserved. 6ff662b5cSJustin T. Gibbs * 7ff662b5cSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 8ff662b5cSJustin T. Gibbs * modification, are permitted provided that the following conditions 9ff662b5cSJustin T. Gibbs * are met: 10ff662b5cSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 11ff662b5cSJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 12ff662b5cSJustin T. Gibbs * without modification. 13ff662b5cSJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14ff662b5cSJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 15ff662b5cSJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 16ff662b5cSJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 17ff662b5cSJustin T. Gibbs * binary redistribution. 18ff662b5cSJustin T. Gibbs * 19ff662b5cSJustin T. Gibbs * NO WARRANTY 20ff662b5cSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21ff662b5cSJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ff662b5cSJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 23ff662b5cSJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24ff662b5cSJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25ff662b5cSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26ff662b5cSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27ff662b5cSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28ff662b5cSJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29ff662b5cSJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30ff662b5cSJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 31ff662b5cSJustin T. Gibbs */ 32ff662b5cSJustin T. Gibbs 33ff662b5cSJustin T. Gibbs /*- 34ff662b5cSJustin T. Gibbs * HVM suspend/resume support: 35ff662b5cSJustin T. Gibbs * 36ff662b5cSJustin T. Gibbs * Copyright (c) 2008 Citrix Systems, Inc. 37ff662b5cSJustin T. Gibbs * All rights reserved. 38ff662b5cSJustin T. Gibbs * 39ff662b5cSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 40ff662b5cSJustin T. Gibbs * modification, are permitted provided that the following conditions 41ff662b5cSJustin T. Gibbs * are met: 42ff662b5cSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 43ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 44ff662b5cSJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 45ff662b5cSJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 46ff662b5cSJustin T. Gibbs * documentation and/or other materials provided with the distribution. 47ff662b5cSJustin T. Gibbs * 48ff662b5cSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 49ff662b5cSJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50ff662b5cSJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51ff662b5cSJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 52ff662b5cSJustin T. Gibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53ff662b5cSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54ff662b5cSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55ff662b5cSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56ff662b5cSJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57ff662b5cSJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58ff662b5cSJustin T. Gibbs * SUCH DAMAGE. 59ff662b5cSJustin T. Gibbs */ 60ff662b5cSJustin T. Gibbs #include <sys/cdefs.h> 61ff662b5cSJustin T. Gibbs /** 62ff662b5cSJustin T. Gibbs * \file control.c 63ff662b5cSJustin T. Gibbs * 64ff662b5cSJustin T. Gibbs * \brief Device driver to repond to control domain events that impact 65ff662b5cSJustin T. Gibbs * this VM. 66ff662b5cSJustin T. Gibbs */ 67ff662b5cSJustin T. Gibbs 68ff662b5cSJustin T. Gibbs #include <sys/param.h> 69ff662b5cSJustin T. Gibbs #include <sys/systm.h> 70ff662b5cSJustin T. Gibbs #include <sys/kernel.h> 71ff662b5cSJustin T. Gibbs #include <sys/malloc.h> 72ff662b5cSJustin T. Gibbs 73ff662b5cSJustin T. Gibbs #include <sys/bio.h> 74ff662b5cSJustin T. Gibbs #include <sys/bus.h> 75ff662b5cSJustin T. Gibbs #include <sys/conf.h> 76ff662b5cSJustin T. Gibbs #include <sys/disk.h> 77ff662b5cSJustin T. Gibbs #include <sys/fcntl.h> 78ff662b5cSJustin T. Gibbs #include <sys/filedesc.h> 79ff662b5cSJustin T. Gibbs #include <sys/kdb.h> 80ff662b5cSJustin T. Gibbs #include <sys/module.h> 81f1084587SKonstantin Belousov #include <sys/mount.h> 82ff662b5cSJustin T. Gibbs #include <sys/namei.h> 83ff662b5cSJustin T. Gibbs #include <sys/proc.h> 84ff662b5cSJustin T. Gibbs #include <sys/reboot.h> 85ff662b5cSJustin T. Gibbs #include <sys/rman.h> 862ca7463bSJustin T. Gibbs #include <sys/sched.h> 87ff662b5cSJustin T. Gibbs #include <sys/taskqueue.h> 88ff662b5cSJustin T. Gibbs #include <sys/types.h> 89ff662b5cSJustin T. Gibbs #include <sys/vnode.h> 90ff662b5cSJustin T. Gibbs #include <sys/sched.h> 91ff662b5cSJustin T. Gibbs #include <sys/smp.h> 92428b7ca2SJustin T. Gibbs #include <sys/eventhandler.h> 936e2a4a5fSRoger Pau Monné #include <sys/timetc.h> 94ff662b5cSJustin T. Gibbs 95ff662b5cSJustin T. Gibbs #include <geom/geom.h> 96ff662b5cSJustin T. Gibbs 97ff662b5cSJustin T. Gibbs #include <machine/_inttypes.h> 9846c46eddSJulien Grall #if defined(__amd64__) || defined(__i386__) 9976acc41fSJustin T. Gibbs #include <machine/intr_machdep.h> 100ff662b5cSJustin T. Gibbs 10115226522SRoger Pau Monné #include <x86/apicvar.h> 102d3705b5aSElliott Mitchell #endif 10315226522SRoger Pau Monné 104ff662b5cSJustin T. Gibbs #include <vm/vm.h> 105ff662b5cSJustin T. Gibbs #include <vm/vm_extern.h> 106ff662b5cSJustin T. Gibbs #include <vm/vm_kern.h> 107ff662b5cSJustin T. Gibbs 10876acc41fSJustin T. Gibbs #include <xen/xen-os.h> 109ff662b5cSJustin T. Gibbs #include <xen/blkif.h> 110ff662b5cSJustin T. Gibbs #include <xen/evtchn.h> 111ff662b5cSJustin T. Gibbs #include <xen/gnttab.h> 112ff662b5cSJustin T. Gibbs #include <xen/xen_intr.h> 113ff662b5cSJustin T. Gibbs 114428b7ca2SJustin T. Gibbs #include <xen/hvm.h> 115428b7ca2SJustin T. Gibbs 116ad7dd514SElliott Mitchell #include <contrib/xen/event_channel.h> 117ad7dd514SElliott Mitchell #include <contrib/xen/grant_table.h> 118ff662b5cSJustin T. Gibbs 119ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h> 120ff662b5cSJustin T. Gibbs 1218dee0e9bSRoger Pau Monné bool xen_suspend_cancelled; 122ff662b5cSJustin T. Gibbs /*--------------------------- Forward Declarations --------------------------*/ 123ff662b5cSJustin T. Gibbs /** Function signature for shutdown event handlers. */ 124ff662b5cSJustin T. Gibbs typedef void (xctrl_shutdown_handler_t)(void); 125ff662b5cSJustin T. Gibbs 126ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_poweroff; 127ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_reboot; 128ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_suspend; 129ff662b5cSJustin T. Gibbs static xctrl_shutdown_handler_t xctrl_crash; 130ff662b5cSJustin T. Gibbs 131ff662b5cSJustin T. Gibbs /*-------------------------- Private Data Structures -------------------------*/ 132ff662b5cSJustin T. Gibbs /** Element type for lookup table of event name to handler. */ 133ff662b5cSJustin T. Gibbs struct xctrl_shutdown_reason { 134ff662b5cSJustin T. Gibbs const char *name; 135ff662b5cSJustin T. Gibbs xctrl_shutdown_handler_t *handler; 136ff662b5cSJustin T. Gibbs }; 137ff662b5cSJustin T. Gibbs 138ff662b5cSJustin T. Gibbs /** Lookup table for shutdown event name to handler. */ 139dcceabd3SMarius Strobl static const struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = { 140ff662b5cSJustin T. Gibbs { "poweroff", xctrl_poweroff }, 141ff662b5cSJustin T. Gibbs { "reboot", xctrl_reboot }, 142ff662b5cSJustin T. Gibbs { "suspend", xctrl_suspend }, 143ff662b5cSJustin T. Gibbs { "crash", xctrl_crash }, 1444c85fcfaSJustin T. Gibbs { "halt", xctrl_poweroff }, 145ff662b5cSJustin T. Gibbs }; 146ff662b5cSJustin T. Gibbs 147ff662b5cSJustin T. Gibbs struct xctrl_softc { 148ff662b5cSJustin T. Gibbs struct xs_watch xctrl_watch; 149ff662b5cSJustin T. Gibbs }; 150ff662b5cSJustin T. Gibbs 151ff662b5cSJustin T. Gibbs /*------------------------------ Event Handlers ------------------------------*/ 152ff662b5cSJustin T. Gibbs static void 153a6c80304SDimitry Andric xctrl_poweroff(void) 154ff662b5cSJustin T. Gibbs { 155ff662b5cSJustin T. Gibbs shutdown_nice(RB_POWEROFF|RB_HALT); 156ff662b5cSJustin T. Gibbs } 157ff662b5cSJustin T. Gibbs 158ff662b5cSJustin T. Gibbs static void 159a6c80304SDimitry Andric xctrl_reboot(void) 160ff662b5cSJustin T. Gibbs { 161ff662b5cSJustin T. Gibbs shutdown_nice(0); 162ff662b5cSJustin T. Gibbs } 163ff662b5cSJustin T. Gibbs 16446c46eddSJulien Grall #if !defined(__amd64__) && !defined(__i386__) 16546c46eddSJulien Grall static void 166a6c80304SDimitry Andric xctrl_suspend(void) 16746c46eddSJulien Grall { 16846c46eddSJulien Grall printf("WARNING: xen/control: Suspend not supported!\n"); 16946c46eddSJulien Grall } 17046c46eddSJulien Grall #else /* __amd64__ || __i386__ */ 171ff662b5cSJustin T. Gibbs static void 172a6c80304SDimitry Andric xctrl_suspend(void) 173ff662b5cSJustin T. Gibbs { 174428b7ca2SJustin T. Gibbs #ifdef SMP 175428b7ca2SJustin T. Gibbs cpuset_t cpu_suspend_map; 176428b7ca2SJustin T. Gibbs #endif 177ff662b5cSJustin T. Gibbs 1786e2a4a5fSRoger Pau Monné EVENTHANDLER_INVOKE(power_suspend_early); 17941716b8dSRoger Pau Monné xs_lock(); 1806e2a4a5fSRoger Pau Monné stop_all_proc(); 18141716b8dSRoger Pau Monné xs_unlock(); 182f1084587SKonstantin Belousov suspend_all_fs(); 1832ca7463bSJustin T. Gibbs EVENTHANDLER_INVOKE(power_suspend); 1842ca7463bSJustin T. Gibbs 185fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 186fdce57a0SJohn Baldwin MPASS(mp_ncpus == 1 || smp_started); 187fdce57a0SJohn Baldwin thread_lock(curthread); 188fdce57a0SJohn Baldwin sched_bind(curthread, 0); 189fdce57a0SJohn Baldwin thread_unlock(curthread); 190fdce57a0SJohn Baldwin #else 191428b7ca2SJustin T. Gibbs if (smp_started) { 192428b7ca2SJustin T. Gibbs thread_lock(curthread); 193428b7ca2SJustin T. Gibbs sched_bind(curthread, 0); 194428b7ca2SJustin T. Gibbs thread_unlock(curthread); 195428b7ca2SJustin T. Gibbs } 196fdce57a0SJohn Baldwin #endif 197428b7ca2SJustin T. Gibbs KASSERT((PCPU_GET(cpuid) == 0), ("Not running on CPU#0")); 198428b7ca2SJustin T. Gibbs 199428b7ca2SJustin T. Gibbs /* 200c6df6f53SWarner Losh * Be sure to hold Giant across DEVICE_SUSPEND/RESUME. 2012ca7463bSJustin T. Gibbs */ 202c6df6f53SWarner Losh bus_topo_lock(); 203dcceabd3SMarius Strobl if (DEVICE_SUSPEND(root_bus) != 0) { 204c6df6f53SWarner Losh bus_topo_unlock(); 205dcceabd3SMarius Strobl printf("%s: device_suspend failed\n", __func__); 206ff662b5cSJustin T. Gibbs return; 207ff662b5cSJustin T. Gibbs } 208ff662b5cSJustin T. Gibbs 209428b7ca2SJustin T. Gibbs #ifdef SMP 210fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 211fdce57a0SJohn Baldwin /* 212fdce57a0SJohn Baldwin * Suspend other CPUs. This prevents IPIs while we 213fdce57a0SJohn Baldwin * are resuming, and will allow us to reset per-cpu 214fdce57a0SJohn Baldwin * vcpu_info on resume. 215fdce57a0SJohn Baldwin */ 216fdce57a0SJohn Baldwin cpu_suspend_map = all_cpus; 217fdce57a0SJohn Baldwin CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 218fdce57a0SJohn Baldwin if (!CPU_EMPTY(&cpu_suspend_map)) 219fdce57a0SJohn Baldwin suspend_cpus(cpu_suspend_map); 220fdce57a0SJohn Baldwin #else 221faf8ff5fSDimitry Andric CPU_ZERO(&cpu_suspend_map); /* silence gcc */ 222428b7ca2SJustin T. Gibbs if (smp_started) { 223428b7ca2SJustin T. Gibbs /* 224428b7ca2SJustin T. Gibbs * Suspend other CPUs. This prevents IPIs while we 225428b7ca2SJustin T. Gibbs * are resuming, and will allow us to reset per-cpu 226428b7ca2SJustin T. Gibbs * vcpu_info on resume. 227428b7ca2SJustin T. Gibbs */ 228428b7ca2SJustin T. Gibbs cpu_suspend_map = all_cpus; 229428b7ca2SJustin T. Gibbs CPU_CLR(PCPU_GET(cpuid), &cpu_suspend_map); 230428b7ca2SJustin T. Gibbs if (!CPU_EMPTY(&cpu_suspend_map)) 231428b7ca2SJustin T. Gibbs suspend_cpus(cpu_suspend_map); 232428b7ca2SJustin T. Gibbs } 233428b7ca2SJustin T. Gibbs #endif 234fdce57a0SJohn Baldwin #endif 235428b7ca2SJustin T. Gibbs 236ff662b5cSJustin T. Gibbs /* 237ff662b5cSJustin T. Gibbs * Prevent any races with evtchn_interrupt() handler. 238ff662b5cSJustin T. Gibbs */ 239ff662b5cSJustin T. Gibbs disable_intr(); 24076acc41fSJustin T. Gibbs intr_suspend(); 241428b7ca2SJustin T. Gibbs xen_hvm_suspend(); 242ff662b5cSJustin T. Gibbs 2438dee0e9bSRoger Pau Monné xen_suspend_cancelled = !!HYPERVISOR_suspend(0); 24476acc41fSJustin T. Gibbs 2458dee0e9bSRoger Pau Monné if (!xen_suspend_cancelled) { 2468dee0e9bSRoger Pau Monné xen_hvm_resume(false); 2478dee0e9bSRoger Pau Monné } 2488dee0e9bSRoger Pau Monné intr_resume(xen_suspend_cancelled != 0); 249428b7ca2SJustin T. Gibbs enable_intr(); 250ff662b5cSJustin T. Gibbs 251ff662b5cSJustin T. Gibbs /* 252428b7ca2SJustin T. Gibbs * Reset grant table info. 253ff662b5cSJustin T. Gibbs */ 2548dee0e9bSRoger Pau Monné if (!xen_suspend_cancelled) { 255a8f2f559SRoger Pau Monné gnttab_resume(NULL); 2568dee0e9bSRoger Pau Monné } 257428b7ca2SJustin T. Gibbs 258428b7ca2SJustin T. Gibbs #ifdef SMP 259b406166fSJohn Baldwin if (!CPU_EMPTY(&cpu_suspend_map)) { 260428b7ca2SJustin T. Gibbs /* 261428b7ca2SJustin T. Gibbs * Now that event channels have been initialized, 262428b7ca2SJustin T. Gibbs * resume CPUs. 263428b7ca2SJustin T. Gibbs */ 264428b7ca2SJustin T. Gibbs resume_cpus(cpu_suspend_map); 265d3705b5aSElliott Mitchell #if defined(__amd64__) || defined(__i386__) 2664ea0b4adSRoger Pau Monné /* Send an IPI_BITMAP in case there are pending bitmap IPIs. */ 2674ea0b4adSRoger Pau Monné lapic_ipi_vectored(IPI_BITMAP_VECTOR, APIC_IPI_DEST_ALL); 268d3705b5aSElliott Mitchell #endif 269428b7ca2SJustin T. Gibbs } 270428b7ca2SJustin T. Gibbs #endif 271ff662b5cSJustin T. Gibbs 272ff662b5cSJustin T. Gibbs /* 273ff662b5cSJustin T. Gibbs * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or 274ff662b5cSJustin T. Gibbs * similar. 275ff662b5cSJustin T. Gibbs */ 276ff662b5cSJustin T. Gibbs DEVICE_RESUME(root_bus); 277c6df6f53SWarner Losh bus_topo_unlock(); 2782ca7463bSJustin T. Gibbs 2796e2a4a5fSRoger Pau Monné /* 2806e2a4a5fSRoger Pau Monné * Warm up timecounter again and reset system clock. 2816e2a4a5fSRoger Pau Monné */ 2826e2a4a5fSRoger Pau Monné timecounter->tc_get_timecount(timecounter); 2836e2a4a5fSRoger Pau Monné inittodr(time_second); 2846e2a4a5fSRoger Pau Monné 285fdce57a0SJohn Baldwin #ifdef EARLY_AP_STARTUP 286fdce57a0SJohn Baldwin thread_lock(curthread); 287fdce57a0SJohn Baldwin sched_unbind(curthread); 288fdce57a0SJohn Baldwin thread_unlock(curthread); 289fdce57a0SJohn Baldwin #else 290428b7ca2SJustin T. Gibbs if (smp_started) { 291428b7ca2SJustin T. Gibbs thread_lock(curthread); 292428b7ca2SJustin T. Gibbs sched_unbind(curthread); 293428b7ca2SJustin T. Gibbs thread_unlock(curthread); 294428b7ca2SJustin T. Gibbs } 295fdce57a0SJohn Baldwin #endif 296428b7ca2SJustin T. Gibbs 297f1084587SKonstantin Belousov resume_all_fs(); 2986e2a4a5fSRoger Pau Monné resume_all_proc(); 2996e2a4a5fSRoger Pau Monné 3002ca7463bSJustin T. Gibbs EVENTHANDLER_INVOKE(power_resume); 301428b7ca2SJustin T. Gibbs 302428b7ca2SJustin T. Gibbs if (bootverbose) 303428b7ca2SJustin T. Gibbs printf("System resumed after suspension\n"); 304428b7ca2SJustin T. Gibbs 305ff662b5cSJustin T. Gibbs } 30646c46eddSJulien Grall #endif /* __amd64__ || __i386__ */ 307ff662b5cSJustin T. Gibbs 308ff662b5cSJustin T. Gibbs static void 309a6c80304SDimitry Andric xctrl_crash(void) 310ff662b5cSJustin T. Gibbs { 311ff662b5cSJustin T. Gibbs panic("Xen directed crash"); 312ff662b5cSJustin T. Gibbs } 313ff662b5cSJustin T. Gibbs 314bd851e63SRoger Pau Monné static void 3159e0b0f5dSMitchell Horne xctrl_shutdown_final(void *arg, int howto) 316bd851e63SRoger Pau Monné { 3179e0b0f5dSMitchell Horne /* 3189e0b0f5dSMitchell Horne * Inform the hypervisor that shutdown is complete, and specify the 3199e0b0f5dSMitchell Horne * nature of the shutdown. RB_HALT is not handled by this function. 3209e0b0f5dSMitchell Horne */ 3219e0b0f5dSMitchell Horne if (KERNEL_PANICKED()) 3229e0b0f5dSMitchell Horne HYPERVISOR_shutdown(SHUTDOWN_crash); 3239e0b0f5dSMitchell Horne else if ((howto & RB_POWEROFF) != 0) 324bd851e63SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_poweroff); 3259e0b0f5dSMitchell Horne else if ((howto & RB_HALT) == 0) 3269e0b0f5dSMitchell Horne /* RB_POWERCYCLE or regular reset. */ 327bd851e63SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_reboot); 328bd851e63SRoger Pau Monné } 329bd851e63SRoger Pau Monné 330ff662b5cSJustin T. Gibbs /*------------------------------ Event Reception -----------------------------*/ 331ff662b5cSJustin T. Gibbs static void 332ff662b5cSJustin T. Gibbs xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) 333ff662b5cSJustin T. Gibbs { 334dcceabd3SMarius Strobl const struct xctrl_shutdown_reason *reason; 335dcceabd3SMarius Strobl const struct xctrl_shutdown_reason *last_reason; 336ff662b5cSJustin T. Gibbs char *result; 337ff662b5cSJustin T. Gibbs int error; 338ff662b5cSJustin T. Gibbs int result_len; 339ff662b5cSJustin T. Gibbs 340ff662b5cSJustin T. Gibbs error = xs_read(XST_NIL, "control", "shutdown", 341ff662b5cSJustin T. Gibbs &result_len, (void **)&result); 34206592d60SRoger Pau Monné if (error != 0 || result_len == 0) 343ff662b5cSJustin T. Gibbs return; 344ff662b5cSJustin T. Gibbs 34506798cf5SRoger Pau Monné /* Acknowledge the request by writing back an empty string. */ 34606798cf5SRoger Pau Monné error = xs_write(XST_NIL, "control", "shutdown", ""); 34706798cf5SRoger Pau Monné if (error != 0) 34806798cf5SRoger Pau Monné printf("unable to ack shutdown request, proceeding anyway\n"); 34906798cf5SRoger Pau Monné 350ff662b5cSJustin T. Gibbs reason = xctrl_shutdown_reasons; 351dcceabd3SMarius Strobl last_reason = reason + nitems(xctrl_shutdown_reasons); 352ff662b5cSJustin T. Gibbs while (reason < last_reason) { 353ff662b5cSJustin T. Gibbs if (!strcmp(result, reason->name)) { 354ff662b5cSJustin T. Gibbs reason->handler(); 355ff662b5cSJustin T. Gibbs break; 356ff662b5cSJustin T. Gibbs } 357ff662b5cSJustin T. Gibbs reason++; 358ff662b5cSJustin T. Gibbs } 359ff662b5cSJustin T. Gibbs 360ff662b5cSJustin T. Gibbs free(result, M_XENSTORE); 361ff662b5cSJustin T. Gibbs } 362ff662b5cSJustin T. Gibbs 363ff662b5cSJustin T. Gibbs /*------------------ Private Device Attachment Functions --------------------*/ 3649dd5105fSRoger Pau Monné 3659dd5105fSRoger Pau Monné static void 3669dd5105fSRoger Pau Monné notify_support(void) 3679dd5105fSRoger Pau Monné { 3689dd5105fSRoger Pau Monné /* 3699dd5105fSRoger Pau Monné * Notify kernel is ready to handle "control/shutdown" events. Ignore 3709dd5105fSRoger Pau Monné * errors if the nodes haven't been created by the toolstack, as the 3719dd5105fSRoger Pau Monné * parent "control" directory should be read-only for the guest. 3729dd5105fSRoger Pau Monné */ 3739dd5105fSRoger Pau Monné xs_write(XST_NIL, "control", "feature-poweroff", "1"); 3749dd5105fSRoger Pau Monné xs_write(XST_NIL, "control", "feature-reboot", "1"); 3759dd5105fSRoger Pau Monné xs_write(XST_NIL, "control", "feature-suspend", "1"); 3769dd5105fSRoger Pau Monné } 3779dd5105fSRoger Pau Monné 378ff662b5cSJustin T. Gibbs /** 379ff662b5cSJustin T. Gibbs * \brief Identify instances of this device type in the system. 380ff662b5cSJustin T. Gibbs * 381ff662b5cSJustin T. Gibbs * \param driver The driver performing this identify action. 382ff662b5cSJustin T. Gibbs * \param parent The NewBus parent device for any devices this method adds. 383ff662b5cSJustin T. Gibbs */ 384ff662b5cSJustin T. Gibbs static void 385d48760ffSElliott Mitchell xctrl_identify(driver_t *driver, device_t parent) 386ff662b5cSJustin T. Gibbs { 387ff662b5cSJustin T. Gibbs /* 388ff662b5cSJustin T. Gibbs * A single device instance for our driver is always present 389ff662b5cSJustin T. Gibbs * in a system operating under Xen. 390ff662b5cSJustin T. Gibbs */ 391ff662b5cSJustin T. Gibbs BUS_ADD_CHILD(parent, 0, driver->name, 0); 392ff662b5cSJustin T. Gibbs } 393ff662b5cSJustin T. Gibbs 394ff662b5cSJustin T. Gibbs /** 395453130d9SPedro F. Giffuni * \brief Probe for the existence of the Xen Control device 396ff662b5cSJustin T. Gibbs * 397ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control instance. 398ff662b5cSJustin T. Gibbs * 399ff662b5cSJustin T. Gibbs * \return Always returns 0 indicating success. 400ff662b5cSJustin T. Gibbs */ 401ff662b5cSJustin T. Gibbs static int 402ff662b5cSJustin T. Gibbs xctrl_probe(device_t dev) 403ff662b5cSJustin T. Gibbs { 404ff662b5cSJustin T. Gibbs device_set_desc(dev, "Xen Control Device"); 405ff662b5cSJustin T. Gibbs 4062f9ec994SRoger Pau Monné return (BUS_PROBE_NOWILDCARD); 407ff662b5cSJustin T. Gibbs } 408ff662b5cSJustin T. Gibbs 409ff662b5cSJustin T. Gibbs /** 410ff662b5cSJustin T. Gibbs * \brief Attach the Xen control device. 411ff662b5cSJustin T. Gibbs * 412ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control instance. 413ff662b5cSJustin T. Gibbs * 414ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the 415ff662b5cSJustin T. Gibbs * type of failure. 416ff662b5cSJustin T. Gibbs */ 417ff662b5cSJustin T. Gibbs static int 418ff662b5cSJustin T. Gibbs xctrl_attach(device_t dev) 419ff662b5cSJustin T. Gibbs { 420ff662b5cSJustin T. Gibbs struct xctrl_softc *xctrl; 421ff662b5cSJustin T. Gibbs 422ff662b5cSJustin T. Gibbs xctrl = device_get_softc(dev); 423ff662b5cSJustin T. Gibbs 424ff662b5cSJustin T. Gibbs /* Activate watch */ 425ff662b5cSJustin T. Gibbs xctrl->xctrl_watch.node = "control/shutdown"; 426ff662b5cSJustin T. Gibbs xctrl->xctrl_watch.callback = xctrl_on_watch_event; 427283d6f72SJustin T. Gibbs xctrl->xctrl_watch.callback_data = (uintptr_t)xctrl; 4284e4e43dcSRoger Pau Monné /* 4294e4e43dcSRoger Pau Monné * We don't care about the path updated, just about the value changes 4304e4e43dcSRoger Pau Monné * on that single node, hence there's no need to queue more that one 4314e4e43dcSRoger Pau Monné * event. 4324e4e43dcSRoger Pau Monné */ 4334e4e43dcSRoger Pau Monné xctrl->xctrl_watch.max_pending = 1; 434ff662b5cSJustin T. Gibbs xs_register_watch(&xctrl->xctrl_watch); 435ff662b5cSJustin T. Gibbs 4369e0b0f5dSMitchell Horne EVENTHANDLER_REGISTER(shutdown_final, xctrl_shutdown_final, NULL, 437ff662b5cSJustin T. Gibbs SHUTDOWN_PRI_LAST); 438ff662b5cSJustin T. Gibbs 4399dd5105fSRoger Pau Monné notify_support(); 4409dd5105fSRoger Pau Monné 441ff662b5cSJustin T. Gibbs return (0); 442ff662b5cSJustin T. Gibbs } 443ff662b5cSJustin T. Gibbs 444ff662b5cSJustin T. Gibbs /** 445ff662b5cSJustin T. Gibbs * \brief Detach the Xen control device. 446ff662b5cSJustin T. Gibbs * 447ff662b5cSJustin T. Gibbs * \param dev NewBus device_t for this Xen control device instance. 448ff662b5cSJustin T. Gibbs * 449ff662b5cSJustin T. Gibbs * \return On success, 0. Otherwise an errno value indicating the 450ff662b5cSJustin T. Gibbs * type of failure. 451ff662b5cSJustin T. Gibbs */ 452ff662b5cSJustin T. Gibbs static int 453ff662b5cSJustin T. Gibbs xctrl_detach(device_t dev) 454ff662b5cSJustin T. Gibbs { 455ff662b5cSJustin T. Gibbs struct xctrl_softc *xctrl; 456ff662b5cSJustin T. Gibbs 457ff662b5cSJustin T. Gibbs xctrl = device_get_softc(dev); 458ff662b5cSJustin T. Gibbs 459ff662b5cSJustin T. Gibbs /* Release watch */ 460ff662b5cSJustin T. Gibbs xs_unregister_watch(&xctrl->xctrl_watch); 461ff662b5cSJustin T. Gibbs 462ff662b5cSJustin T. Gibbs return (0); 463ff662b5cSJustin T. Gibbs } 464ff662b5cSJustin T. Gibbs 4659dd5105fSRoger Pau Monné static int 4669dd5105fSRoger Pau Monné xctrl_resume(device_t dev) 4679dd5105fSRoger Pau Monné { 4689dd5105fSRoger Pau Monné notify_support(); 4699dd5105fSRoger Pau Monné 4709dd5105fSRoger Pau Monné return (0); 4719dd5105fSRoger Pau Monné } 4729dd5105fSRoger Pau Monné 473ff662b5cSJustin T. Gibbs /*-------------------- Private Device Attachment Data -----------------------*/ 474ff662b5cSJustin T. Gibbs static device_method_t xctrl_methods[] = { 475ff662b5cSJustin T. Gibbs /* Device interface */ 476ff662b5cSJustin T. Gibbs DEVMETHOD(device_identify, xctrl_identify), 477ff662b5cSJustin T. Gibbs DEVMETHOD(device_probe, xctrl_probe), 478ff662b5cSJustin T. Gibbs DEVMETHOD(device_attach, xctrl_attach), 479ff662b5cSJustin T. Gibbs DEVMETHOD(device_detach, xctrl_detach), 4809dd5105fSRoger Pau Monné DEVMETHOD(device_resume, xctrl_resume), 481ff662b5cSJustin T. Gibbs 482dcceabd3SMarius Strobl DEVMETHOD_END 483ff662b5cSJustin T. Gibbs }; 484ff662b5cSJustin T. Gibbs 485ff662b5cSJustin T. Gibbs DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc)); 486ff662b5cSJustin T. Gibbs 487f929eb1eSJohn Baldwin DRIVER_MODULE(xctrl, xenstore, xctrl_driver, NULL, NULL); 488