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/xen/xenbus/xenbus_comms.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  * xenbus_comms.c
    3  *
    4  * Low level code to talks to Xen Store: ringbuffer and event channel.
    5  *
    6  * Copyright (C) 2005 Rusty Russell, IBM Corporation
    7  * 
    8  * This file may be distributed separately from the Linux kernel, or
    9  * incorporated into other software packages, subject to the following license:
   10  * 
   11  * Permission is hereby granted, free of charge, to any person obtaining a copy
   12  * of this source file (the "Software"), to deal in the Software without
   13  * restriction, including without limitation the rights to use, copy, modify,
   14  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   15  * and to permit persons to whom the Software is furnished to do so, subject to
   16  * the following conditions:
   17  * 
   18  * The above copyright notice and this permission notice shall be included in
   19  * all copies or substantial portions of the Software.
   20  * 
   21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   27  * IN THE SOFTWARE.
   28  */
   29 
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/8.1/sys/xen/xenbus/xenbus_comms.c 186557 2008-12-29 06:31:03Z kmacy $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <sys/sx.h>
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/syslog.h>
   43 
   44 #include <machine/xen/xen-os.h>
   45 #include <xen/hypervisor.h>
   46 
   47 #include <xen/xen_intr.h>
   48 #include <xen/evtchn.h>
   49 #include <xen/interface/io/xs_wire.h>
   50 #include <xen/xenbus/xenbus_comms.h>
   51 
   52 static unsigned int xenstore_irq;
   53 
   54 static inline struct xenstore_domain_interface *
   55 xenstore_domain_interface(void)
   56 {
   57 
   58         return (struct xenstore_domain_interface *)xen_store;
   59 }
   60 
   61 static void
   62 xb_intr(void * arg __attribute__((unused)))
   63 {
   64 
   65         wakeup(xen_store);
   66 }
   67 
   68 static int
   69 xb_check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
   70 {
   71 
   72         return ((prod - cons) <= XENSTORE_RING_SIZE);
   73 }
   74 
   75 static void *
   76 xb_get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
   77     char *buf, uint32_t *len)
   78 {
   79 
   80         *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
   81         if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
   82                 *len = XENSTORE_RING_SIZE - (prod - cons);
   83         return (buf + MASK_XENSTORE_IDX(prod));
   84 }
   85 
   86 static const void *
   87 xb_get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
   88     const char *buf, uint32_t *len)
   89 {
   90 
   91         *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
   92         if ((prod - cons) < *len)
   93                 *len = prod - cons;
   94         return (buf + MASK_XENSTORE_IDX(cons));
   95 }
   96 
   97 int
   98 xb_write(const void *tdata, unsigned len, struct lock_object *lock)
   99 {
  100         struct xenstore_domain_interface *intf = xenstore_domain_interface();
  101         XENSTORE_RING_IDX cons, prod;
  102         const char *data = (const char *)tdata;
  103         int error;
  104 
  105         while (len != 0) {
  106                 void *dst;
  107                 unsigned int avail;
  108 
  109                 while ((intf->req_prod - intf->req_cons)
  110                     == XENSTORE_RING_SIZE) {
  111                         error = _sleep(intf,
  112                             lock,
  113                             PCATCH, "xbwrite", hz/10);
  114                         if (error && error != EWOULDBLOCK)
  115                                 return (error);
  116                 }
  117 
  118                 /* Read indexes, then verify. */
  119                 cons = intf->req_cons;
  120                 prod = intf->req_prod;
  121                 mb();
  122                 if (!xb_check_indexes(cons, prod)) {
  123                         intf->req_cons = intf->req_prod = 0;
  124                         return (EIO);
  125                 }
  126 
  127                 dst = xb_get_output_chunk(cons, prod, intf->req, &avail);
  128                 if (avail == 0)
  129                         continue;
  130                 if (avail > len)
  131                         avail = len;
  132                 mb();
  133                                 
  134                 memcpy(dst, data, avail);
  135                 data += avail;
  136                 len -= avail;
  137 
  138                 /* Other side must not see new header until data is there. */
  139                 wmb();
  140                 intf->req_prod += avail;
  141 
  142                 /* This implies mb() before other side sees interrupt. */
  143                 notify_remote_via_evtchn(xen_store_evtchn);
  144         }
  145 
  146         return (0);
  147 }
  148 
  149 int
  150 xb_read(void *tdata, unsigned len, struct lock_object *lock)
  151 {
  152         struct xenstore_domain_interface *intf = xenstore_domain_interface();
  153         XENSTORE_RING_IDX cons, prod;
  154         char *data = (char *)tdata;
  155         int error;
  156 
  157         while (len != 0) {
  158                 unsigned int avail;
  159                 const char *src;
  160 
  161                 while (intf->rsp_cons == intf->rsp_prod) {
  162                         error = _sleep(intf, lock,
  163                             PCATCH, "xbread", hz/10);
  164                         if (error && error != EWOULDBLOCK)
  165                                 return (error);
  166                 }
  167                         
  168                 /* Read indexes, then verify. */
  169                 cons = intf->rsp_cons;
  170                 prod = intf->rsp_prod;
  171                 if (!xb_check_indexes(cons, prod)) {
  172                         intf->rsp_cons = intf->rsp_prod = 0;
  173                         return (EIO);
  174                 }
  175                                 
  176                 src = xb_get_input_chunk(cons, prod, intf->rsp, &avail);
  177                 if (avail == 0)
  178                         continue;
  179                 if (avail > len)
  180                         avail = len;
  181 
  182                 /* We must read header before we read data. */
  183                 rmb();
  184 
  185                 memcpy(data, src, avail);
  186                 data += avail;
  187                 len -= avail;
  188 
  189                 /* Other side must not see free space until we've copied out */
  190                 mb();
  191                 intf->rsp_cons += avail;
  192 
  193                 /* Implies mb(): they will see new header. */
  194                 notify_remote_via_evtchn(xen_store_evtchn);
  195         }
  196 
  197         return (0);
  198 }
  199 
  200 /* Set up interrupt handler off store event channel. */
  201 int
  202 xb_init_comms(void)
  203 {
  204         struct xenstore_domain_interface *intf = xenstore_domain_interface();
  205         int error;
  206 
  207         if (intf->rsp_prod != intf->rsp_cons) {
  208                 log(LOG_WARNING, "XENBUS response ring is not quiescent "
  209                     "(%08x:%08x): fixing up\n",
  210                     intf->rsp_cons, intf->rsp_prod);
  211                 intf->rsp_cons = intf->rsp_prod;
  212         }
  213 
  214         if (xenstore_irq)
  215                 unbind_from_irqhandler(xenstore_irq);
  216 
  217         error = bind_caller_port_to_irqhandler(
  218                 xen_store_evtchn, "xenbus",
  219                     xb_intr, NULL, INTR_TYPE_NET, &xenstore_irq);
  220         if (error) {
  221                 log(LOG_WARNING, "XENBUS request irq failed %i\n", error);
  222                 return (error);
  223         }
  224 
  225         return (0);
  226 }

Cache object: f9415d4e1370ba96be97319a0b1604bb


[ 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.