diff options
author | dfr <dfr@FreeBSD.org> | 2008-11-22 16:14:52 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-11-22 16:14:52 +0000 |
commit | 19b6af98ec71398e77874582eb84ec5310c7156f (patch) | |
tree | 61eebb1b357f3edaa339d295e26a47a74534ac23 /sys/xen/xenbus | |
parent | 83299de5870b2dc099c17aec548d3502821bc29b (diff) | |
download | FreeBSD-src-19b6af98ec71398e77874582eb84ec5310c7156f.zip FreeBSD-src-19b6af98ec71398e77874582eb84ec5310c7156f.tar.gz |
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
performance in Xen's HVM mode.
Diffstat (limited to 'sys/xen/xenbus')
-rw-r--r-- | sys/xen/xenbus/init.txt | 14 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_client.c | 318 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_comms.c | 251 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_comms.h | 157 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_dev.c | 259 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_probe.c | 1134 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_probe_backend.c | 308 | ||||
-rw-r--r-- | sys/xen/xenbus/xenbus_xs.c | 960 |
8 files changed, 0 insertions, 3401 deletions
diff --git a/sys/xen/xenbus/init.txt b/sys/xen/xenbus/init.txt deleted file mode 100644 index 4249549..0000000 --- a/sys/xen/xenbus/init.txt +++ /dev/null @@ -1,14 +0,0 @@ - - -- frontend driver initializes static xenbus_driver with _ids, _probe, _remove, -_resume, _otherend_changed - - - initialization calls xenbus_register_frontend(xenbus_driver) - - - xenbus_register_frontend sets read_otherend details to read_backend_details - then calls xenbus_register_driver_common(xenbus_driver, xenbus_frontend) - - - xenbus_register_driver_common sets underlying driver name to xenbus_driver name - underlying driver bus to xenbus_frontend's bus, driver's probe to xenbus_dev_probe - driver's remove to xenbus_dev_remove then calls driver_register - diff --git a/sys/xen/xenbus/xenbus_client.c b/sys/xen/xenbus/xenbus_client.c deleted file mode 100644 index a6f9e6b..0000000 --- a/sys/xen/xenbus/xenbus_client.c +++ /dev/null @@ -1,318 +0,0 @@ -/****************************************************************************** - * Client-facing interface for the Xenbus driver. In other words, the - * interface between the Xenbus and the device-specific code, be it the - * frontend or the backend of that driver. - * - * Copyright (C) 2005 XenSource Ltd - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#if 0 -#define DPRINTK(fmt, args...) \ - printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/cdefs.h> -#include <sys/types.h> -#include <sys/malloc.h> -#include <sys/libkern.h> - -#include <machine/xen/xen-os.h> -#include <machine/xen/evtchn.h> -#include <xen/gnttab.h> -#include <machine/xen/xenbus.h> -#include <machine/stdarg.h> - - -#define EXPORT_SYMBOL(x) -#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK) -#define kfree(ptr) free(ptr, M_DEVBUF) -#define BUG_ON PANIC_IF - - -const char *xenbus_strstate(XenbusState state) -{ - static const char *const name[] = { - [ XenbusStateUnknown ] = "Unknown", - [ XenbusStateInitialising ] = "Initialising", - [ XenbusStateInitWait ] = "InitWait", - [ XenbusStateInitialised ] = "Initialised", - [ XenbusStateConnected ] = "Connected", - [ XenbusStateClosing ] = "Closing", - [ XenbusStateClosed ] = "Closed", - }; - return (state < (XenbusStateClosed + 1)) ? name[state] : "INVALID"; -} - -int -xenbus_watch_path(struct xenbus_device *dev, char *path, - struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)) -{ - int err; - - watch->node = path; - watch->callback = callback; - - err = register_xenbus_watch(watch); - - if (err) { - watch->node = NULL; - watch->callback = NULL; - xenbus_dev_fatal(dev, err, "adding watch on %s", path); - } - - return err; -} -EXPORT_SYMBOL(xenbus_watch_path); - - -int xenbus_watch_path2(struct xenbus_device *dev, const char *path, - const char *path2, struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)) -{ - int err; - char *state = - kmalloc(strlen(path) + 1 + strlen(path2) + 1, GFP_KERNEL); - if (!state) { - xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch"); - return -ENOMEM; - } - strcpy(state, path); - strcat(state, "/"); - strcat(state, path2); - - err = xenbus_watch_path(dev, state, watch, callback); - - if (err) { - kfree(state); - } - return err; -} -EXPORT_SYMBOL(xenbus_watch_path2); - - -int xenbus_switch_state(struct xenbus_device *dev, - XenbusState state) -{ - /* We check whether the state is currently set to the given value, and - if not, then the state is set. We don't want to unconditionally - write the given state, because we don't want to fire watches - unnecessarily. Furthermore, if the node has gone, we don't write - to it, as the device will be tearing down, and we don't want to - resurrect that directory. - */ - - int current_state; - int err; - - if (state == dev->state) - return (0); - - err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d", - ¤t_state); - if (err != 1) - return 0; - - err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state); - if (err) { - if (state != XenbusStateClosing) /* Avoid looping */ - xenbus_dev_fatal(dev, err, "writing new state"); - return err; - } - - dev->state = state; - return 0; - -} - -int xenbus_frontend_closed(struct xenbus_device *dev) -{ - xenbus_switch_state(dev, XenbusStateClosed); -#if 0 - complete(&dev->down); -#endif - return 0; -} - -/** - * Return the path to the error node for the given device, or NULL on failure. - * If the value returned is non-NULL, then it is the caller's to kfree. - */ -static char *error_path(struct xenbus_device *dev) -{ - char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) + - 1, GFP_KERNEL); - if (path_buffer == NULL) { - return NULL; - } - - strcpy(path_buffer, "error/"); - strcpy(path_buffer + strlen("error/"), dev->nodename); - - return path_buffer; -} - - -static void _dev_error(struct xenbus_device *dev, int err, const char *fmt, - va_list ap) -{ - int ret; - unsigned int len; - char *printf_buffer = NULL, *path_buffer = NULL; - -#define PRINTF_BUFFER_SIZE 4096 - printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); - if (printf_buffer == NULL) - goto fail; - - len = sprintf(printf_buffer, "%i ", -err); - ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); - - BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1); -#if 0 - dev_err(&dev->dev, "%s\n", printf_buffer); -#endif - path_buffer = error_path(dev); - - if (path_buffer == NULL) { - printk("xenbus: failed to write error node for %s (%s)\n", - dev->nodename, printf_buffer); - goto fail; - } - - if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) { - printk("xenbus: failed to write error node for %s (%s)\n", - dev->nodename, printf_buffer); - goto fail; - } - - fail: - if (printf_buffer) - kfree(printf_buffer); - if (path_buffer) - kfree(path_buffer); -} - - -void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, - ...) -{ - va_list ap; - - va_start(ap, fmt); - _dev_error(dev, err, fmt, ap); - va_end(ap); -} -EXPORT_SYMBOL(xenbus_dev_error); - - -void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, - ...) -{ - va_list ap; - - va_start(ap, fmt); - _dev_error(dev, err, fmt, ap); - va_end(ap); - - xenbus_switch_state(dev, XenbusStateClosing); -} -EXPORT_SYMBOL(xenbus_dev_fatal); - - -int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) -{ - int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); - if (err < 0) - xenbus_dev_fatal(dev, err, "granting access to ring page"); - return err; -} -EXPORT_SYMBOL(xenbus_grant_ring); - - -int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) -{ - struct evtchn_alloc_unbound alloc_unbound; - int err; - - alloc_unbound.dom = DOMID_SELF; - alloc_unbound.remote_dom = dev->otherend_id; - - err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, - &alloc_unbound); - - if (err) - xenbus_dev_fatal(dev, err, "allocating event channel"); - else - *port = alloc_unbound.port; - return err; -} -EXPORT_SYMBOL(xenbus_alloc_evtchn); - - -int xenbus_free_evtchn(struct xenbus_device *dev, int port) -{ - struct evtchn_close close; - int err; - - close.port = port; - - err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); - if (err) - xenbus_dev_error(dev, err, "freeing event channel %d", port); - return err; -} -EXPORT_SYMBOL(xenbus_free_evtchn); - - -XenbusState xenbus_read_driver_state(const char *path) -{ - XenbusState result; - - int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL); - if (err) - result = XenbusStateClosed; - - return result; -} -EXPORT_SYMBOL(xenbus_read_driver_state); - - -/* - * Local variables: - * c-file-style: "linux" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/sys/xen/xenbus/xenbus_comms.c b/sys/xen/xenbus/xenbus_comms.c deleted file mode 100644 index 8f0f171..0000000 --- a/sys/xen/xenbus/xenbus_comms.c +++ /dev/null @@ -1,251 +0,0 @@ -/****************************************************************************** - * xenbus_comms.c - * - * Low level code to talks to Xen Store: ringbuffer and event channel. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/time.h> -#include <sys/errno.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/syslog.h> -#include <sys/proc.h> -#include <sys/kernel.h> - - - -#include <machine/xen/xen-os.h> -#include <machine/xen/hypervisor.h> -#include <machine/xen/evtchn.h> -#include <machine/xen/xenbus.h> -#include <machine/xen/xen_intr.h> -#include <xen/xenbus/xenbus_comms.h> - -static int xenbus_irq; - -extern void xenbus_probe(void *); -extern int xenstored_ready; -#if 0 -static DECLARE_WORK(probe_work, xenbus_probe, NULL); -#endif -int xb_wait; -extern char *xen_store; -#define wake_up wakeup -#define xb_waitq xb_wait -#define pr_debug(a,b,c) - -static inline struct xenstore_domain_interface *xenstore_domain_interface(void) -{ - return (struct xenstore_domain_interface *)xen_store; -} - -static void -wake_waiting(void * arg __attribute__((unused))) -{ -#if 0 - if (unlikely(xenstored_ready == 0)) { - xenstored_ready = 1; - schedule_work(&probe_work); - } -#endif - wakeup(&xb_wait); -} - -static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) -{ - return ((prod - cons) <= XENSTORE_RING_SIZE); -} - -static void *get_output_chunk(XENSTORE_RING_IDX cons, - XENSTORE_RING_IDX prod, - char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); - if ((XENSTORE_RING_SIZE - (prod - cons)) < *len) - *len = XENSTORE_RING_SIZE - (prod - cons); - return buf + MASK_XENSTORE_IDX(prod); -} - -static const void *get_input_chunk(XENSTORE_RING_IDX cons, - XENSTORE_RING_IDX prod, - const char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); - if ((prod - cons) < *len) - *len = prod - cons; - return buf + MASK_XENSTORE_IDX(cons); -} - -int xb_write(const void *tdata, unsigned len) -{ - struct xenstore_domain_interface *intf = xenstore_domain_interface(); - XENSTORE_RING_IDX cons, prod; - const char *data = (const char *)tdata; - - while (len != 0) { - void *dst; - unsigned int avail; - - wait_event_interruptible(&xb_waitq, - (intf->req_prod - intf->req_cons) != - XENSTORE_RING_SIZE); - - /* Read indexes, then verify. */ - cons = intf->req_cons; - prod = intf->req_prod; - mb(); - if (!check_indexes(cons, prod)) { - intf->req_cons = intf->req_prod = 0; - return -EIO; - } - - dst = get_output_chunk(cons, prod, intf->req, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - mb(); - - memcpy(dst, data, avail); - data += avail; - len -= avail; - - /* Other side must not see new header until data is there. */ - wmb(); - intf->req_prod += avail; - - /* This implies mb() before other side sees interrupt. */ - notify_remote_via_evtchn(xen_start_info->store_evtchn); - } - - return 0; -} - -#ifdef notyet -int xb_data_to_read(void) -{ - struct xenstore_domain_interface *intf = xen_store_interface; - return (intf->rsp_cons != intf->rsp_prod); -} - -int xb_wait_for_data_to_read(void) -{ - return wait_event_interruptible(xb_waitq, xb_data_to_read()); -} -#endif - - -int xb_read(void *tdata, unsigned len) -{ - struct xenstore_domain_interface *intf = xenstore_domain_interface(); - XENSTORE_RING_IDX cons, prod; - char *data = (char *)tdata; - - while (len != 0) { - unsigned int avail; - const char *src; - - wait_event_interruptible(&xb_waitq, - intf->rsp_cons != intf->rsp_prod); - - /* Read indexes, then verify. */ - cons = intf->rsp_cons; - prod = intf->rsp_prod; - if (!check_indexes(cons, prod)) { - intf->rsp_cons = intf->rsp_prod = 0; - return -EIO; - } - - src = get_input_chunk(cons, prod, intf->rsp, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - - /* We must read header before we read data. */ - rmb(); - - memcpy(data, src, avail); - data += avail; - len -= avail; - - /* Other side must not see free space until we've copied out */ - mb(); - intf->rsp_cons += avail; - - pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); - - /* Implies mb(): they will see new header. */ - notify_remote_via_evtchn(xen_start_info->store_evtchn); - } - - return 0; -} - -/* Set up interrupt handler off store event channel. */ -int xb_init_comms(void) -{ - struct xenstore_domain_interface *intf = xenstore_domain_interface(); - int err; - - if (intf->rsp_prod != intf->rsp_cons) { - log(LOG_WARNING, "XENBUS response ring is not quiescent " - "(%08x:%08x): fixing up\n", - intf->rsp_cons, intf->rsp_prod); - intf->rsp_cons = intf->rsp_prod; - } - - if (xenbus_irq) - unbind_from_irqhandler(xenbus_irq, &xb_waitq); - - err = bind_caller_port_to_irqhandler( - xen_start_info->store_evtchn, - "xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL); - if (err <= 0) { - log(LOG_WARNING, "XENBUS request irq failed %i\n", err); - return err; - } - - xenbus_irq = err; - - return 0; -} - -/* - * Local variables: - * c-file-style: "bsd" - * indent-tabs-mode: t - * c-indent-level: 4 - * c-basic-offset: 8 - * tab-width: 4 - * End: - */ diff --git a/sys/xen/xenbus/xenbus_comms.h b/sys/xen/xenbus/xenbus_comms.h deleted file mode 100644 index 871afd5..0000000 --- a/sys/xen/xenbus/xenbus_comms.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Private include for xenbus communications. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _XENBUS_COMMS_H -#define _XENBUS_COMMS_H - -int xs_init(void); -int xb_init_comms(void); - -/* Low level routines. */ -int xb_write(const void *data, unsigned len); -int xb_read(void *data, unsigned len); -int xs_input_avail(void); -extern int xb_waitq; -extern int xenbus_running; - -#define __wait_event_interruptible(wchan, condition, ret) \ -do { \ - for (;;) { \ - if (xenbus_running == 0) { \ - break; \ - } \ - if (condition) \ - break; \ - if ((ret = !tsleep(wchan, PWAIT | PCATCH, "waitev", hz/10))) \ - break; \ - } \ -} while (0) - - -#define wait_event_interruptible(wchan, condition) \ -({ \ - int __ret = 0; \ - if (!(condition)) \ - __wait_event_interruptible(wchan, condition, __ret); \ - __ret; \ -}) - - - -#define DECLARE_MUTEX(lock) struct sema lock -#define semaphore sema -#define rw_semaphore sema - -#define down sema_wait -#define up sema_post -#define down_read sema_wait -#define up_read sema_post -#define down_write sema_wait -#define up_write sema_post - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - - -/* - * XXX - * - */ - -#define GFP_KERNEL 1 -#define EXPORT_SYMBOL(x) -#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK) -#define kfree(ptr) free((void *)(uintptr_t)ptr, M_DEVBUF) -#define BUG_ON PANIC_IF -#define semaphore sema -#define rw_semaphore sema -#define DEFINE_SPINLOCK(lock) struct mtx lock -#define DECLARE_MUTEX(lock) struct sema lock -#define u32 uint32_t -#define list_del(head, ent) TAILQ_REMOVE(head, ent, list) -#define simple_strtoul strtoul -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -#define list_empty TAILQ_EMPTY -#define wake_up wakeup -#define BUS_ID_SIZE 128 - -struct xen_bus_type -{ - char *root; - unsigned int levels; - int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); - int (*probe)(const char *type, const char *dir); - struct xendev_list_head *bus; - int error; -#if 0 - struct bus_type bus; - struct device dev; -#endif -}; - - -extern void xenbus_backend_probe_and_watch(void); -int xenbus_probe_node(struct xen_bus_type *bus, const char *type, - const char *nodename); -int xenbus_probe_devices(struct xen_bus_type *bus); - -int xenbus_register_driver_common(struct xenbus_driver *drv, - struct xen_bus_type *bus); - -void dev_changed(const char *node, struct xen_bus_type *bus); - -int -read_otherend_details(struct xenbus_device *xendev, char *id_node, - char *path_node); - -char *kasprintf(const char *fmt, ...); - - - - -#endif /* _XENBUS_COMMS_H */ - -/* - * Local variables: - * c-file-style: "linux" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/sys/xen/xenbus/xenbus_dev.c b/sys/xen/xenbus/xenbus_dev.c deleted file mode 100644 index 8a13322..0000000 --- a/sys/xen/xenbus/xenbus_dev.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * xenbus_dev.c - * - * Driver giving user-space access to the kernel's xenbus connection - * to xenstore. - * - * Copyright (c) 2005, Christian Limpach - * Copyright (c) 2005, Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/errno.h> -#include <sys/uio.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/conf.h> - - -#include <machine/xen/xen-os.h> -#include <machine/xen/hypervisor.h> -#include <machine/xen/xenbus.h> -#include <machine/xen/hypervisor.h> -#include <xen/xenbus/xenbus_comms.h> - - - - -#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK) -#define BUG_ON PANIC_IF -#define semaphore sema -#define rw_semaphore sema -#define DEFINE_SPINLOCK(lock) struct mtx lock -#define DECLARE_MUTEX(lock) struct sema lock -#define u32 uint32_t -#define simple_strtoul strtoul - -struct xenbus_dev_transaction { - LIST_ENTRY(xenbus_dev_transaction) list; - struct xenbus_transaction handle; -}; - -struct xenbus_dev_data { - /* In-progress transaction. */ - LIST_HEAD(xdd_list_head, xenbus_dev_transaction) transactions; - - /* Partial request. */ - unsigned int len; - union { - struct xsd_sockmsg msg; - char buffer[PAGE_SIZE]; - } u; - - /* Response queue. */ -#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1)) - char read_buffer[PAGE_SIZE]; - unsigned int read_cons, read_prod; - int read_waitq; -}; -#if 0 -static struct proc_dir_entry *xenbus_dev_intf; -#endif -static int -xenbus_dev_read(struct cdev *dev, struct uio *uio, int ioflag) -{ - int i = 0; - struct xenbus_dev_data *u = dev->si_drv1; - - if (wait_event_interruptible(&u->read_waitq, - u->read_prod != u->read_cons)) - return EINTR; - - for (i = 0; i < uio->uio_iov[0].iov_len; i++) { - if (u->read_cons == u->read_prod) - break; - copyout(&u->read_buffer[MASK_READ_IDX(u->read_cons)], (char *)uio->uio_iov[0].iov_base+i, 1); - u->read_cons++; - uio->uio_resid--; - } - return 0; -} - -static void queue_reply(struct xenbus_dev_data *u, - char *data, unsigned int len) -{ - int i; - - for (i = 0; i < len; i++, u->read_prod++) - u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i]; - - BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer)); - - wakeup(&u->read_waitq); -} - -static int -xenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag) -{ - int err = 0; - struct xenbus_dev_data *u = dev->si_drv1; - struct xenbus_dev_transaction *trans; - void *reply; - int len = uio->uio_iov[0].iov_len; - - if ((len + u->len) > sizeof(u->u.buffer)) - return EINVAL; - - if (copyin(u->u.buffer + u->len, uio->uio_iov[0].iov_base, len) != 0) - return EFAULT; - - u->len += len; - if (u->len < (sizeof(u->u.msg) + u->u.msg.len)) - return len; - - switch (u->u.msg.type) { - case XS_TRANSACTION_START: - case XS_TRANSACTION_END: - case XS_DIRECTORY: - case XS_READ: - case XS_GET_PERMS: - case XS_RELEASE: - case XS_GET_DOMAIN_PATH: - case XS_WRITE: - case XS_MKDIR: - case XS_RM: - case XS_SET_PERMS: - reply = xenbus_dev_request_and_reply(&u->u.msg); - if (IS_ERR(reply)) { - err = PTR_ERR(reply); - } else { - if (u->u.msg.type == XS_TRANSACTION_START) { - trans = kmalloc(sizeof(*trans), GFP_KERNEL); - trans->handle.id = simple_strtoul(reply, NULL, 0); - LIST_INSERT_HEAD(&u->transactions, trans, list); - } else if (u->u.msg.type == XS_TRANSACTION_END) { - LIST_FOREACH(trans, &u->transactions, - list) - if (trans->handle.id == - u->u.msg.tx_id) - break; -#if 0 /* XXX does this mean the list is empty? */ - BUG_ON(&trans->list == &u->transactions); -#endif - LIST_REMOVE(trans, list); - kfree(trans); - } - queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); - queue_reply(u, (char *)reply, u->u.msg.len); - kfree(reply); - } - break; - - default: - err = EINVAL; - break; - } - - if (err == 0) { - u->len = 0; - err = len; - } - - return err; -} - -static int xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) -{ - struct xenbus_dev_data *u; - - if (xen_start_info->store_evtchn == 0) - return ENOENT; -#if 0 /* XXX figure out if equiv needed */ - nonseekable_open(inode, filp); -#endif - u = kmalloc(sizeof(*u), GFP_KERNEL); - if (u == NULL) - return ENOMEM; - - memset(u, 0, sizeof(*u)); - LIST_INIT(&u->transactions); - - dev->si_drv1 = u; - - return 0; -} - -static int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) -{ - struct xenbus_dev_data *u = dev->si_drv1; - struct xenbus_dev_transaction *trans, *tmp; - - LIST_FOREACH_SAFE(trans, &u->transactions, list, tmp) { - xenbus_transaction_end(trans->handle, 1); - LIST_REMOVE(trans, list); - kfree(trans); - } - - kfree(u); - return 0; -} - -static struct cdevsw xenbus_dev_cdevsw = { - .d_version = D_VERSION, - .d_read = xenbus_dev_read, - .d_write = xenbus_dev_write, - .d_open = xenbus_dev_open, - .d_close = xenbus_dev_close, - .d_name = "xenbus_dev", -}; - -static int -xenbus_dev_sysinit(void) -{ - make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, "xenbus"); - - return 0; -} -SYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, xenbus_dev_sysinit, NULL); -/* SYSINIT NEEDED XXX */ - - - -/* - * Local variables: - * c-file-style: "linux" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c deleted file mode 100644 index c45a375..0000000 --- a/sys/xen/xenbus/xenbus_probe.c +++ /dev/null @@ -1,1134 +0,0 @@ -/****************************************************************************** - * Talks to Xen Store to figure out what devices we have. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * Copyright (C) 2005 Mike Wray, Hewlett-Packard - * Copyright (C) 2005 XenSource Ltd - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#if 0 -#define DPRINTK(fmt, args...) \ - printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/time.h> -#include <sys/sema.h> -#include <sys/eventhandler.h> -#include <sys/errno.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/systm.h> -#include <sys/syslog.h> -#include <sys/proc.h> -#include <sys/bus.h> -#include <sys/sx.h> - -#include <machine/xen/xen-os.h> -#include <machine/xen/hypervisor.h> -#include <machine/xen/xenbus.h> -#include <machine/xen/evtchn.h> -#include <machine/stdarg.h> - -#include <xen/xenbus/xenbus_comms.h> - -struct xendev_list_head xenbus_device_frontend_list; -struct xendev_list_head xenbus_device_backend_list; -static LIST_HEAD(, xenbus_driver) xendrv_list; - -extern struct sx xenwatch_mutex; - -EVENTHANDLER_DECLARE(xenstore_event, xenstore_event_handler_t); -static struct eventhandler_list *xenstore_chain; -device_t xenbus_dev; -device_t xenbus_backend_dev; -static MALLOC_DEFINE(M_XENDEV, "xenintrdrv", "xen system device"); - -#define streq(a, b) (strcmp((a), (b)) == 0) - -static int watch_otherend(struct xenbus_device *dev); - - -/* If something in array of ids matches this device, return it. */ -static const struct xenbus_device_id * -match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) -{ - for (; !streq(arr->devicetype, ""); arr++) { - if (streq(arr->devicetype, dev->devicetype)) - return arr; - } - return NULL; -} - -#if 0 -static int xenbus_match(device_t _dev) -{ - struct xenbus_driver *drv; - struct xenbus_device *dev; - - dev = device_get_softc(_dev); - drv = dev->driver; - - if (!drv->ids) - return 0; - - return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; -} -#endif - - -/* device/<type>/<id> => <type>-<id> */ -static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) -{ - nodename = strchr(nodename, '/'); - if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) { - log(LOG_WARNING, "XENBUS: bad frontend %s\n", nodename); - return -EINVAL; - } - - strlcpy(bus_id, nodename + 1, BUS_ID_SIZE); - if (!strchr(bus_id, '/')) { - log(LOG_WARNING, "XENBUS: bus_id %s no slash\n", bus_id); - return -EINVAL; - } - *strchr(bus_id, '/') = '-'; - return 0; -} - - -static void free_otherend_details(struct xenbus_device *dev) -{ - kfree((void*)(uintptr_t)dev->otherend); - dev->otherend = NULL; -} - - -static void free_otherend_watch(struct xenbus_device *dev) -{ - if (dev->otherend_watch.node) { - unregister_xenbus_watch(&dev->otherend_watch); - kfree(dev->otherend_watch.node); - dev->otherend_watch.node = NULL; - } -} - -int -read_otherend_details(struct xenbus_device *xendev, char *id_node, - char *path_node) -{ - int err = xenbus_gather(XBT_NIL, xendev->nodename, - id_node, "%i", &xendev->otherend_id, - path_node, NULL, &xendev->otherend, - NULL); - if (err) { - xenbus_dev_fatal(xendev, err, - "reading other end details from %s", - xendev->nodename); - return err; - } - if (strlen(xendev->otherend) == 0 || - !xenbus_exists(XBT_NIL, xendev->otherend, "")) { - xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s", - xendev->nodename); - kfree((void *)(uintptr_t)xendev->otherend); - xendev->otherend = NULL; - return -ENOENT; - } - - return 0; -} - - -static int read_backend_details(struct xenbus_device *xendev) -{ - return read_otherend_details(xendev, "backend-id", "backend"); -} - -#ifdef notyet -/* XXX - move to probe backend */ -static int read_frontend_details(struct xenbus_device *xendev) -{ - if (strncmp(xendev->nodename, "backend", 7)) - return -ENOENT; - return read_otherend_details(xendev, "frontend-id", "frontend"); -} -#endif - -/* Bus type for frontend drivers. */ -static int xenbus_probe_frontend(const char *type, const char *name); -static struct xen_bus_type xenbus_frontend = { - .root = "device", - .levels = 2, /* device/type/<id> */ - .get_bus_id = frontend_bus_id, - .probe = xenbus_probe_frontend, - .bus = &xenbus_device_frontend_list, -#if 0 - /* this initialization needs to happen dynamically */ - .bus = { - .name = "xen", - .match = xenbus_match, - }, - .dev = { - .bus_id = "xen", - }, -#endif -}; - -#if 0 -static int xenbus_hotplug_backend(device_t dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - panic("implement me"); -#if 0 - struct xenbus_device *xdev; - struct xenbus_driver *drv = NULL; - int i = 0; - int length = 0; - char *basepath_end; - char *frontend_id; - - DPRINTK(""); - - if (dev == NULL) - return -ENODEV; - - xdev = to_xenbus_device(dev); - if (xdev == NULL) - return -ENODEV; - - if (dev->driver) - drv = to_xenbus_driver(dev->driver); - - /* stuff we want to pass to /sbin/hotplug */ - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "XENBUS_TYPE=%s", xdev->devicetype); - - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "XENBUS_PATH=%s", xdev->nodename); - - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "XENBUS_BASE_PATH=%s", xdev->nodename); - - basepath_end = strrchr(envp[i - 1], '/'); - length -= strlen(basepath_end); - *basepath_end = '\0'; - basepath_end = strrchr(envp[i - 1], '/'); - length -= strlen(basepath_end); - *basepath_end = '\0'; - - basepath_end++; - frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL); - strcpy(frontend_id, basepath_end); - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "XENBUS_FRONTEND_ID=%s", frontend_id); - kfree(frontend_id); - - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - - if (drv && drv->hotplug) - return drv->hotplug(xdev, envp, num_envp, buffer, buffer_size); - -#endif - return 0; -} -#endif - -#if 0 -static int xenbus_probe_backend(const char *type, const char *domid, int unit); -static struct xen_bus_type xenbus_backend = { - .root = "backend", - .levels = 3, /* backend/type/<frontend>/<id> */ - .get_bus_id = backend_bus_id, - .probe = xenbus_probe_backend, - /* at init time */ - .bus = &xenbus_device_backend_list, -#if 0 - .bus = { - .name = "xen-backend", - .match = xenbus_match, - .hotplug = xenbus_hotplug_backend, - }, - .dev = { - .bus_id = "xen-backend", - }, -#endif -}; -#endif - -static void otherend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - - struct xenbus_device *dev = (struct xenbus_device *)watch; - struct xenbus_driver *drv = dev->driver; - XenbusState state; - - /* Protect us against watches firing on old details when the otherend - details change, say immediately after a resume. */ - if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH], - strlen(dev->otherend))) { - DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]); - return; - } - - state = xenbus_read_driver_state(dev->otherend); - - DPRINTK("state is %d, %s, %s", state, dev->otherend_watch.node, - vec[XS_WATCH_PATH]); - - /* - * Ignore xenbus transitions during shutdown. This prevents us doing - * work that can fail e.g., when the rootfs is gone. - */ -#if 0 - if (system_state > SYSTEM_RUNNING) { - struct xen_bus_type *bus = bus; - bus = container_of(dev->dev.bus, struct xen_bus_type, bus); - /* If we're frontend, drive the state machine to Closed. */ - /* This should cause the backend to release our resources. */ - if ((bus == &xenbus_frontend) && (state == XenbusStateClosing)) - xenbus_frontend_closed(dev); - return; - } -#endif - if (drv->otherend_changed) - drv->otherend_changed(dev, state); - -} - - -static int talk_to_otherend(struct xenbus_device *dev) -{ - struct xenbus_driver *drv; - - drv = dev->driver; - - free_otherend_watch(dev); - free_otherend_details(dev); - - return drv->read_otherend_details(dev); -} - -static int watch_otherend(struct xenbus_device *dev) -{ - return xenbus_watch_path2(dev, dev->otherend, "state", - &dev->otherend_watch, otherend_changed); -} - -static int -xenbus_dev_probe(struct xenbus_device *dev) -{ - struct xenbus_driver *drv = dev->driver; - const struct xenbus_device_id *id; - int err; - - DPRINTK(""); - - if (!drv->probe) { - err = -ENODEV; - goto fail; - } - - id = match_device(drv->ids, dev); - if (!id) { - err = -ENODEV; - goto fail; - } - - err = talk_to_otherend(dev); - if (err) { - log(LOG_WARNING, - "xenbus_probe: talk_to_otherend on %s failed.\n", - dev->nodename); - return err; - } - - err = drv->probe(dev, id); - if (err) - goto fail; - - err = watch_otherend(dev); - if (err) { - log(LOG_WARNING, - "xenbus_probe: watch_otherend on %s failed.\n", - dev->nodename); - return err; - } - - return 0; - fail: - xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); - xenbus_switch_state(dev, XenbusStateClosed); - return -ENODEV; -} - -static void xenbus_dev_free(struct xenbus_device *xendev) -{ - LIST_REMOVE(xendev, list); - kfree(xendev); -} - -int -xenbus_remove_device(struct xenbus_device *dev) -{ - struct xenbus_driver *drv = dev->driver; - - DPRINTK(""); - - free_otherend_watch(dev); - free_otherend_details(dev); - - if (drv->remove) - drv->remove(dev); - - xenbus_switch_state(dev, XenbusStateClosed); - - if (drv->cleanup_device) - return drv->cleanup_device(dev); - - xenbus_dev_free(dev); - - return 0; -} - -#if 0 -static int -xenbus_dev_remove(device_t _dev) -{ - return xenbus_remove_device(to_xenbus_device(_dev)); -} -#endif - -int xenbus_register_driver_common(struct xenbus_driver *drv, - struct xen_bus_type *bus) -{ - struct xenbus_device *xdev; - -#if 0 - int ret; - /* this all happens in the driver itself - * doing this here simple serves to obfuscate - */ - - drv->driver.name = drv->name; - drv->driver.bus = &bus->bus; - drv->driver.owner = drv->owner; - drv->driver.probe = xenbus_dev_probe; - drv->driver.remove = xenbus_dev_remove; - - return ret; -#endif - sx_xlock(&xenwatch_mutex); - LIST_INSERT_HEAD(&xendrv_list, drv, list); - sx_xunlock(&xenwatch_mutex); - LIST_FOREACH(xdev, bus->bus, list) { - if (match_device(drv->ids, xdev)) { - xdev->driver = drv; - xenbus_dev_probe(xdev); - } - } - return 0; -} - -int xenbus_register_frontend(struct xenbus_driver *drv) -{ - drv->read_otherend_details = read_backend_details; - - return xenbus_register_driver_common(drv, &xenbus_frontend); -} -EXPORT_SYMBOL(xenbus_register_frontend); - - -void xenbus_unregister_driver(struct xenbus_driver *drv) -{ -#if 0 - driver_unregister(&drv->driver); -#endif -} -EXPORT_SYMBOL(xenbus_unregister_driver); - -struct xb_find_info -{ - struct xenbus_device *dev; - const char *nodename; -}; - -static struct xenbus_device * -xenbus_device_find(const char *nodename, struct xendev_list_head *bus) -{ - struct xenbus_device *xdev; - LIST_FOREACH(xdev, bus, list) { - if (streq(xdev->nodename, nodename)) { - return xdev; -#if 0 - get_device(dev); -#endif - } - } - return NULL; -} -#if 0 -static int cleanup_dev(device_t dev, void *data) -{ - struct xenbus_device *xendev = device_get_softc(dev); - struct xb_find_info *info = data; - int len = strlen(info->nodename); - - DPRINTK("%s", info->nodename); - - if (!strncmp(xendev->nodename, info->nodename, len)) { - info->dev = xendev; -#if 0 - get_device(dev); -#endif - return 1; - } - return 0; -} - -#endif -static void xenbus_cleanup_devices(const char *path, struct xendev_list_head * bus) -{ -#if 0 - struct xb_find_info info = { .nodename = path }; - - do { - info.dev = NULL; - bus_for_each_dev(bus, NULL, &info, cleanup_dev); - if (info.dev) { - device_unregister(&info.dev->dev); - put_device(&info.dev->dev); - } - } while (info.dev); -#endif -} - -#if 0 -void xenbus_dev_release(device_t dev) -{ - /* - * nothing to do softc gets freed with the device - */ - -} -#endif -/* Simplified asprintf. */ -char *kasprintf(const char *fmt, ...) -{ - va_list ap; - unsigned int len; - char *p, dummy[1]; - - va_start(ap, fmt); - /* FIXME: vsnprintf has a bug, NULL should work */ - len = vsnprintf(dummy, 0, fmt, ap); - va_end(ap); - - p = kmalloc(len + 1, GFP_KERNEL); - if (!p) - return NULL; - va_start(ap, fmt); - vsprintf(p, fmt, ap); - va_end(ap); - return p; -} - -#if 0 -static ssize_t xendev_show_nodename(struct device *dev, char *buf) -{ - return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); -} -DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); - -static ssize_t xendev_show_devtype(struct device *dev, char *buf) -{ - return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); -} -DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); -#endif - -int xenbus_probe_node(struct xen_bus_type *bus, const char *type, - const char *nodename) -{ -#define CHECK_FAIL \ - do { \ - if (err) \ - goto fail; \ - } while (0) \ - - - - int err; - struct xenbus_device *xendev; - struct xenbus_driver *xdrv; - size_t stringlen; - char *tmpstring; - - XenbusState state = xenbus_read_driver_state(nodename); - - if (bus->error) - return (bus->error); - - - if (state != XenbusStateInitialising) { - /* Device is not new, so ignore it. This can happen if a - device is going away after switching to Closed. */ - return 0; - } - - stringlen = strlen(nodename) + 1 + strlen(type) + 1; - xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL); - if (!xendev) - return -ENOMEM; - memset(xendev, 0, sizeof(*xendev)); - xendev->state = XenbusStateInitialising; - - /* Copy the strings into the extra space. */ - - tmpstring = (char *)(xendev + 1); - strcpy(tmpstring, nodename); - xendev->nodename = tmpstring; - - tmpstring += strlen(tmpstring) + 1; - strcpy(tmpstring, type); - xendev->devicetype = tmpstring; - /* - * equivalent to device registration - * events - */ - LIST_INSERT_HEAD(bus->bus, xendev, list); - LIST_FOREACH(xdrv, &xendrv_list, list) { - if (match_device(xdrv->ids, xendev)) { - xendev->driver = xdrv; - if (!xenbus_dev_probe(xendev)) - break; - } - } - -#if 0 - xendev->dev.parent = &bus->dev; - xendev->dev.bus = &bus->bus; - xendev->dev.release = xenbus_dev_release; - - err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename); - CHECK_FAIL; - - /* Register with generic device framework. */ - err = device_register(&xendev->dev); - CHECK_FAIL; - - device_create_file(&xendev->dev, &dev_attr_nodename); - device_create_file(&xendev->dev, &dev_attr_devtype); -#endif - return 0; - -#undef CHECK_FAIL -#if 0 - fail: - xenbus_dev_free(xendev); -#endif - return err; -} - -/* device/<typename>/<name> */ -static int xenbus_probe_frontend(const char *type, const char *name) -{ - char *nodename; - int err; - - nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name); - if (!nodename) - return -ENOMEM; - - DPRINTK("%s", nodename); - - err = xenbus_probe_node(&xenbus_frontend, type, nodename); - kfree(nodename); - return err; -} - -static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) -{ - int err = 0; - char **dir; - unsigned int dir_n = 0; - int i; - - dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n); - if (IS_ERR(dir)) - return PTR_ERR(dir); - - for (i = 0; i < dir_n; i++) { - err = bus->probe(type, dir[i]); - if (err) - break; - } - kfree(dir); - return err; -} - -int xenbus_probe_devices(struct xen_bus_type *bus) -{ - int err = 0; - char **dir; - unsigned int i, dir_n; - - dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n); - if (IS_ERR(dir)) - return PTR_ERR(dir); - - for (i = 0; i < dir_n; i++) { - err = xenbus_probe_device_type(bus, dir[i]); - if (err) - break; - } - kfree(dir); - - return err; -} - -static unsigned int char_count(const char *str, char c) -{ - unsigned int i, ret = 0; - - for (i = 0; str[i]; i++) - if (str[i] == c) - ret++; - return ret; -} - -static int strsep_len(const char *str, char c, unsigned int len) -{ - unsigned int i; - - for (i = 0; str[i]; i++) - if (str[i] == c) { - if (len == 0) - return i; - len--; - } - return (len == 0) ? i : -ERANGE; -} - -void dev_changed(const char *node, struct xen_bus_type *bus) -{ - int exists, rootlen; - struct xenbus_device *dev; - char type[BUS_ID_SIZE]; - const char *p; - char *root; - - DPRINTK(""); - if (char_count(node, '/') < 2) - return; - - exists = xenbus_exists(XBT_NIL, node, ""); - if (!exists) { - xenbus_cleanup_devices(node, bus->bus); - return; - } - - /* backend/<type>/... or device/<type>/... */ - p = strchr(node, '/') + 1; - snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p); - type[BUS_ID_SIZE-1] = '\0'; - - rootlen = strsep_len(node, '/', bus->levels); - if (rootlen < 0) - return; - root = kasprintf("%.*s", rootlen, node); - if (!root) - return; - - dev = xenbus_device_find(root, bus->bus); - if (!dev) - xenbus_probe_node(bus, type, root); -#if 0 - else - put_device(&dev->dev); -#endif - kfree(root); -} - -static void frontend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - DPRINTK(""); - - dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); -} - -/* We watch for devices appearing and vanishing. */ -static struct xenbus_watch fe_watch = { - .node = "device", - .callback = frontend_changed, -}; - -#ifdef notyet - -static int suspend_dev(device_t dev, void *data) -{ - int err = 0; - struct xenbus_driver *drv; - struct xenbus_device *xdev; - - DPRINTK(""); - - xdev = device_get_softc(dev); - - drv = xdev->driver; - - if (device_get_driver(dev) == NULL) - return 0; - - if (drv->suspend) - err = drv->suspend(xdev); -#if 0 - /* bus_id ? */ - if (err) - log(LOG_WARNING, "xenbus: suspend %s failed: %i\n", - dev->bus_id, err); -#endif - return 0; -} - - - -static int resume_dev(device_t dev, void *data) -{ - int err; - struct xenbus_driver *drv; - struct xenbus_device *xdev; - - DPRINTK(""); - - if (device_get_driver(dev) == NULL) - return 0; - xdev = device_get_softc(dev); - drv = xdev->driver; - - err = talk_to_otherend(xdev); -#if 0 - if (err) { - log(LOG_WARNING, - "xenbus: resume (talk_to_otherend) %s failed: %i\n", - dev->bus_id, err); - return err; - } -#endif - if (drv->resume) - err = drv->resume(xdev); - - err = watch_otherend(xdev); -#if 0 - /* bus_id? */ - if (err) - log(LOG_WARNING, - "xenbus: resume %s failed: %i\n", dev->bus_id, err); -#endif - return err; -} - -#endif -void xenbus_suspend(void) -{ - DPRINTK(""); - panic("implement me"); -#if 0 - bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); -#endif - xs_suspend(); -} -EXPORT_SYMBOL(xenbus_suspend); - -void xenbus_resume(void) -{ - xb_init_comms(); - xs_resume(); - panic("implement me"); -#if 0 - bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); -#endif -} -EXPORT_SYMBOL(xenbus_resume); - -#if 0 -static device_t -xenbus_add_child(device_t bus, int order, const char *name, int unit) -{ - device_t child; - - child = device_add_child_ordered(bus, order, name, unit); - - return(child); -} -#endif - -/* A flag to determine if xenstored is 'ready' (i.e. has started) */ -int xenstored_ready = 0; - - -int register_xenstore_notifier(xenstore_event_handler_t func, void *arg, int priority) -{ - int ret = 0; - - if (xenstored_ready > 0) - ret = func(NULL); - else - eventhandler_register(xenstore_chain, "xenstore", func, arg, priority); - - return ret; -} -EXPORT_SYMBOL(register_xenstore_notifier); -#if 0 -void unregister_xenstore_notifier(struct notifier_block *nb) -{ - notifier_chain_unregister(&xenstore_chain, nb); -} -EXPORT_SYMBOL(unregister_xenstore_notifier); -#endif - - - -#ifdef DOM0 -static struct proc_dir_entry *xsd_mfn_intf; -static struct proc_dir_entry *xsd_port_intf; - - -static int xsd_mfn_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - len = sprintf(page, "%ld", xen_start_info->store_mfn); - *eof = 1; - return len; -} - -static int xsd_port_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - - len = sprintf(page, "%d", xen_start_info->store_evtchn); - *eof = 1; - return len; -} - -#endif - -static int dom0 = 0; - -static int -xenbus_probe_sysinit(void *unused) -{ - int err = 0; - - DPRINTK(""); - - LIST_INIT(&xenbus_device_frontend_list); - LIST_INIT(&xenbus_device_backend_list); - LIST_INIT(&xendrv_list); -#if 0 - if (xen_init() < 0) { - DPRINTK("failed"); - return -ENODEV; - } - - - /* Register ourselves with the kernel bus & device subsystems */ - bus_register(&xenbus_frontend.bus); - bus_register(&xenbus_backend.bus); - device_register(&xenbus_frontend.dev); - device_register(&xenbus_backend.dev); -#endif - - /* - ** Domain0 doesn't have a store_evtchn or store_mfn yet. - */ - dom0 = (xen_start_info->store_evtchn == 0); - - -#ifdef DOM0 - if (dom0) { - - unsigned long page; - evtchn_op_t op = { 0 }; - int ret; - - - /* Allocate page. */ - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - /* We don't refcnt properly, so set reserved on page. - * (this allocation is permanent) */ - SetPageReserved(virt_to_page(page)); - - xen_start_info->store_mfn = - pfn_to_mfn(virt_to_phys((void *)page) >> - PAGE_SHIFT); - - /* Next allocate a local port which xenstored can bind to */ - op.cmd = EVTCHNOP_alloc_unbound; - op.u.alloc_unbound.dom = DOMID_SELF; - op.u.alloc_unbound.remote_dom = 0; - - ret = HYPERVISOR_event_channel_op(&op); - BUG_ON(ret); - xen_start_info->store_evtchn = op.u.alloc_unbound.port; - - /* And finally publish the above info in /proc/xen */ - if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400))) - xsd_mfn_intf->read_proc = xsd_mfn_read; - if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400))) - xsd_port_intf->read_proc = xsd_port_read; - } -#endif - /* Initialize the interface to xenstore. */ - err = xs_init(); - if (err) { - log(LOG_WARNING, - "XENBUS: Error initializing xenstore comms: %i\n", err); - return err; - } - - return 0; -} - - -static int -xenbus_probe_sysinit2(void *unused) -{ - if (!dom0) { - xenstored_ready = 1; -#if 0 - xenbus_dev = BUS_ADD_CHILD(parent, 0, "xenbus", 0); - if (xenbus_dev == NULL) - panic("xenbus: could not attach"); - xenbus_backend_dev = BUS_ADD_CHILD(parent, 0, "xb_be", 0); - if (xenbus_backend_dev == NULL) - panic("xenbus: could not attach"); -#endif - BUG_ON((xenstored_ready <= 0)); - - - - /* Enumerate devices in xenstore. */ - xenbus_probe_devices(&xenbus_frontend); - register_xenbus_watch(&fe_watch); - xenbus_backend_probe_and_watch(); - - /* Notify others that xenstore is up */ - EVENTHANDLER_INVOKE(xenstore_event); - } - return (0); -} - - -SYSINIT(xenbus_probe_sysinit, SI_SUB_PSEUDO, SI_ORDER_FIRST, xenbus_probe_sysinit, NULL); -SYSINIT(xenbus_probe_sysinit2, SI_SUB_PSEUDO, SI_ORDER_ANY, - xenbus_probe_sysinit2, NULL); - -#if 0 -static device_method_t xenbus_methods[] = { - /* Device interface */ -#if 0 - DEVMETHOD(device_identify, xenbus_identify), - DEVMETHOD(device_probe, xenbus_probe), - DEVMETHOD(device_attach, xenbus_attach), - - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), -#endif - DEVMETHOD(device_suspend, xenbus_suspend), - DEVMETHOD(device_resume, xenbus_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_add_child, xenbus_add_child), - DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), - DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), -#if 0 - DEVMETHOD(bus_set_resource, bus_generic_set_resource), - DEVMETHOD(bus_get_resource, bus_generic_get_resource), -#endif - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), -#if 0 - DEVMETHOD(bus_delete_resource, bus_generic_delete_resource), -#endif - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - { 0, 0 } -}; - -static char driver_name[] = "xenbus"; -static driver_t xenbus_driver = { - driver_name, - xenbus_methods, - sizeof(struct xenbus_device), -}; -devclass_t xenbus_devclass; - -DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0); - -#endif - - - - - -/* - * Local variables: - * c-file-style: "bsd" - * indent-tabs-mode: t - * c-indent-level: 4 - * c-basic-offset: 8 - * tab-width: 4 - * End: - */ diff --git a/sys/xen/xenbus/xenbus_probe_backend.c b/sys/xen/xenbus/xenbus_probe_backend.c deleted file mode 100644 index 3cb8e67..0000000 --- a/sys/xen/xenbus/xenbus_probe_backend.c +++ /dev/null @@ -1,308 +0,0 @@ -/****************************************************************************** - * Talks to Xen Store to figure out what devices we have (backend half). - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * Copyright (C) 2005 Mike Wray, Hewlett-Packard - * Copyright (C) 2005, 2006 XenSource Ltd - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#if 0 -#define DPRINTK(fmt, args...) \ - printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/time.h> -#include <sys/sema.h> -#include <sys/eventhandler.h> -#include <sys/errno.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/systm.h> -#include <sys/syslog.h> -#include <sys/proc.h> -#include <sys/bus.h> -#include <sys/sx.h> - -#include <machine/xen/xen-os.h> -#include <machine/xen/hypervisor.h> -#include <machine/xen/xenbus.h> -#include <machine/xen/evtchn.h> -#include <machine/stdarg.h> - -#include <xen/xenbus/xenbus_comms.h> - -#define BUG_ON PANIC_IF -#define semaphore sema -#define rw_semaphore sema -#define DEFINE_SPINLOCK(lock) struct mtx lock -#define DECLARE_MUTEX(lock) struct sema lock -#define u32 uint32_t -#define list_del(head, ent) TAILQ_REMOVE(head, ent, list) -#define simple_strtoul strtoul -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -#define list_empty TAILQ_EMPTY - -extern struct xendev_list_head xenbus_device_backend_list; -#if 0 -static int xenbus_uevent_backend(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -#endif -static int xenbus_probe_backend(const char *type, const char *domid); - -static int read_frontend_details(struct xenbus_device *xendev) -{ - return read_otherend_details(xendev, "frontend-id", "frontend"); -} - -/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ -static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) -{ - int domid, err; - const char *devid, *type, *frontend; - unsigned int typelen; - - type = strchr(nodename, '/'); - if (!type) - return -EINVAL; - type++; - typelen = strcspn(type, "/"); - if (!typelen || type[typelen] != '/') - return -EINVAL; - - devid = strrchr(nodename, '/') + 1; - - err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, - "frontend", NULL, &frontend, - NULL); - if (err) - return err; - if (strlen(frontend) == 0) - err = -ERANGE; - if (!err && !xenbus_exists(XBT_NIL, frontend, "")) - err = -ENOENT; - kfree(frontend); - - if (err) - return err; - - if (snprintf(bus_id, BUS_ID_SIZE, - "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) - return -ENOSPC; - return 0; -} - -static struct xen_bus_type xenbus_backend = { - .root = "backend", - .levels = 3, /* backend/type/<frontend>/<id> */ - .get_bus_id = backend_bus_id, - .probe = xenbus_probe_backend, - .bus = &xenbus_device_backend_list, - -#if 0 - .error = -ENODEV, - .bus = { - .name = "xen-backend", - .match = xenbus_match, - .probe = xenbus_dev_probe, - .remove = xenbus_dev_remove, -// .shutdown = xenbus_dev_shutdown, - .uevent = xenbus_uevent_backend, - }, - .dev = { - .bus_id = "xen-backend", - }, -#endif -}; - -#if 0 -static int xenbus_uevent_backend(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - struct xenbus_device *xdev; - struct xenbus_driver *drv; - int i = 0; - int length = 0; - - DPRINTK(""); - - if (dev == NULL) - return -ENODEV; - - xdev = to_xenbus_device(dev); - if (xdev == NULL) - return -ENODEV; -2 - /* stuff we want to pass to /sbin/hotplug */ - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_TYPE=%s", xdev->devicetype); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_PATH=%s", xdev->nodename); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_BASE_PATH=%s", xenbus_backend.root); - - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - - if (dev->driver) { - drv = to_xenbus_driver(dev->driver); - if (drv && drv->uevent) - return drv->uevent(xdev, envp, num_envp, buffer, - buffer_size); - } - - return 0; -} -#endif - -int xenbus_register_backend(struct xenbus_driver *drv) -{ - drv->read_otherend_details = read_frontend_details; - - return xenbus_register_driver_common(drv, &xenbus_backend); -} - -/* backend/<typename>/<frontend-uuid>/<name> */ -static int xenbus_probe_backend_unit(const char *dir, - const char *type, - const char *name) -{ - char *nodename; - int err; - - nodename = kasprintf("%s/%s", dir, name); - if (!nodename) - return -ENOMEM; - - DPRINTK("%s\n", nodename); - - err = xenbus_probe_node(&xenbus_backend, type, nodename); - kfree(nodename); - return err; -} - -/* backend/<typename>/<frontend-domid> */ -static int xenbus_probe_backend(const char *type, const char *domid) -{ - char *nodename; - int err = 0; - char **dir; - unsigned int i, dir_n = 0; - - DPRINTK(""); - - nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); - if (!nodename) - return -ENOMEM; - - dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); - if (IS_ERR(dir)) { - kfree(nodename); - return PTR_ERR(dir); - } - - for (i = 0; i < dir_n; i++) { - err = xenbus_probe_backend_unit(nodename, type, dir[i]); - if (err) - break; - } - kfree(dir); - kfree(nodename); - return err; -} - -static void backend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - DPRINTK(""); - - dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); -} - -static struct xenbus_watch be_watch = { - .node = "backend", - .callback = backend_changed, -}; -#if 0 -void xenbus_backend_suspend(int (*fn)(struct device *, void *)) -{ - DPRINTK(""); - if (!xenbus_backend.error) - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); -} - -void xenbus_backend_resume(int (*fn)(struct device *, void *)) -{ - DPRINTK(""); - if (!xenbus_backend.error) - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); -} -#endif -void xenbus_backend_probe_and_watch(void) -{ - xenbus_probe_devices(&xenbus_backend); - register_xenbus_watch(&be_watch); -} - -#if 0 -void xenbus_backend_bus_register(void) -{ - xenbus_backend.error = bus_register(&xenbus_backend.bus); - if (xenbus_backend.error) - log(LOG_WARNING, - "XENBUS: Error registering backend bus: %i\n", - xenbus_backend.error); -} - -void xenbus_backend_device_register(void) -{ - if (xenbus_backend.error) - return; - - xenbus_backend.error = device_register(&xenbus_backend.dev); - if (xenbus_backend.error) { - bus_unregister(&xenbus_backend.bus); - log(LOG_WARNING, - "XENBUS: Error registering backend device: %i\n", - xenbus_backend.error); - } -} -#endif diff --git a/sys/xen/xenbus/xenbus_xs.c b/sys/xen/xenbus/xenbus_xs.c deleted file mode 100644 index 90c32e1..0000000 --- a/sys/xen/xenbus/xenbus_xs.c +++ /dev/null @@ -1,960 +0,0 @@ -/****************************************************************************** - * xenbus_xs.c - * - * This is the kernel equivalent of the "xs" library. We don't need everything - * and we use xenbus_comms for communication. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/unistd.h> -#include <sys/errno.h> -#include <sys/uio.h> -#include <sys/kernel.h> -#include <sys/time.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/sx.h> -#include <sys/sema.h> -#include <sys/syslog.h> -#include <sys/malloc.h> -#include <sys/libkern.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/kthread.h> - -#include <machine/xen/xen-os.h> -#include <machine/xen/hypervisor.h> -#include <machine/xen/xenbus.h> -#include <machine/stdarg.h> - -#include <xen/xenbus/xenbus_comms.h> -static int xs_process_msg(enum xsd_sockmsg_type *type); - -#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK) -#define BUG_ON PANIC_IF -#define DEFINE_SPINLOCK(lock) struct mtx lock -#define u32 uint32_t -#define list_del(head, ent) TAILQ_REMOVE(head, ent, list) -#define simple_strtoul strtoul -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -#define list_empty TAILQ_EMPTY - -#define streq(a, b) (strcmp((a), (b)) == 0) -int xenwatch_running = 0; -int xenbus_running = 0; - -struct kvec { - const void *iov_base; - size_t iov_len; -}; - -struct xs_stored_msg { - TAILQ_ENTRY(xs_stored_msg) list; - - struct xsd_sockmsg hdr; - - union { - /* Queued replies. */ - struct { - char *body; - } reply; - - /* Queued watch events. */ - struct { - struct xenbus_watch *handle; - char **vec; - unsigned int vec_size; - } watch; - } u; -}; - -struct xs_handle { - /* A list of replies. Currently only one will ever be outstanding. */ - TAILQ_HEAD(xs_handle_list, xs_stored_msg) reply_list; - struct mtx reply_lock; - int reply_waitq; - - /* One request at a time. */ - struct sx request_mutex; - - /* Protect transactions against save/restore. */ - struct sx suspend_mutex; -}; - -static struct xs_handle xs_state; - -/* List of registered watches, and a lock to protect it. */ -static LIST_HEAD(watch_list_head, xenbus_watch) watches; -static DEFINE_SPINLOCK(watches_lock); -/* List of pending watch callback events, and a lock to protect it. */ -static TAILQ_HEAD(event_list_head, xs_stored_msg) watch_events; -static DEFINE_SPINLOCK(watch_events_lock); -/* - * Details of the xenwatch callback kernel thread. The thread waits on the - * watch_events_waitq for work to do (queued on watch_events list). When it - * wakes up it acquires the xenwatch_mutex before reading the list and - * carrying out work. - */ -static pid_t xenwatch_pid; -struct sx xenwatch_mutex; -static int watch_events_waitq; - -static int get_error(const char *errorstring) -{ - unsigned int i; - - for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { - if (i == ARRAY_SIZE(xsd_errors) - 1) { - log(LOG_WARNING, "XENBUS xen store gave: unknown error %s", - errorstring); - return EINVAL; - } - } - return xsd_errors[i].errnum; -} - -extern void idle_block(void); -extern void kdb_backtrace(void); - -static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) -{ - struct xs_stored_msg *msg; - char *body; - int i, err; - enum xsd_sockmsg_type itype = *type; - - printf("read_reply "); - if (xenbus_running == 0) { - /* - * Give other domain time to run :-/ - */ - for (i = 0; i < 1000000 && (xenbus_running == 0); i++) { - err = xs_process_msg(type); - - if ((err == 0) - && (*type != XS_WATCH_EVENT)) - break; - - HYPERVISOR_yield(); - } - - if (list_empty(&xs_state.reply_list)) { - printf("giving up and returning an error type=%d\n", - *type); - kdb_backtrace(); - return (ERR_PTR(-1)); - } - - } - - mtx_lock(&xs_state.reply_lock); - if (xenbus_running) { - while (list_empty(&xs_state.reply_list)) { - mtx_unlock(&xs_state.reply_lock); - wait_event_interruptible(&xs_state.reply_waitq, - !list_empty(&xs_state.reply_list)); - - mtx_lock(&xs_state.reply_lock); - } - } - - msg = TAILQ_FIRST(&xs_state.reply_list); - list_del(&xs_state.reply_list, msg); - - mtx_unlock(&xs_state.reply_lock); - - printf("itype=%d htype=%d ", itype, msg->hdr.type); - *type = msg->hdr.type; - if (len) - *len = msg->hdr.len; - body = msg->u.reply.body; - - kfree(msg); - if (len) - printf("len=%d\n", *len); - else - printf("len=NULL\n"); - return body; -} - -#if 0 -/* Emergency write. UNUSED*/ -void xenbus_debug_write(const char *str, unsigned int count) -{ - struct xsd_sockmsg msg = { 0 }; - - msg.type = XS_DEBUG; - msg.len = sizeof("print") + count + 1; - - sx_xlock(&xs_state.request_mutex); - xb_write(&msg, sizeof(msg)); - xb_write("print", sizeof("print")); - xb_write(str, count); - xb_write("", 1); - sx_xunlock(&xs_state.request_mutex); -} - -#endif -void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) -{ - void *ret; - struct xsd_sockmsg req_msg = *msg; - int err; - - if (req_msg.type == XS_TRANSACTION_START) - sx_slock(&xs_state.suspend_mutex); - - sx_xlock(&xs_state.request_mutex); - - err = xb_write(msg, sizeof(*msg) + msg->len); - if (err) { - msg->type = XS_ERROR; - ret = ERR_PTR(err); - } else { - ret = read_reply(&msg->type, &msg->len); - } - - sx_xunlock(&xs_state.request_mutex); - - if ((msg->type == XS_TRANSACTION_END) || - ((req_msg.type == XS_TRANSACTION_START) && - (msg->type == XS_ERROR))) - sx_sunlock(&xs_state.suspend_mutex); - - return ret; -} - -static int xenwatch_inline; - -/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -static void *xs_talkv(struct xenbus_transaction t, - enum xsd_sockmsg_type type, - const struct kvec *iovec, - unsigned int num_vecs, - unsigned int *len) -{ - struct xsd_sockmsg msg; - void *ret = NULL; - unsigned int i; - int err; - - msg.tx_id = t.id; - msg.req_id = 0; - msg.type = type; - msg.len = 0; - for (i = 0; i < num_vecs; i++) - msg.len += iovec[i].iov_len; - - printf("xs_talkv "); - - sx_xlock(&xs_state.request_mutex); - - err = xb_write(&msg, sizeof(msg)); - if (err) { - sx_xunlock(&xs_state.request_mutex); - printf("xs_talkv failed %d\n", err); - return ERR_PTR(err); - } - - for (i = 0; i < num_vecs; i++) { - err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; - if (err) { - sx_xunlock(&xs_state.request_mutex); - printf("xs_talkv failed %d\n", err); - return ERR_PTR(err); - } - } - - ret = read_reply(&msg.type, len); - - sx_xunlock(&xs_state.request_mutex); - - if (IS_ERR(ret)) - return ret; - - if (msg.type == XS_ERROR) { - err = get_error(ret); - kfree(ret); - return ERR_PTR(-err); - } - - if ((xenwatch_running == 0) && (xenwatch_inline == 0)) { - xenwatch_inline = 1; - while (!TAILQ_EMPTY(&watch_events) - && xenwatch_running == 0) { - - struct xs_stored_msg *wmsg = TAILQ_FIRST(&watch_events); - list_del(&watch_events, wmsg); - printf("handling %p ...", wmsg->u.watch.handle->callback); - - wmsg->u.watch.handle->callback( - wmsg->u.watch.handle, - (const char **)wmsg->u.watch.vec, - wmsg->u.watch.vec_size); - printf("... %p done\n", wmsg->u.watch.handle->callback); - kfree(wmsg->u.watch.vec); - kfree(wmsg); - } - xenwatch_inline = 0; - } - BUG_ON(msg.type != type); - - return ret; -} - -/* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xenbus_transaction t, - enum xsd_sockmsg_type type, - const char *string, - unsigned int *len) -{ - struct kvec iovec; - - printf("xs_single %s ", string); - iovec.iov_base = (const void *)string; - iovec.iov_len = strlen(string) + 1; - return xs_talkv(t, type, &iovec, 1, len); -} - -/* Many commands only need an ack, don't care what it says. */ -static int xs_error(char *reply) -{ - if (IS_ERR(reply)) - return PTR_ERR(reply); - kfree(reply); - return 0; -} - -static unsigned int count_strings(const char *strings, unsigned int len) -{ - unsigned int num; - const char *p; - - for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) - num++; - - return num; -} - -/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ -static char *join(const char *dir, const char *name) -{ - char *buffer; - - buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1, - GFP_KERNEL); - if (buffer == NULL) - return ERR_PTR(-ENOMEM); - - strcpy(buffer, dir); - if (!streq(name, "")) { - strcat(buffer, "/"); - strcat(buffer, name); - } - - return buffer; -} - -static char **split(char *strings, unsigned int len, unsigned int *num) -{ - char *p, **ret; - - /* Count the strings. */ - *num = count_strings(strings, len) + 1; - - /* Transfer to one big alloc for easy freeing. */ - ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL); - if (!ret) { - kfree(strings); - return ERR_PTR(-ENOMEM); - } - memcpy(&ret[*num], strings, len); - kfree(strings); - - strings = (char *)&ret[*num]; - for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) - ret[(*num)++] = p; - - ret[*num] = strings + len; - - return ret; -} - -char **xenbus_directory(struct xenbus_transaction t, - const char *dir, const char *node, unsigned int *num) -{ - char *strings, *path; - unsigned int len = 0; - - path = join(dir, node); - if (IS_ERR(path)) - return (char **)path; - - strings = xs_single(t, XS_DIRECTORY, path, &len); - kfree(path); - if (IS_ERR(strings)) - return (char **)strings; - - return split(strings, len, num); -} -EXPORT_SYMBOL(xenbus_directory); - -/* Check if a path exists. Return 1 if it does. */ -int xenbus_exists(struct xenbus_transaction t, - const char *dir, const char *node) -{ - char **d; - int dir_n; - - d = xenbus_directory(t, dir, node, &dir_n); - if (IS_ERR(d)) - return 0; - kfree(d); - return 1; -} -EXPORT_SYMBOL(xenbus_exists); - -/* Get the value of a single file. - * Returns a kmalloced value: call free() on it after use. - * len indicates length in bytes. - */ -void *xenbus_read(struct xenbus_transaction t, - const char *dir, const char *node, unsigned int *len) -{ - char *path; - void *ret; - - path = join(dir, node); - if (IS_ERR(path)) - return (void *)path; - - printf("xs_read "); - ret = xs_single(t, XS_READ, path, len); - kfree(path); - return ret; -} -EXPORT_SYMBOL(xenbus_read); - -/* Write the value of a single file. - * Returns -err on failure. - */ -int xenbus_write(struct xenbus_transaction t, - const char *dir, const char *node, const char *string) -{ - char *path; - struct kvec iovec[2]; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - iovec[0].iov_base = path; - iovec[0].iov_len = strlen(path) + 1; - iovec[1].iov_base = string; - iovec[1].iov_len = strlen(string); - - printf("xenbus_write dir=%s val=%s ", dir, string); - ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); - kfree(path); - return ret; -} -EXPORT_SYMBOL(xenbus_write); - -/* Create a new directory. */ -int xenbus_mkdir(struct xenbus_transaction t, - const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - ret = xs_error(xs_single(t, XS_MKDIR, path, NULL)); - kfree(path); - return ret; -} -EXPORT_SYMBOL(xenbus_mkdir); - -/* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - ret = xs_error(xs_single(t, XS_RM, path, NULL)); - kfree(path); - return ret; -} -EXPORT_SYMBOL(xenbus_rm); - -/* Start a transaction: changes by others will not be seen during this - * transaction, and changes will not be visible to others until end. - */ -int xenbus_transaction_start(struct xenbus_transaction *t) -{ - char *id_str; - - sx_slock(&xs_state.suspend_mutex); - id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); - if (IS_ERR(id_str)) { - sx_sunlock(&xs_state.suspend_mutex); - return PTR_ERR(id_str); - } - - t->id = simple_strtoul(id_str, NULL, 0); - kfree(id_str); - - return 0; -} -EXPORT_SYMBOL(xenbus_transaction_start); - -/* End a transaction. - * If abandon is true, transaction is discarded instead of committed. - */ -int xenbus_transaction_end(struct xenbus_transaction t, int abort) -{ - char abortstr[2]; - int err; - - if (abort) - strcpy(abortstr, "F"); - else - strcpy(abortstr, "T"); - - printf("xenbus_transaction_end "); - err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); - - sx_sunlock(&xs_state.suspend_mutex); - - return err; -} -EXPORT_SYMBOL(xenbus_transaction_end); - -/* Single read and scanf: returns -errno or num scanned. */ -int xenbus_scanf(struct xenbus_transaction t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; - char *val; - - val = xenbus_read(t, dir, node, NULL); - if (IS_ERR(val)) - return PTR_ERR(val); - - va_start(ap, fmt); - ret = vsscanf(val, fmt, ap); - va_end(ap); - kfree(val); - /* Distinctive errno. */ - if (ret == 0) - return -ERANGE; - return ret; -} -EXPORT_SYMBOL(xenbus_scanf); - -/* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; -#define PRINTF_BUFFER_SIZE 4096 - char *printf_buffer; - - printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); - if (printf_buffer == NULL) - return -ENOMEM; - - va_start(ap, fmt); - ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); - va_end(ap); - - BUG_ON(ret > PRINTF_BUFFER_SIZE-1); - ret = xenbus_write(t, dir, node, printf_buffer); - - kfree(printf_buffer); - - return ret; -} -EXPORT_SYMBOL(xenbus_printf); - -/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int xenbus_gather(struct xenbus_transaction t, const char *dir, ...) -{ - va_list ap; - const char *name; - int i, ret = 0; - - for (i = 0; i < 10000; i++) - HYPERVISOR_yield(); - - printf("gather "); - va_start(ap, dir); - while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - char *p; - - p = xenbus_read(t, dir, name, NULL); - if (IS_ERR(p)) { - ret = PTR_ERR(p); - break; - } - printf(" %s ", p); - if (fmt) { - if (sscanf(p, fmt, result) == 0) - ret = -EINVAL; - kfree(p); - } else - *(char **)result = p; - } - va_end(ap); - printf("\n"); - return ret; -} -EXPORT_SYMBOL(xenbus_gather); - -static int xs_watch(const char *path, const char *token) -{ - struct kvec iov[2]; - - iov[0].iov_base = path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = token; - iov[1].iov_len = strlen(token) + 1; - - return xs_error(xs_talkv(XBT_NIL, XS_WATCH, iov, - ARRAY_SIZE(iov), NULL)); -} - -static int xs_unwatch(const char *path, const char *token) -{ - struct kvec iov[2]; - - iov[0].iov_base = path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = token; - iov[1].iov_len = strlen(token) + 1; - - return xs_error(xs_talkv(XBT_NIL, XS_UNWATCH, iov, - ARRAY_SIZE(iov), NULL)); -} - -static struct xenbus_watch *find_watch(const char *token) -{ - struct xenbus_watch *i, *cmp; - - cmp = (void *)simple_strtoul(token, NULL, 16); - - LIST_FOREACH(i, &watches, list) - if (i == cmp) - return i; - - return NULL; -} - -/* Register callback to watch this node. */ -int register_xenbus_watch(struct xenbus_watch *watch) -{ - /* Pointer in ascii is the token. */ - char token[sizeof(watch) * 2 + 1]; - int err; - - sprintf(token, "%lX", (long)watch); - - sx_slock(&xs_state.suspend_mutex); - - mtx_lock(&watches_lock); - BUG_ON(find_watch(token) != NULL); - LIST_INSERT_HEAD(&watches, watch, list); - mtx_unlock(&watches_lock); - - err = xs_watch(watch->node, token); - - /* Ignore errors due to multiple registration. */ - if ((err != 0) && (err != -EEXIST)) { - mtx_lock(&watches_lock); - LIST_REMOVE(watch, list); - mtx_unlock(&watches_lock); - } - - sx_sunlock(&xs_state.suspend_mutex); - - return err; -} -EXPORT_SYMBOL(register_xenbus_watch); - -void unregister_xenbus_watch(struct xenbus_watch *watch) -{ - struct xs_stored_msg *msg, *tmp; - char token[sizeof(watch) * 2 + 1]; - int err; - - sprintf(token, "%lX", (long)watch); - - sx_slock(&xs_state.suspend_mutex); - - mtx_lock(&watches_lock); - BUG_ON(!find_watch(token)); - LIST_REMOVE(watch, list); - mtx_unlock(&watches_lock); - - err = xs_unwatch(watch->node, token); - if (err) - log(LOG_WARNING, "XENBUS Failed to release watch %s: %i\n", - watch->node, err); - - sx_sunlock(&xs_state.suspend_mutex); - - /* Cancel pending watch events. */ - mtx_lock(&watch_events_lock); - TAILQ_FOREACH_SAFE(msg, &watch_events, list, tmp) { - if (msg->u.watch.handle != watch) - continue; - list_del(&watch_events, msg); - kfree(msg->u.watch.vec); - kfree(msg); - } - mtx_unlock(&watch_events_lock); - - /* Flush any currently-executing callback, unless we are it. :-) */ - if (curproc->p_pid != xenwatch_pid) { - sx_xlock(&xenwatch_mutex); - sx_xunlock(&xenwatch_mutex); - } -} -EXPORT_SYMBOL(unregister_xenbus_watch); - -void xs_suspend(void) -{ - sx_xlock(&xs_state.suspend_mutex); - sx_xlock(&xs_state.request_mutex); -} - -void xs_resume(void) -{ - struct xenbus_watch *watch; - char token[sizeof(watch) * 2 + 1]; - - sx_xunlock(&xs_state.request_mutex); - - /* No need for watches_lock: the suspend_mutex is sufficient. */ - LIST_FOREACH(watch, &watches, list) { - sprintf(token, "%lX", (long)watch); - xs_watch(watch->node, token); - } - - sx_xunlock(&xs_state.suspend_mutex); -} - -static void xenwatch_thread(void *unused) -{ - struct xs_stored_msg *msg; - - xenwatch_running = 1; - - DELAY(100000); - while (xenwatch_inline) { - printf("xenwatch inline still running\n"); - DELAY(100000); - } - - - for (;;) { - - while (list_empty(&watch_events)) - tsleep(&watch_events_waitq, - PWAIT | PCATCH, "waitev", hz/10); - - sx_xlock(&xenwatch_mutex); - - mtx_lock(&watch_events_lock); - msg = TAILQ_FIRST(&watch_events); - if (msg) - list_del(&watch_events, msg); - mtx_unlock(&watch_events_lock); - - if (msg != NULL) { - msg->u.watch.handle->callback( - msg->u.watch.handle, - (const char **)msg->u.watch.vec, - msg->u.watch.vec_size); - kfree(msg->u.watch.vec); - kfree(msg); - } - - sx_xunlock(&xenwatch_mutex); - } -} - -static int xs_process_msg(enum xsd_sockmsg_type *type) -{ - struct xs_stored_msg *msg; - char *body; - int err; - - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (msg == NULL) - return -ENOMEM; - - err = xb_read(&msg->hdr, sizeof(msg->hdr)); - if (err) { - kfree(msg); - return err; - } - - body = kmalloc(msg->hdr.len + 1, GFP_KERNEL); - if (body == NULL) { - kfree(msg); - return -ENOMEM; - } - - err = xb_read(body, msg->hdr.len); - if (err) { - kfree(body); - kfree(msg); - return err; - } - body[msg->hdr.len] = '\0'; - - *type = msg->hdr.type; - if (msg->hdr.type == XS_WATCH_EVENT) { - msg->u.watch.vec = split(body, msg->hdr.len, - &msg->u.watch.vec_size); - if (IS_ERR(msg->u.watch.vec)) { - kfree(msg); - return PTR_ERR(msg->u.watch.vec); - } - - mtx_lock(&watches_lock); - msg->u.watch.handle = find_watch( - msg->u.watch.vec[XS_WATCH_TOKEN]); - if (msg->u.watch.handle != NULL) { - mtx_lock(&watch_events_lock); - TAILQ_INSERT_TAIL(&watch_events, msg, list); - wakeup(&watch_events_waitq); - mtx_unlock(&watch_events_lock); - } else { - kfree(msg->u.watch.vec); - kfree(msg); - } - mtx_unlock(&watches_lock); - } else { - printf("event=%d ", *type); - msg->u.reply.body = body; - mtx_lock(&xs_state.reply_lock); - TAILQ_INSERT_TAIL(&xs_state.reply_list, msg, list); - wakeup(&xs_state.reply_waitq); - mtx_unlock(&xs_state.reply_lock); - } - if (*type == XS_WATCH_EVENT) - printf("\n"); - - return 0; -} - -static void xenbus_thread(void *unused) -{ - int err; - enum xsd_sockmsg_type type; - - DELAY(10000); - xenbus_running = 1; - tsleep(&lbolt, 0, "xenbus", hz/10); - - for (;;) { - err = xs_process_msg(&type); - if (err) - printf("XENBUS error %d while reading " - "message\n", err); - - } -} - -int xs_init(void) -{ - int err; - struct proc *p; - - TAILQ_INIT(&xs_state.reply_list); - TAILQ_INIT(&watch_events); - sx_init(&xenwatch_mutex, "xenwatch"); - - - mtx_init(&xs_state.reply_lock, "state reply", NULL, MTX_DEF); - sx_init(&xs_state.request_mutex, "xenstore request"); - sx_init(&xs_state.suspend_mutex, "xenstore suspend"); - - -#if 0 - mtx_init(&xs_state.suspend_mutex, "xenstore suspend", NULL, MTX_DEF); - sema_init(&xs_state.request_mutex, 1, "xenstore request"); - sema_init(&xenwatch_mutex, 1, "xenwatch"); -#endif - mtx_init(&watches_lock, "watches", NULL, MTX_DEF); - mtx_init(&watch_events_lock, "watch events", NULL, MTX_DEF); - - /* Initialize the shared memory rings to talk to xenstored */ - err = xb_init_comms(); - if (err) - return err; - - err = kthread_create(xenwatch_thread, NULL, &p, - RFHIGHPID, 0, "xenwatch"); - if (err) - return err; - xenwatch_pid = p->p_pid; - - err = kthread_create(xenbus_thread, NULL, NULL, - RFHIGHPID, 0, "xenbus"); - - return err; -} - - -/* - * Local variables: - * c-file-style: "bsd" - * indent-tabs-mode: t - * c-indent-level: 4 - * c-basic-offset: 8 - * tab-width: 4 - * End: - */ |