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/types.h>
35 #include <sys/cdefs.h>
37 #include <sys/errno.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/syslog.h>
42 #include <sys/kernel.h>
46 #include <machine/xen/xen-os.h>
47 #include <machine/xen/hypervisor.h>
48 #include <machine/xen/evtchn.h>
49 #include <machine/xen/xenbus.h>
50 #include <machine/xen/xen_intr.h>
51 #include <xen/xenbus/xenbus_comms.h>
53 static int xenbus_irq;
55 extern void xenbus_probe(void *);
56 extern int xenstored_ready;
58 static DECLARE_WORK(probe_work, xenbus_probe, NULL);
61 extern char *xen_store;
62 #define wake_up wakeup
63 #define xb_waitq xb_wait
64 #define pr_debug(a,b,c)
66 static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
68 return (struct xenstore_domain_interface *)xen_store;
72 wake_waiting(void * arg __attribute__((unused)))
75 if (unlikely(xenstored_ready == 0)) {
77 schedule_work(&probe_work);
83 static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
85 return ((prod - cons) <= XENSTORE_RING_SIZE);
88 static void *get_output_chunk(XENSTORE_RING_IDX cons,
89 XENSTORE_RING_IDX prod,
90 char *buf, uint32_t *len)
92 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
93 if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
94 *len = XENSTORE_RING_SIZE - (prod - cons);
95 return buf + MASK_XENSTORE_IDX(prod);
98 static const void *get_input_chunk(XENSTORE_RING_IDX cons,
99 XENSTORE_RING_IDX prod,
100 const char *buf, uint32_t *len)
102 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
103 if ((prod - cons) < *len)
105 return buf + MASK_XENSTORE_IDX(cons);
108 int xb_write(const void *tdata, unsigned len)
110 struct xenstore_domain_interface *intf = xenstore_domain_interface();
111 XENSTORE_RING_IDX cons, prod;
112 const char *data = (const char *)tdata;
118 wait_event_interruptible(&xb_waitq,
119 (intf->req_prod - intf->req_cons) !=
122 /* Read indexes, then verify. */
123 cons = intf->req_cons;
124 prod = intf->req_prod;
126 if (!check_indexes(cons, prod)) {
127 intf->req_cons = intf->req_prod = 0;
131 dst = get_output_chunk(cons, prod, intf->req, &avail);
138 memcpy(dst, data, avail);
142 /* Other side must not see new header until data is there. */
144 intf->req_prod += avail;
146 /* This implies mb() before other side sees interrupt. */
147 notify_remote_via_evtchn(xen_start_info->store_evtchn);
154 int xb_data_to_read(void)
156 struct xenstore_domain_interface *intf = xen_store_interface;
157 return (intf->rsp_cons != intf->rsp_prod);
160 int xb_wait_for_data_to_read(void)
162 return wait_event_interruptible(xb_waitq, xb_data_to_read());
167 int xb_read(void *tdata, unsigned len)
169 struct xenstore_domain_interface *intf = xenstore_domain_interface();
170 XENSTORE_RING_IDX cons, prod;
171 char *data = (char *)tdata;
177 wait_event_interruptible(&xb_waitq,
178 intf->rsp_cons != intf->rsp_prod);
180 /* Read indexes, then verify. */
181 cons = intf->rsp_cons;
182 prod = intf->rsp_prod;
183 if (!check_indexes(cons, prod)) {
184 intf->rsp_cons = intf->rsp_prod = 0;
188 src = get_input_chunk(cons, prod, intf->rsp, &avail);
194 /* We must read header before we read data. */
197 memcpy(data, src, avail);
201 /* Other side must not see free space until we've copied out */
203 intf->rsp_cons += avail;
205 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
207 /* Implies mb(): they will see new header. */
208 notify_remote_via_evtchn(xen_start_info->store_evtchn);
214 /* Set up interrupt handler off store event channel. */
215 int xb_init_comms(void)
217 struct xenstore_domain_interface *intf = xenstore_domain_interface();
220 if (intf->rsp_prod != intf->rsp_cons) {
221 log(LOG_WARNING, "XENBUS response ring is not quiescent "
222 "(%08x:%08x): fixing up\n",
223 intf->rsp_cons, intf->rsp_prod);
224 intf->rsp_cons = intf->rsp_prod;
228 unbind_from_irqhandler(xenbus_irq, &xb_waitq);
230 err = bind_caller_port_to_irqhandler(
231 xen_start_info->store_evtchn,
232 "xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL);
234 log(LOG_WARNING, "XENBUS request irq failed %i\n", err);
245 * c-file-style: "bsd"
246 * indent-tabs-mode: t