ia64/xen-unstable

view extras/mini-os/xenbus/xenbus.c @ 16458:ce3e5e859d66

vt-d: Fix iommu_map_page().
Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Nov 25 09:23:02 2007 +0000 (2007-11-25)
parents 7b5b65fbaf61
children 6fd17d0dcbcd
line source
1 /*
2 ****************************************************************************
3 * (C) 2006 - Cambridge University
4 ****************************************************************************
5 *
6 * File: xenbus.c
7 * Author: Steven Smith (sos22@cam.ac.uk)
8 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
9 * Changes: John D. Ramsdell
10 *
11 * Date: Jun 2006, chages Aug 2005
12 *
13 * Environment: Xen Minimal OS
14 * Description: Minimal implementation of xenbus
15 *
16 ****************************************************************************
17 **/
18 #include <os.h>
19 #include <mm.h>
20 #include <traps.h>
21 #include <lib.h>
22 #include <xenbus.h>
23 #include <events.h>
24 #include <errno.h>
25 #include <sched.h>
26 #include <wait.h>
27 #include <xen/io/xs_wire.h>
28 #include <spinlock.h>
29 #include <xmalloc.h>
31 #define BUG_ON(x) do { \
32 if (x) {printk("BUG at %s:%d\n", __FILE__, __LINE__); BUG(); } \
33 } while (0)
35 #define min(x,y) ({ \
36 typeof(x) tmpx = (x); \
37 typeof(y) tmpy = (y); \
38 tmpx < tmpy ? tmpx : tmpy; \
39 })
41 #ifdef XENBUS_DEBUG
42 #define DEBUG(_f, _a...) \
43 printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
44 #else
45 #define DEBUG(_f, _a...) ((void)0)
46 #endif
48 static struct xenstore_domain_interface *xenstore_buf;
49 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
50 static DECLARE_WAIT_QUEUE_HEAD(watch_queue);
51 struct xenbus_req_info
52 {
53 int in_use:1;
54 struct wait_queue_head waitq;
55 void *reply;
56 };
58 #define NR_REQS 32
59 static struct xenbus_req_info req_info[NR_REQS];
61 static void memcpy_from_ring(const void *Ring,
62 void *Dest,
63 int off,
64 int len)
65 {
66 int c1, c2;
67 const char *ring = Ring;
68 char *dest = Dest;
69 c1 = min(len, XENSTORE_RING_SIZE - off);
70 c2 = len - c1;
71 memcpy(dest, ring + off, c1);
72 memcpy(dest + c1, ring, c2);
73 }
75 void wait_for_watch(void)
76 {
77 DEFINE_WAIT(w);
78 add_waiter(w,watch_queue);
79 schedule();
80 remove_waiter(w);
81 wake(current);
82 remove_wait_queue(&w);
83 }
85 char* xenbus_wait_for_value(const char* path,const char* value)
86 {
87 for(;;)
88 {
89 char *res, *msg;
90 int r;
92 msg = xenbus_read(XBT_NIL, path, &res);
93 if(msg) return msg;
95 r = strcmp(value,res);
96 free(res);
98 if(r==0) break;
99 else wait_for_watch();
100 }
101 return NULL;
102 }
105 static void xenbus_thread_func(void *ign)
106 {
107 struct xsd_sockmsg msg;
108 unsigned prod = 0;
110 for (;;)
111 {
112 wait_event(xb_waitq, prod != xenstore_buf->rsp_prod);
113 while (1)
114 {
115 prod = xenstore_buf->rsp_prod;
116 DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons,
117 xenstore_buf->rsp_prod);
118 if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
119 break;
120 rmb();
121 memcpy_from_ring(xenstore_buf->rsp,
122 &msg,
123 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
124 sizeof(msg));
125 DEBUG("Msg len %d, %d avail, id %d.\n",
126 msg.len + sizeof(msg),
127 xenstore_buf->rsp_prod - xenstore_buf->rsp_cons,
128 msg.req_id);
129 if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons <
130 sizeof(msg) + msg.len)
131 break;
133 DEBUG("Message is good.\n");
135 if(msg.type == XS_WATCH_EVENT)
136 {
137 char* payload = (char*)malloc(sizeof(msg) + msg.len);
138 char *path,*token;
140 memcpy_from_ring(xenstore_buf->rsp,
141 payload,
142 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
143 msg.len + sizeof(msg));
145 path = payload + sizeof(msg);
146 token = path + strlen(path) + 1;
148 xenstore_buf->rsp_cons += msg.len + sizeof(msg);
149 free(payload);
150 wake_up(&watch_queue);
151 }
153 else
154 {
155 req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
156 memcpy_from_ring(xenstore_buf->rsp,
157 req_info[msg.req_id].reply,
158 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
159 msg.len + sizeof(msg));
160 xenstore_buf->rsp_cons += msg.len + sizeof(msg);
161 wake_up(&req_info[msg.req_id].waitq);
162 }
163 }
164 }
165 }
167 static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
168 void *ign)
169 {
170 wake_up(&xb_waitq);
171 }
173 static int nr_live_reqs;
174 static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
175 static DECLARE_WAIT_QUEUE_HEAD(req_wq);
177 /* Release a xenbus identifier */
178 static void release_xenbus_id(int id)
179 {
180 BUG_ON(!req_info[id].in_use);
181 spin_lock(&req_lock);
182 req_info[id].in_use = 0;
183 nr_live_reqs--;
184 req_info[id].in_use = 0;
185 if (nr_live_reqs == NR_REQS - 1)
186 wake_up(&req_wq);
187 spin_unlock(&req_lock);
188 }
190 /* Allocate an identifier for a xenbus request. Blocks if none are
191 available. */
192 static int allocate_xenbus_id(void)
193 {
194 static int probe;
195 int o_probe;
197 while (1)
198 {
199 spin_lock(&req_lock);
200 if (nr_live_reqs < NR_REQS)
201 break;
202 spin_unlock(&req_lock);
203 wait_event(req_wq, (nr_live_reqs < NR_REQS));
204 }
206 o_probe = probe;
207 for (;;)
208 {
209 if (!req_info[o_probe].in_use)
210 break;
211 o_probe = (o_probe + 1) % NR_REQS;
212 BUG_ON(o_probe == probe);
213 }
214 nr_live_reqs++;
215 req_info[o_probe].in_use = 1;
216 probe = (o_probe + 1) % NR_REQS;
217 spin_unlock(&req_lock);
218 init_waitqueue_head(&req_info[o_probe].waitq);
220 return o_probe;
221 }
223 /* Initialise xenbus. */
224 void init_xenbus(void)
225 {
226 int err;
227 printk("Initialising xenbus\n");
228 DEBUG("init_xenbus called.\n");
229 xenstore_buf = mfn_to_virt(start_info.store_mfn);
230 create_thread("xenstore", xenbus_thread_func, NULL);
231 DEBUG("buf at %p.\n", xenstore_buf);
232 err = bind_evtchn(start_info.store_evtchn,
233 xenbus_evtchn_handler,
234 NULL);
235 DEBUG("xenbus on irq %d\n", err);
236 }
238 struct write_req {
239 const void *data;
240 unsigned len;
241 };
243 /* Send data to xenbus. This can block. All of the requests are seen
244 by xenbus as if sent atomically. The header is added
245 automatically, using type %type, req_id %req_id, and trans_id
246 %trans_id. */
247 static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
248 const struct write_req *req, int nr_reqs)
249 {
250 XENSTORE_RING_IDX prod;
251 int r;
252 int len = 0;
253 const struct write_req *cur_req;
254 int req_off;
255 int total_off;
256 int this_chunk;
257 struct xsd_sockmsg m = {.type = type, .req_id = req_id,
258 .tx_id = trans_id };
259 struct write_req header_req = { &m, sizeof(m) };
261 for (r = 0; r < nr_reqs; r++)
262 len += req[r].len;
263 m.len = len;
264 len += sizeof(m);
266 cur_req = &header_req;
268 BUG_ON(len > XENSTORE_RING_SIZE);
269 /* Wait for the ring to drain to the point where we can send the
270 message. */
271 prod = xenstore_buf->req_prod;
272 if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE)
273 {
274 /* Wait for there to be space on the ring */
275 DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n",
276 prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
277 wait_event(xb_waitq,
278 xenstore_buf->req_prod + len - xenstore_buf->req_cons <=
279 XENSTORE_RING_SIZE);
280 DEBUG("Back from wait.\n");
281 prod = xenstore_buf->req_prod;
282 }
284 /* We're now guaranteed to be able to send the message without
285 overflowing the ring. Do so. */
286 total_off = 0;
287 req_off = 0;
288 while (total_off < len)
289 {
290 this_chunk = min(cur_req->len - req_off,
291 XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
292 memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
293 (char *)cur_req->data + req_off, this_chunk);
294 prod += this_chunk;
295 req_off += this_chunk;
296 total_off += this_chunk;
297 if (req_off == cur_req->len)
298 {
299 req_off = 0;
300 if (cur_req == &header_req)
301 cur_req = req;
302 else
303 cur_req++;
304 }
305 }
307 DEBUG("Complete main loop of xb_write.\n");
308 BUG_ON(req_off != 0);
309 BUG_ON(total_off != len);
310 BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
312 /* Remote must see entire message before updating indexes */
313 wmb();
315 xenstore_buf->req_prod += len;
317 /* Send evtchn to notify remote */
318 notify_remote_via_evtchn(start_info.store_evtchn);
319 }
321 /* Send a mesasge to xenbus, in the same fashion as xb_write, and
322 block waiting for a reply. The reply is malloced and should be
323 freed by the caller. */
324 static struct xsd_sockmsg *
325 xenbus_msg_reply(int type,
326 xenbus_transaction_t trans,
327 struct write_req *io,
328 int nr_reqs)
329 {
330 int id;
331 DEFINE_WAIT(w);
332 struct xsd_sockmsg *rep;
334 id = allocate_xenbus_id();
335 add_waiter(w, req_info[id].waitq);
337 xb_write(type, id, trans, io, nr_reqs);
339 schedule();
340 remove_waiter(w);
341 wake(current);
343 rep = req_info[id].reply;
344 BUG_ON(rep->req_id != id);
345 release_xenbus_id(id);
346 return rep;
347 }
349 static char *errmsg(struct xsd_sockmsg *rep)
350 {
351 if (!rep) {
352 char msg[] = "No reply";
353 size_t len = strlen(msg) + 1;
354 return memcpy(malloc(len), msg, len);
355 }
356 if (rep->type != XS_ERROR)
357 return NULL;
358 char *res = malloc(rep->len + 1);
359 memcpy(res, rep + 1, rep->len);
360 res[rep->len] = 0;
361 free(rep);
362 return res;
363 }
365 /* Send a debug message to xenbus. Can block. */
366 static void xenbus_debug_msg(const char *msg)
367 {
368 int len = strlen(msg);
369 struct write_req req[] = {
370 { "print", sizeof("print") },
371 { msg, len },
372 { "", 1 }};
373 struct xsd_sockmsg *reply;
375 reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));
376 DEBUG("Got a reply, type %d, id %d, len %d.\n",
377 reply->type, reply->req_id, reply->len);
378 }
380 /* List the contents of a directory. Returns a malloc()ed array of
381 pointers to malloc()ed strings. The array is NULL terminated. May
382 block. */
383 char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
384 {
385 struct xsd_sockmsg *reply, *repmsg;
386 struct write_req req[] = { { pre, strlen(pre)+1 } };
387 int nr_elems, x, i;
388 char **res;
390 repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
391 char *msg = errmsg(repmsg);
392 if (msg) {
393 *contents = NULL;
394 return msg;
395 }
396 reply = repmsg + 1;
397 for (x = nr_elems = 0; x < repmsg->len; x++)
398 nr_elems += (((char *)reply)[x] == 0);
399 res = malloc(sizeof(res[0]) * (nr_elems + 1));
400 for (x = i = 0; i < nr_elems; i++) {
401 int l = strlen((char *)reply + x);
402 res[i] = malloc(l + 1);
403 memcpy(res[i], (char *)reply + x, l + 1);
404 x += l + 1;
405 }
406 res[i] = NULL;
407 free(repmsg);
408 *contents = res;
409 return NULL;
410 }
412 char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
413 {
414 struct write_req req[] = { {path, strlen(path) + 1} };
415 struct xsd_sockmsg *rep;
416 char *res;
417 rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
418 char *msg = errmsg(rep);
419 if (msg) {
420 *value = NULL;
421 return msg;
422 }
423 res = malloc(rep->len + 1);
424 memcpy(res, rep + 1, rep->len);
425 res[rep->len] = 0;
426 free(rep);
427 *value = res;
428 return NULL;
429 }
431 char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value)
432 {
433 struct write_req req[] = {
434 {path, strlen(path) + 1},
435 {value, strlen(value) + 1},
436 };
437 struct xsd_sockmsg *rep;
438 rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
439 char *msg = errmsg(rep);
440 if (msg) return msg;
441 free(rep);
442 return NULL;
443 }
445 char* xenbus_watch_path( xenbus_transaction_t xbt, const char *path)
446 {
447 /* in the future one could have multiple watch queues, and use
448 * the token for demuxing. For now the token is 0. */
450 struct xsd_sockmsg *rep;
452 struct write_req req[] = {
453 {path, strlen(path) + 1},
454 {"0",2 },
455 };
457 rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
459 char *msg = errmsg(rep);
460 if (msg) return msg;
461 free(rep);
463 return NULL;
464 }
466 char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
467 {
468 struct write_req req[] = { {path, strlen(path) + 1} };
469 struct xsd_sockmsg *rep;
470 rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
471 char *msg = errmsg(rep);
472 if (msg)
473 return msg;
474 free(rep);
475 return NULL;
476 }
478 char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
479 {
480 struct write_req req[] = { {path, strlen(path) + 1} };
481 struct xsd_sockmsg *rep;
482 char *res;
483 rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
484 char *msg = errmsg(rep);
485 if (msg) {
486 *value = NULL;
487 return msg;
488 }
489 res = malloc(rep->len + 1);
490 memcpy(res, rep + 1, rep->len);
491 res[rep->len] = 0;
492 free(rep);
493 *value = res;
494 return NULL;
495 }
497 #define PERM_MAX_SIZE 32
498 char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm)
499 {
500 char value[PERM_MAX_SIZE];
501 snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
502 struct write_req req[] = {
503 {path, strlen(path) + 1},
504 {value, strlen(value) + 1},
505 };
506 struct xsd_sockmsg *rep;
507 rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
508 char *msg = errmsg(rep);
509 if (msg)
510 return msg;
511 free(rep);
512 return NULL;
513 }
515 char *xenbus_transaction_start(xenbus_transaction_t *xbt)
516 {
517 /* xenstored becomes angry if you send a length 0 message, so just
518 shove a nul terminator on the end */
519 struct write_req req = { "", 1};
520 struct xsd_sockmsg *rep;
521 char *err;
523 rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
524 err = errmsg(rep);
525 if (err)
526 return err;
527 sscanf((char *)(rep + 1), "%u", xbt);
528 free(rep);
529 return NULL;
530 }
532 char *
533 xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
534 {
535 struct xsd_sockmsg *rep;
536 struct write_req req;
537 char *err;
539 *retry = 0;
541 req.data = abort ? "F" : "T";
542 req.len = 2;
543 rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
544 err = errmsg(rep);
545 if (err) {
546 if (!strcmp(err, "EAGAIN")) {
547 *retry = 1;
548 free(err);
549 return NULL;
550 } else {
551 return err;
552 }
553 }
554 free(rep);
555 return NULL;
556 }
558 int xenbus_read_integer(char *path)
559 {
560 char *res, *buf;
561 int t;
563 res = xenbus_read(XBT_NIL, path, &buf);
564 if (res) {
565 printk("Failed to read %s.\n", path);
566 free(res);
567 return -1;
568 }
569 sscanf(buf, "%d", &t);
570 free(buf);
571 return t;
572 }
574 static void do_ls_test(const char *pre)
575 {
576 char **dirs;
577 int x;
579 DEBUG("ls %s...\n", pre);
580 char *msg = xenbus_ls(XBT_NIL, pre, &dirs);
581 if (msg) {
582 DEBUG("Error in xenbus ls: %s\n", msg);
583 free(msg);
584 return;
585 }
586 for (x = 0; dirs[x]; x++)
587 {
588 DEBUG("ls %s[%d] -> %s\n", pre, x, dirs[x]);
589 free(dirs[x]);
590 }
591 free(dirs);
592 }
594 static void do_read_test(const char *path)
595 {
596 char *res;
597 DEBUG("Read %s...\n", path);
598 char *msg = xenbus_read(XBT_NIL, path, &res);
599 if (msg) {
600 DEBUG("Error in xenbus read: %s\n", msg);
601 free(msg);
602 return;
603 }
604 DEBUG("Read %s -> %s.\n", path, res);
605 free(res);
606 }
608 static void do_write_test(const char *path, const char *val)
609 {
610 DEBUG("Write %s to %s...\n", val, path);
611 char *msg = xenbus_write(XBT_NIL, path, val);
612 if (msg) {
613 DEBUG("Result %s\n", msg);
614 free(msg);
615 } else {
616 DEBUG("Success.\n");
617 }
618 }
620 static void do_rm_test(const char *path)
621 {
622 DEBUG("rm %s...\n", path);
623 char *msg = xenbus_rm(XBT_NIL, path);
624 if (msg) {
625 DEBUG("Result %s\n", msg);
626 free(msg);
627 } else {
628 DEBUG("Success.\n");
629 }
630 }
632 /* Simple testing thing */
633 void test_xenbus(void)
634 {
635 DEBUG("Doing xenbus test.\n");
636 xenbus_debug_msg("Testing xenbus...\n");
638 DEBUG("Doing ls test.\n");
639 do_ls_test("device");
640 do_ls_test("device/vif");
641 do_ls_test("device/vif/0");
643 DEBUG("Doing read test.\n");
644 do_read_test("device/vif/0/mac");
645 do_read_test("device/vif/0/backend");
647 DEBUG("Doing write test.\n");
648 do_write_test("device/vif/0/flibble", "flobble");
649 do_read_test("device/vif/0/flibble");
650 do_write_test("device/vif/0/flibble", "widget");
651 do_read_test("device/vif/0/flibble");
653 DEBUG("Doing rm test.\n");
654 do_rm_test("device/vif/0/flibble");
655 do_read_test("device/vif/0/flibble");
656 DEBUG("(Should have said ENOENT)\n");
657 }
659 /*
660 * Local variables:
661 * mode: C
662 * c-basic-offset: 4
663 * End:
664 */