Home | History | Annotate | Line # | Download | only in xenbus
xenbus_comms.c revision 1.13
      1  1.13       jym /* $NetBSD: xenbus_comms.c,v 1.13 2011/07/02 19:07:56 jym Exp $ */
      2   1.1    bouyer /******************************************************************************
      3   1.1    bouyer  * xenbus_comms.c
      4   1.1    bouyer  *
      5   1.1    bouyer  * Low level code to talks to Xen Store: ringbuffer and event channel.
      6   1.1    bouyer  *
      7   1.1    bouyer  * Copyright (C) 2005 Rusty Russell, IBM Corporation
      8   1.1    bouyer  *
      9   1.1    bouyer  * This file may be distributed separately from the Linux kernel, or
     10   1.1    bouyer  * incorporated into other software packages, subject to the following license:
     11   1.1    bouyer  *
     12   1.1    bouyer  * Permission is hereby granted, free of charge, to any person obtaining a copy
     13   1.1    bouyer  * of this source file (the "Software"), to deal in the Software without
     14   1.1    bouyer  * restriction, including without limitation the rights to use, copy, modify,
     15   1.1    bouyer  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
     16   1.1    bouyer  * and to permit persons to whom the Software is furnished to do so, subject to
     17   1.1    bouyer  * the following conditions:
     18   1.1    bouyer  *
     19   1.1    bouyer  * The above copyright notice and this permission notice shall be included in
     20   1.1    bouyer  * all copies or substantial portions of the Software.
     21   1.1    bouyer  *
     22   1.1    bouyer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23   1.1    bouyer  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24   1.1    bouyer  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     25   1.1    bouyer  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     26   1.1    bouyer  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     27   1.1    bouyer  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     28   1.1    bouyer  * IN THE SOFTWARE.
     29   1.1    bouyer  */
     30   1.1    bouyer 
     31   1.2    bouyer #include <sys/cdefs.h>
     32  1.13       jym __KERNEL_RCSID(0, "$NetBSD: xenbus_comms.c,v 1.13 2011/07/02 19:07:56 jym Exp $");
     33   1.2    bouyer 
     34   1.2    bouyer #include <sys/types.h>
     35   1.2    bouyer #include <sys/null.h>
     36   1.2    bouyer #include <sys/errno.h>
     37   1.2    bouyer #include <sys/param.h>
     38   1.2    bouyer #include <sys/proc.h>
     39   1.2    bouyer #include <sys/systm.h>
     40   1.2    bouyer 
     41  1.10    cegger #include <xen/xen.h>	/* for xendomain_is_dom0() */
     42   1.5    bouyer #include <xen/hypervisor.h>
     43   1.5    bouyer #include <xen/evtchn.h>
     44   1.5    bouyer #include <xen/xenbus.h>
     45   1.1    bouyer #include "xenbus_comms.h"
     46   1.1    bouyer 
     47   1.2    bouyer #undef XENDEBUG
     48   1.2    bouyer #ifdef XENDEBUG
     49   1.2    bouyer #define XENPRINTF(x) printf x
     50   1.2    bouyer #else
     51   1.2    bouyer #define XENPRINTF(x)
     52   1.2    bouyer #endif
     53   1.2    bouyer 
     54   1.2    bouyer struct xenstore_domain_interface *xenstore_interface;
     55   1.2    bouyer 
     56   1.2    bouyer static int xenbus_irq = 0;
     57   1.1    bouyer 
     58   1.1    bouyer extern int xenstored_ready;
     59   1.2    bouyer // static DECLARE_WORK(probe_work, xenbus_probe, NULL);
     60   1.2    bouyer 
     61   1.2    bouyer static int wake_waiting(void *);
     62   1.2    bouyer static int check_indexes(XENSTORE_RING_IDX, XENSTORE_RING_IDX);
     63   1.4  christos static void *get_output_chunk(XENSTORE_RING_IDX, XENSTORE_RING_IDX,
     64   1.2    bouyer     char *, uint32_t *);
     65   1.4  christos static const void *get_input_chunk(XENSTORE_RING_IDX, XENSTORE_RING_IDX,
     66   1.2    bouyer     const char *, uint32_t *);
     67   1.1    bouyer 
     68   1.1    bouyer 
     69   1.2    bouyer static inline struct xenstore_domain_interface *
     70   1.2    bouyer xenstore_domain_interface(void)
     71   1.1    bouyer {
     72   1.2    bouyer 	return xenstore_interface;
     73   1.1    bouyer }
     74   1.1    bouyer 
     75   1.2    bouyer static int
     76   1.2    bouyer wake_waiting(void *arg)
     77   1.1    bouyer {
     78   1.8    cegger 	if (__predict_false(xenstored_ready == 0 && xendomain_is_dom0())) {
     79   1.1    bouyer 		xenstored_ready = 1;
     80   1.3    bouyer 		wakeup(&xenstored_ready);
     81   1.1    bouyer 	}
     82   1.1    bouyer 
     83   1.2    bouyer 	wakeup(&xenstore_interface);
     84   1.2    bouyer 	return 1;
     85   1.1    bouyer }
     86   1.1    bouyer 
     87   1.2    bouyer static int
     88   1.2    bouyer check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
     89   1.1    bouyer {
     90   1.1    bouyer 	return ((prod - cons) <= XENSTORE_RING_SIZE);
     91   1.1    bouyer }
     92   1.1    bouyer 
     93   1.2    bouyer static void *
     94   1.2    bouyer get_output_chunk(XENSTORE_RING_IDX cons,
     95   1.1    bouyer 			      XENSTORE_RING_IDX prod,
     96   1.1    bouyer 			      char *buf, uint32_t *len)
     97   1.1    bouyer {
     98   1.1    bouyer 	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
     99   1.1    bouyer 	if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
    100   1.1    bouyer 		*len = XENSTORE_RING_SIZE - (prod - cons);
    101   1.1    bouyer 	return buf + MASK_XENSTORE_IDX(prod);
    102   1.1    bouyer }
    103   1.1    bouyer 
    104   1.2    bouyer static const void *
    105   1.2    bouyer get_input_chunk(XENSTORE_RING_IDX cons,
    106   1.1    bouyer 				   XENSTORE_RING_IDX prod,
    107   1.1    bouyer 				   const char *buf, uint32_t *len)
    108   1.1    bouyer {
    109   1.1    bouyer 	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
    110   1.1    bouyer 	if ((prod - cons) < *len)
    111   1.1    bouyer 		*len = prod - cons;
    112   1.1    bouyer 	return buf + MASK_XENSTORE_IDX(cons);
    113   1.1    bouyer }
    114   1.1    bouyer 
    115   1.2    bouyer int
    116   1.2    bouyer xb_write(const void *data, unsigned len)
    117   1.1    bouyer {
    118   1.1    bouyer 	struct xenstore_domain_interface *intf = xenstore_domain_interface();
    119   1.1    bouyer 	XENSTORE_RING_IDX cons, prod;
    120   1.1    bouyer 
    121   1.2    bouyer 	int s = spltty();
    122   1.2    bouyer 
    123   1.1    bouyer 	while (len != 0) {
    124   1.1    bouyer 		void *dst;
    125   1.1    bouyer 		unsigned int avail;
    126   1.1    bouyer 
    127   1.2    bouyer 		while ((intf->req_prod - intf->req_cons) == XENSTORE_RING_SIZE) {
    128   1.2    bouyer 			XENPRINTF(("xb_write tsleep\n"));
    129   1.2    bouyer 			tsleep(&xenstore_interface, PRIBIO, "wrst", 0);
    130   1.2    bouyer 			XENPRINTF(("xb_write tsleep done\n"));
    131   1.2    bouyer 		}
    132   1.1    bouyer 
    133   1.1    bouyer 		/* Read indexes, then verify. */
    134   1.1    bouyer 		cons = intf->req_cons;
    135   1.1    bouyer 		prod = intf->req_prod;
    136  1.12       jym 		xen_rmb();
    137   1.2    bouyer 		if (!check_indexes(cons, prod)) {
    138   1.2    bouyer 			splx(s);
    139   1.2    bouyer 			return EIO;
    140   1.2    bouyer 		}
    141   1.1    bouyer 
    142   1.1    bouyer 		dst = get_output_chunk(cons, prod, intf->req, &avail);
    143   1.1    bouyer 		if (avail == 0)
    144   1.1    bouyer 			continue;
    145   1.1    bouyer 		if (avail > len)
    146   1.1    bouyer 			avail = len;
    147   1.1    bouyer 
    148   1.1    bouyer 		memcpy(dst, data, avail);
    149   1.2    bouyer 		data = (const char *)data + avail;
    150   1.1    bouyer 		len -= avail;
    151   1.1    bouyer 
    152   1.1    bouyer 		/* Other side must not see new header until data is there. */
    153  1.12       jym 		xen_rmb();
    154   1.1    bouyer 		intf->req_prod += avail;
    155  1.12       jym 		xen_rmb();
    156   1.1    bouyer 
    157   1.2    bouyer 		hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
    158   1.1    bouyer 	}
    159   1.1    bouyer 
    160   1.2    bouyer 	splx(s);
    161   1.1    bouyer 	return 0;
    162   1.1    bouyer }
    163   1.1    bouyer 
    164   1.2    bouyer int
    165   1.2    bouyer xb_read(void *data, unsigned len)
    166   1.1    bouyer {
    167   1.1    bouyer 	struct xenstore_domain_interface *intf = xenstore_domain_interface();
    168   1.1    bouyer 	XENSTORE_RING_IDX cons, prod;
    169   1.1    bouyer 
    170   1.2    bouyer 	int s = spltty();
    171   1.2    bouyer 
    172   1.1    bouyer 	while (len != 0) {
    173   1.1    bouyer 		unsigned int avail;
    174   1.1    bouyer 		const char *src;
    175   1.1    bouyer 
    176   1.2    bouyer 		while (intf->rsp_cons == intf->rsp_prod)
    177   1.2    bouyer 			tsleep(&xenstore_interface, PRIBIO, "rdst", 0);
    178   1.1    bouyer 
    179   1.1    bouyer 		/* Read indexes, then verify. */
    180   1.1    bouyer 		cons = intf->rsp_cons;
    181   1.1    bouyer 		prod = intf->rsp_prod;
    182  1.12       jym 		xen_rmb();
    183   1.2    bouyer 		if (!check_indexes(cons, prod)) {
    184   1.2    bouyer 			XENPRINTF(("xb_read EIO\n"));
    185   1.2    bouyer 			splx(s);
    186   1.2    bouyer 			return EIO;
    187   1.2    bouyer 		}
    188   1.1    bouyer 
    189   1.1    bouyer 		src = get_input_chunk(cons, prod, intf->rsp, &avail);
    190   1.1    bouyer 		if (avail == 0)
    191   1.1    bouyer 			continue;
    192   1.1    bouyer 		if (avail > len)
    193   1.1    bouyer 			avail = len;
    194   1.1    bouyer 
    195   1.1    bouyer 		/* We must read header before we read data. */
    196  1.12       jym 		xen_rmb();
    197   1.1    bouyer 
    198   1.1    bouyer 		memcpy(data, src, avail);
    199   1.2    bouyer 		data = (char *)data + avail;
    200   1.1    bouyer 		len -= avail;
    201   1.1    bouyer 
    202   1.1    bouyer 		/* Other side must not see free space until we've copied out */
    203  1.12       jym 		xen_rmb();
    204   1.1    bouyer 		intf->rsp_cons += avail;
    205  1.12       jym 		xen_rmb();
    206   1.1    bouyer 
    207   1.2    bouyer 		XENPRINTF(("Finished read of %i bytes (%i to go)\n",
    208   1.2    bouyer 		    avail, len));
    209   1.1    bouyer 
    210   1.2    bouyer 		hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
    211   1.1    bouyer 	}
    212   1.1    bouyer 
    213   1.2    bouyer 	splx(s);
    214   1.1    bouyer 	return 0;
    215   1.1    bouyer }
    216   1.1    bouyer 
    217   1.9       jym /* Set up interrupt handler of store event channel. */
    218   1.2    bouyer int
    219   1.7    cegger xb_init_comms(device_t dev)
    220   1.1    bouyer {
    221   1.1    bouyer 	if (xenbus_irq)
    222   1.2    bouyer 		event_remove_handler(xenbus_irq, wake_waiting, NULL);
    223   1.1    bouyer 
    224  1.13       jym 	event_set_handler(xen_start_info.store_evtchn, wake_waiting,
    225   1.2    bouyer 	    NULL, IPL_TTY, "xenbus");
    226  1.13       jym 
    227   1.2    bouyer 	xenbus_irq = xen_start_info.store_evtchn;
    228   1.9       jym 	aprint_verbose_dev(dev, "using event channel %d\n", xenbus_irq);
    229   1.2    bouyer 	hypervisor_enable_event(xenbus_irq);
    230   1.1    bouyer 	return 0;
    231   1.1    bouyer }
    232   1.1    bouyer 
    233   1.1    bouyer /*
    234   1.1    bouyer  * Local variables:
    235   1.1    bouyer  *  c-file-style: "linux"
    236   1.1    bouyer  *  indent-tabs-mode: t
    237   1.1    bouyer  *  c-indent-level: 8
    238   1.1    bouyer  *  c-basic-offset: 8
    239   1.1    bouyer  *  tab-width: 8
    240   1.1    bouyer  * End:
    241   1.1    bouyer  */
    242