36#include <sys/kernel.h>
38#include <sys/module.h>
41#include <sys/syslog.h>
42#include <sys/malloc.h>
45#include <sys/kthread.h>
47#include <sys/sysctl.h>
49#include <sys/unistd.h>
51#include <sys/taskqueue.h>
53#include <machine/stdarg.h>
55#include <xen/xen-os.h>
56#include <xen/hypervisor.h>
57#include <xen/xen_intr.h>
59#include <contrib/xen/hvm/params.h>
62#include <xen/xenstore/xenstorevar.h>
63#include <xen/xenstore/xenstore_internal.h>
127 struct xsd_sockmsg hdr;
278 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) {
305split(
char *strings, u_int len, u_int *num)
311 strings[len - 1] =
'\0';
317 ret = malloc(*num *
sizeof(
char *) + len, M_XENSTORE, M_WAITOK);
318 memcpy(&ret[*num], strings, len);
319 free(strings, M_XENSTORE);
322 strings = (
char *)&ret[*num];
335 sb = sbuf_new_auto();
337 if (name[0] !=
'\0') {
393 return ((prod - cons) <= XENSTORE_RING_SIZE);
409 char *
buf, uint32_t *len)
412 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
413 if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
414 *len = XENSTORE_RING_SIZE - (prod - cons);
415 return (
buf + MASK_XENSTORE_IDX(prod));
431 const char *
buf, uint32_t *len)
434 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
435 if ((prod - cons) < *len)
437 return (
buf + MASK_XENSTORE_IDX(cons));
457 XENSTORE_RING_IDX cons, prod;
458 const char *data = (
const char *)tdata;
470 if ((prod - cons) == XENSTORE_RING_SIZE) {
485 if (error && error != EWOULDBLOCK)
503 memcpy(dst, data, avail);
546 XENSTORE_RING_IDX cons, prod;
547 char *data = (
char *)tdata;
573 if (error && error != EWOULDBLOCK)
595 memcpy(data, src, avail);
634 msg = malloc(
sizeof(*msg), M_XENSTORE, M_WAITOK);
637 free(msg, M_XENSTORE);
641 body = malloc(msg->hdr.len + 1, M_XENSTORE, M_WAITOK);
644 free(body, M_XENSTORE);
645 free(msg, M_XENSTORE);
648 body[msg->hdr.len] =
'\0';
650 *type = msg->hdr.type;
651 if (msg->hdr.type == XS_WATCH_EVENT) {
652 msg->
u.watch.vec =
split(body, msg->hdr.len,
653 &msg->
u.watch.vec_size);
657 msg->
u.watch.vec[XS_WATCH_TOKEN]);
659 if (msg->
u.watch.handle != NULL &&
660 (!msg->
u.watch.handle->max_pending ||
661 msg->
u.watch.handle->pending <
662 msg->
u.watch.handle->max_pending)) {
663 msg->
u.watch.handle->pending++;
669 free(msg->
u.watch.vec, M_XENSTORE);
670 free(msg, M_XENSTORE);
674 msg->
u.reply.body = body;
694 enum xsd_sockmsg_type type;
699 printf(
"XENSTORE error %d while reading message\n",
705#define xsd_error_count (sizeof(xsd_errors) / sizeof(xsd_errors[0]))
722 if (!strcmp(errorstring, xsd_errors[i].errstring))
723 return (xsd_errors[i].errnum);
725 log(LOG_WARNING,
"XENSTORE xen store gave: unknown error %s",
751 if (error && error != EWOULDBLOCK) {
760 *type = msg->hdr.type;
763 body = msg->
u.reply.body;
765 free(msg, M_XENSTORE);
817xs_talkv(
struct xs_transaction t,
enum xsd_sockmsg_type request_type,
818 const struct iovec *iovec, u_int num_vecs, u_int *len,
void **result)
820 struct xsd_sockmsg msg;
827 msg.type = request_type;
829 for (i = 0; i < num_vecs; i++)
830 msg.len += iovec[i].iov_len;
835 printf(
"xs_talkv failed %d\n", error);
836 goto error_lock_held;
839 for (i = 0; i < num_vecs; i++) {
842 printf(
"xs_talkv failed %d\n", error);
843 goto error_lock_held;
854 if (msg.type == XS_ERROR) {
856 free(ret, M_XENSTORE);
861 KASSERT(msg.type == request_type, (
"bad xenstore message type"));
866 free(ret, M_XENSTORE);
888xs_single(
struct xs_transaction t,
enum xsd_sockmsg_type request_type,
889 const char *body, u_int *len,
void **result)
893 iovec.iov_base = (
void *)(uintptr_t)body;
894 iovec.iov_len = strlen(body) + 1;
896 return (
xs_talkv(t, request_type, &iovec, 1, len, result));
914 iov[0].iov_base = (
void *)(uintptr_t) path;
915 iov[0].iov_len = strlen(path) + 1;
916 iov[1].iov_base = (
void *)(uintptr_t) token;
917 iov[1].iov_len = strlen(token) + 1;
919 return (
xs_talkv(XST_NIL, XS_WATCH, iov, 2, NULL, NULL));
936 iov[0].iov_base = (
void *)(uintptr_t) path;
937 iov[0].iov_len = strlen(path) + 1;
938 iov[1].iov_base = (
void *)(uintptr_t) token;
939 iov[1].iov_len = strlen(token) + 1;
941 return (
xs_talkv(XST_NIL, XS_UNWATCH, iov, 2, NULL, NULL));
957 cmp = (
void *)strtoul(token, NULL, 16);
979 PWAIT | PCATCH,
"waitev", hz/10);
988 msg->
u.watch.handle->pending--;
999 if (msg->
u.watch.handle->callback != NULL)
1000 msg->
u.watch.handle->callback(
1001 msg->
u.watch.handle,
1002 (
const char **)msg->
u.watch.vec,
1003 msg->
u.watch.vec_size);
1004 free(msg->
u.watch.vec, M_XENSTORE);
1005 free(msg, M_XENSTORE);
1025 log(LOG_WARNING,
"XENSTORE response ring is not quiescent "
1026 "(%08x:%08x): fixing up\n",
1034 NULL,
xs_intr, NULL, INTR_TYPE_NET|INTR_MPSAFE,
1037 log(LOG_WARNING,
"XENSTORE request irq failed %i\n", error);
1049 BUS_ADD_CHILD(parent, 0,
"xenstore", 0);
1066 device_set_desc(dev,
"XenStore");
1067 return (BUS_PROBE_NOWILDCARD);
1084 KASSERT((pending == 1), (
"xs late attach queued several times"));
1102 device_set_softc(dev, &
xs);
1108 xs.
evtchn = xen_get_xenstore_evtchn();
1110 struct evtchn_alloc_unbound alloc_unbound;
1113 alloc_unbound.dom = DOMID_SELF;
1114 alloc_unbound.remote_dom = DOMID_SELF;
1115 error = HYPERVISOR_event_channel_op(
1116 EVTCHNOP_alloc_unbound, &alloc_unbound);
1119 "unable to alloc event channel for Dom0: %d",
1125 xen_store = malloc(PAGE_SIZE, M_XENSTORE, M_WAITOK | M_ZERO);
1128 xs.
gpfn = xen_get_xenstore_mfn();
1137 mtx_init(&
xs.
ring_lock,
"ring lock", NULL, MTX_DEF);
1156 RFHIGHPID, 0,
"xenstore_rcv");
1179 error = bus_generic_suspend(dev);
1195 char token[
sizeof(watch) * 2 + 1];
1208 sprintf(token,
"%lX", (
long)watch);
1213 bus_generic_resume(dev);
1224 DEVMETHOD(device_detach, bus_generic_detach),
1225 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1230 DEVMETHOD(bus_add_child, bus_generic_add_child),
1231 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
1232 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
1233 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1234 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1276 u_int *num,
const char ***result)
1284 error =
xs_single(t, XS_DIRECTORY, sbuf_data(path), &len,
1290 *result =
split(strings, len, num);
1296xs_exists(
struct xs_transaction t,
const char *dir,
const char *node)
1304 free(d, M_XENSTORE);
1309xs_read(
struct xs_transaction t,
const char *dir,
const char *node,
1310 u_int *len,
void **result)
1317 error =
xs_single(t, XS_READ, sbuf_data(path), len, &ret);
1326xs_write(
struct xs_transaction t,
const char *dir,
const char *node,
1330 struct iovec iovec[2];
1335 iovec[0].iov_base = (
void *)(uintptr_t) sbuf_data(path);
1336 iovec[0].iov_len = sbuf_len(path) + 1;
1337 iovec[1].iov_base = (
void *)(uintptr_t) string;
1338 iovec[1].iov_len = strlen(
string);
1340 error =
xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL);
1347xs_mkdir(
struct xs_transaction t,
const char *dir,
const char *node)
1353 ret =
xs_single(t, XS_MKDIR, sbuf_data(path), NULL, NULL);
1360xs_rm(
struct xs_transaction t,
const char *dir,
const char *node)
1366 ret =
xs_single(t, XS_RM, sbuf_data(path), NULL, NULL);
1373xs_rm_tree(
struct xs_transaction xbt,
const char *base,
const char *node)
1375 struct xs_transaction local_xbt;
1376 struct sbuf *root_path_sbuf;
1377 struct sbuf *cur_path_sbuf;
1384 root_path_sbuf =
xs_join(base, node);
1385 cur_path_sbuf =
xs_join(base, node);
1386 root_path = sbuf_data(root_path_sbuf);
1387 cur_path = sbuf_data(cur_path_sbuf);
1406 for (i = 0; i < count; i++) {
1407 error =
xs_rm(xbt, cur_path, dir[i]);
1408 if (error == ENOTEMPTY) {
1409 struct sbuf *push_dir;
1416 push_dir =
xs_join(cur_path, dir[i]);
1417 sbuf_delete(cur_path_sbuf);
1418 cur_path_sbuf = push_dir;
1419 cur_path = sbuf_data(cur_path_sbuf);
1421 }
else if (error != 0) {
1426 free(dir, M_XENSTORE);
1433 error =
xs_rm(xbt, cur_path,
"");
1437 if (!strcmp(cur_path, root_path))
1441 last_slash = strrchr(cur_path,
'/');
1442 KASSERT(last_slash != NULL,
1443 (
"xs_rm_tree: mangled path %s", cur_path));
1449 sbuf_delete(cur_path_sbuf);
1450 sbuf_delete(root_path_sbuf);
1452 free(dir, M_XENSTORE);
1454 if (local_xbt.id != 0) {
1459 if (terror == EAGAIN && error == 0)
1471 error =
xs_single(XST_NIL, XS_TRANSACTION_START,
"", NULL,
1474 t->id = strtoul(id_str, NULL, 0);
1475 free(id_str, M_XENSTORE);
1486 strcpy(abortstr,
"F");
1488 strcpy(abortstr,
"T");
1490 return (
xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL));
1494xs_scanf(
struct xs_transaction t,
const char *dir,
const char *node,
1495 int *scancountp,
const char *fmt, ...)
1501 error =
xs_read(t, dir, node, NULL, (
void **) &val);
1506 ns = vsscanf(val, fmt, ap);
1508 free(val, M_XENSTORE);
1519 const char *dir,
const char *node,
const char *fmt, va_list ap)
1524 sb = sbuf_new_auto();
1525 sbuf_vprintf(sb, fmt, ap);
1527 error =
xs_write(t, dir, node, sbuf_data(sb));
1534xs_printf(
struct xs_transaction t,
const char *dir,
const char *node,
1535 const char *fmt, ...)
1556 while (error == 0 && (name = va_arg(ap,
char *)) != NULL) {
1557 const char *fmt = va_arg(ap,
char *);
1558 void *result = va_arg(ap,
void *);
1561 error =
xs_read(t, dir, name, NULL, (
void **) &p);
1566 if (sscanf(p, fmt, result) == 0)
1568 free(p, M_XENSTORE);
1570 *(
char **)result = p;
1581 char token[
sizeof(watch) * 2 + 1];
1585 sprintf(token,
"%lX", (
long)watch);
1588 KASSERT(
find_watch(token) == NULL, (
"watch already registered"));
1592 error =
xs_watch(watch->node, token);
1595 if (error == EEXIST)
1600 LIST_REMOVE(watch, list);
1611 char token[
sizeof(watch) * 2 + 1];
1614 sprintf(token,
"%lX", (
long)watch);
1621 LIST_REMOVE(watch, list);
1626 log(LOG_WARNING,
"XENSTORE Failed to release watch %s: %i\n",
1627 watch->node, error);
1632 if (msg->
u.watch.handle != watch)
1635 free(msg->
u.watch.vec, M_XENSTORE);
1636 free(msg, M_XENSTORE);
struct intr_config_hook xs_attachcb
struct xs_watch_list registered_watches
struct mtx registered_watches_lock
struct xs_stored_msg_list reply_list
xen_intr_handle_t xen_intr_handle
struct mtx watch_events_lock
struct xs_stored_msg_list watch_events
TAILQ_ENTRY(xs_stored_msg)
static int xs_watch(const char *path, const char *token)
static int xs_process_msg(enum xsd_sockmsg_type *type)
int xs_dev_request_and_reply(struct xsd_sockmsg *msg, void **result)
static int xs_check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
static void * xs_get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod, char *buf, uint32_t *len)
static int xs_get_error(const char *errorstring)
struct sbuf * xs_join(const char *dir, const char *name)
static void xs_rcv_thread(void *arg __unused)
static int xs_attach(device_t dev)
static int xs_single(struct xs_transaction t, enum xsd_sockmsg_type request_type, const char *body, u_int *len, void **result)
int xs_write(struct xs_transaction t, const char *dir, const char *node, const char *string)
int xs_printf(struct xs_transaction t, const char *dir, const char *node, const char *fmt,...)
static void xenwatch_thread(void *unused)
evtchn_port_t xs_evtchn(void)
static int xs_init_comms(void)
bool xs_initialized(void)
int xs_transaction_start(struct xs_transaction *t)
static struct xenstore_domain_interface * xen_store
static device_method_t xenstore_methods[]
static int xs_suspend(device_t dev)
static void xs_intr(void *arg __unused)
DRIVER_MODULE(xenstore, xenpv, xenstore_driver, xenstore_devclass, 0, 0)
int xs_read(struct xs_transaction t, const char *dir, const char *node, u_int *len, void **result)
static void xs_attach_late(void *arg, int pending)
int xs_transaction_end(struct xs_transaction t, int abort)
int xs_directory(struct xs_transaction t, const char *dir, const char *node, u_int *num, const char ***result)
void xs_unregister_watch(struct xs_watch *watch)
static u_int extract_strings(const char *strings, const char **dest, u_int len)
static int xs_probe(device_t dev)
static int xs_talkv(struct xs_transaction t, enum xsd_sockmsg_type request_type, const struct iovec *iovec, u_int num_vecs, u_int *len, void **result)
int xs_scanf(struct xs_transaction t, const char *dir, const char *node, int *scancountp, const char *fmt,...)
static const void * xs_get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod, const char *buf, uint32_t *len)
int xs_mkdir(struct xs_transaction t, const char *dir, const char *node)
vm_paddr_t xs_address(void)
static struct xs_softc xs
static void xs_attach_deferred(void *arg)
static int xs_read_reply(enum xsd_sockmsg_type *type, u_int *len, void **result)
int xs_vprintf(struct xs_transaction t, const char *dir, const char *node, const char *fmt, va_list ap)
TAILQ_HEAD(xs_stored_msg_list, xs_stored_msg)
SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "Xen")
static const char ** split(char *strings, u_int len, u_int *num)
int xs_gather(struct xs_transaction t, const char *dir,...)
static int xs_unwatch(const char *path, const char *token)
int xs_exists(struct xs_transaction t, const char *dir, const char *node)
SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xs.evtchn, 0, "")
int xs_rm(struct xs_transaction t, const char *dir, const char *node)
static void xs_identify(driver_t *driver, device_t parent)
static int xs_resume(device_t dev __unused)
static int xs_read_store(void *tdata, unsigned len)
int xs_rm_tree(struct xs_transaction xbt, const char *base, const char *node)
static devclass_t xenstore_devclass
DEFINE_CLASS_0(xenstore, xenstore_driver, xenstore_methods, 0)
MALLOC_DEFINE(M_XENSTORE, "xenstore", "XenStore data and results")
int xs_register_watch(struct xs_watch *watch)
static struct xs_watch * find_watch(const char *token)
static int xs_write_store(const void *tdata, unsigned len)
SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD,(u_long *) &xen_store, 0, "")