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
|