The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/xen/control/control.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: c68e46a2e3ddeed323385186411a070f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.