]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/xen/xenbus/xenbus_comms.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / xen / xenbus / xenbus_comms.c
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$");
33
34 #include <sys/types.h>
35 #include <sys/cdefs.h>
36 #include <sys/time.h>
37 #include <sys/errno.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/syslog.h>
41 #include <sys/proc.h>
42 #include <sys/kernel.h>
43
44
45
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>
52
53 static int xenbus_irq;
54
55 extern void xenbus_probe(void *); 
56 extern int xenstored_ready; 
57 #if 0
58 static DECLARE_WORK(probe_work, xenbus_probe, NULL);
59 #endif
60 int xb_wait;
61 extern char *xen_store;
62 #define wake_up wakeup
63 #define xb_waitq xb_wait
64 #define pr_debug(a,b,c)
65
66 static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
67 {
68                 return (struct xenstore_domain_interface *)xen_store;
69 }
70
71 static void
72 wake_waiting(void * arg __attribute__((unused)))
73 {
74 #if 0
75                 if (unlikely(xenstored_ready == 0)) {
76                                 xenstored_ready = 1; 
77                                 schedule_work(&probe_work); 
78                 } 
79 #endif
80                 wakeup(&xb_wait);
81 }
82
83 static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
84 {
85                 return ((prod - cons) <= XENSTORE_RING_SIZE);
86 }
87
88 static void *get_output_chunk(XENSTORE_RING_IDX cons,
89                                                           XENSTORE_RING_IDX prod,
90                                                           char *buf, uint32_t *len)
91 {
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);
96 }
97
98 static const void *get_input_chunk(XENSTORE_RING_IDX cons,
99                                                                    XENSTORE_RING_IDX prod,
100                                                                    const char *buf, uint32_t *len)
101 {
102                 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
103                 if ((prod - cons) < *len)
104                                 *len = prod - cons;
105                 return buf + MASK_XENSTORE_IDX(cons);
106 }
107
108 int xb_write(const void *tdata, unsigned len)
109 {
110                 struct xenstore_domain_interface *intf = xenstore_domain_interface();
111                 XENSTORE_RING_IDX cons, prod;
112                 const char *data = (const char *)tdata;
113
114                 while (len != 0) {
115                                 void *dst;
116                                 unsigned int avail;
117
118                                 wait_event_interruptible(&xb_waitq,
119                                                                                  (intf->req_prod - intf->req_cons) !=
120                                                                                  XENSTORE_RING_SIZE);
121
122                                 /* Read indexes, then verify. */
123                                 cons = intf->req_cons;
124                                 prod = intf->req_prod;
125                                 mb();
126                                 if (!check_indexes(cons, prod)) {
127                                                 intf->req_cons = intf->req_prod = 0;
128                                                 return -EIO;
129                                 }
130
131                                 dst = get_output_chunk(cons, prod, intf->req, &avail);
132                                 if (avail == 0)
133                                                 continue;
134                                 if (avail > len)
135                                                 avail = len;
136                                 mb();
137                                 
138                                 memcpy(dst, data, avail);
139                                 data += avail;
140                                 len -= avail;
141
142                                 /* Other side must not see new header until data is there. */
143                                 wmb();
144                                 intf->req_prod += avail;
145
146                                 /* This implies mb() before other side sees interrupt. */
147                                 notify_remote_via_evtchn(xen_start_info->store_evtchn);
148                 }
149
150                 return 0;
151 }
152
153 #ifdef notyet
154 int xb_data_to_read(void)
155 {
156         struct xenstore_domain_interface *intf = xen_store_interface;
157         return (intf->rsp_cons != intf->rsp_prod);
158 }
159
160 int xb_wait_for_data_to_read(void)
161 {
162         return wait_event_interruptible(xb_waitq, xb_data_to_read());
163 }
164 #endif
165
166
167 int xb_read(void *tdata, unsigned len)
168 {
169                 struct xenstore_domain_interface *intf = xenstore_domain_interface();
170                 XENSTORE_RING_IDX cons, prod;
171                 char *data = (char *)tdata;
172
173                 while (len != 0) {
174                                 unsigned int avail;
175                                 const char *src;
176
177                                 wait_event_interruptible(&xb_waitq,
178                                                                                  intf->rsp_cons != intf->rsp_prod);
179
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;
185                                                 return -EIO;
186                                 }
187                                 
188                                 src = get_input_chunk(cons, prod, intf->rsp, &avail);
189                                 if (avail == 0)
190                                                 continue;
191                                 if (avail > len)
192                                                 avail = len;
193
194                                 /* We must read header before we read data. */
195                                 rmb();
196
197                                 memcpy(data, src, avail);
198                                 data += avail;
199                                 len -= avail;
200
201                                 /* Other side must not see free space until we've copied out */
202                                 mb();
203                                 intf->rsp_cons += avail;
204
205                                 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
206
207                                 /* Implies mb(): they will see new header. */
208                                 notify_remote_via_evtchn(xen_start_info->store_evtchn);
209                 }
210
211                 return 0;
212 }
213
214 /* Set up interrupt handler off store event channel. */
215 int xb_init_comms(void)
216 {
217                 struct xenstore_domain_interface *intf = xenstore_domain_interface();
218                 int err;
219
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;
225                 }
226
227                 if (xenbus_irq)
228                                 unbind_from_irqhandler(xenbus_irq, &xb_waitq);
229
230                 err = bind_caller_port_to_irqhandler(
231                                 xen_start_info->store_evtchn,
232                                 "xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL);
233                 if (err <= 0) {
234                                 log(LOG_WARNING, "XENBUS request irq failed %i\n", err);
235                                 return err;
236                 }
237
238                 xenbus_irq = err;
239
240                 return 0;
241 }
242
243 /*
244  * Local variables:
245  *  c-file-style: "bsd"
246  *  indent-tabs-mode: t
247  *  c-indent-level: 4
248  *  c-basic-offset: 8
249  *  tab-width: 4
250  * End:
251  */