1 /******************************************************************************
4 * Low level code to talks to Xen Store: ringbuffer and event channel.
6 * Copyright (C) 2005 Rusty Russell, IBM Corporation
8 * This file may be distributed separately from the Linux kernel, or
9 * incorporated into other software packages, subject to the following license:
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:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
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
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
36 #include <sys/kernel.h>
38 #include <sys/mutex.h>
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/syslog.h>
44 #include <machine/xen/xen-os.h>
45 #include <xen/hypervisor.h>
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>
52 static unsigned int xenstore_irq;
54 static inline struct xenstore_domain_interface *
55 xenstore_domain_interface(void)
58 return (struct xenstore_domain_interface *)xen_store;
62 xb_intr(void * arg __attribute__((unused)))
69 xb_check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
72 return ((prod - cons) <= XENSTORE_RING_SIZE);
76 xb_get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
77 char *buf, uint32_t *len)
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));
87 xb_get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
88 const char *buf, uint32_t *len)
91 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
92 if ((prod - cons) < *len)
94 return (buf + MASK_XENSTORE_IDX(cons));
98 xb_write(const void *tdata, unsigned len, struct lock_object *lock)
100 struct xenstore_domain_interface *intf = xenstore_domain_interface();
101 XENSTORE_RING_IDX cons, prod;
102 const char *data = (const char *)tdata;
109 while ((intf->req_prod - intf->req_cons)
110 == XENSTORE_RING_SIZE) {
113 PCATCH, "xbwrite", hz/10);
114 if (error && error != EWOULDBLOCK)
118 /* Read indexes, then verify. */
119 cons = intf->req_cons;
120 prod = intf->req_prod;
122 if (!xb_check_indexes(cons, prod)) {
123 intf->req_cons = intf->req_prod = 0;
127 dst = xb_get_output_chunk(cons, prod, intf->req, &avail);
134 memcpy(dst, data, avail);
138 /* Other side must not see new header until data is there. */
140 intf->req_prod += avail;
142 /* This implies mb() before other side sees interrupt. */
143 notify_remote_via_evtchn(xen_store_evtchn);
150 xb_read(void *tdata, unsigned len, struct lock_object *lock)
152 struct xenstore_domain_interface *intf = xenstore_domain_interface();
153 XENSTORE_RING_IDX cons, prod;
154 char *data = (char *)tdata;
161 while (intf->rsp_cons == intf->rsp_prod) {
162 error = _sleep(intf, lock,
163 PCATCH, "xbread", hz/10);
164 if (error && error != EWOULDBLOCK)
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;
176 src = xb_get_input_chunk(cons, prod, intf->rsp, &avail);
182 /* We must read header before we read data. */
185 memcpy(data, src, avail);
189 /* Other side must not see free space until we've copied out */
191 intf->rsp_cons += avail;
193 /* Implies mb(): they will see new header. */
194 notify_remote_via_evtchn(xen_store_evtchn);
200 /* Set up interrupt handler off store event channel. */
204 struct xenstore_domain_interface *intf = xenstore_domain_interface();
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;
215 unbind_from_irqhandler(xenstore_irq);
217 error = bind_caller_port_to_irqhandler(
218 xen_store_evtchn, "xenbus",
219 xb_intr, NULL, INTR_TYPE_NET, &xenstore_irq);
221 log(LOG_WARNING, "XENBUS request irq failed %i\n", error);