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