843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is the kernel equivalent of the "xs" library. We don't need everything
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and we use xenbus_comms for communication.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (C) 2005 Rusty Russell, IBM Corporation
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This file may be distributed separately from the Linux kernel, or
843e19887f64dde75055cf8842fc4db2171eff45johnlev * incorporated into other software packages, subject to the following license:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Permission is hereby granted, free of charge, to any person obtaining a copy
843e19887f64dde75055cf8842fc4db2171eff45johnlev * of this source file (the "Software"), to deal in the Software without
843e19887f64dde75055cf8842fc4db2171eff45johnlev * restriction, including without limitation the rights to use, copy, modify,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * merge, publish, distribute, sublicense, and/or sell copies of the Software,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and to permit persons to whom the Software is furnished to do so, subject to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the following conditions:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The above copyright notice and this permission notice shall be included in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * all copies or substantial portions of the Software.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
843e19887f64dde75055cf8842fc4db2171eff45johnlev * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IN THE SOFTWARE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * NOTE: To future maintainers of the Solaris version of this file:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * I found the Linux version of this code to be very disgusting in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * overloading pointers and error codes into void * return values.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The main difference you will find is that all such usage is changed
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to pass pointers to void* to be filled in with return values and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the functions return error codes.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Queued replies. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Queued watch events. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* A list of replies. Currently only one will ever be outstanding. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* One request at a time. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Protect transactions against save/restore. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * List of clients wanting a xenstore up notification, and a lock to protect it
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* List of registered watches, and a lock to protect it. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* List of pending watch callback events, and a lock to protect it. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Details of the xenwatch callback kernel thread. The thread waits on the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * watch_events_cv for work to do (queued on watch_events list). When it
843e19887f64dde75055cf8842fc4db2171eff45johnlev * wakes up it acquires the xenwatch_mutex before reading the list and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * carrying out work.
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int process_msg(void);
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == (sizeof (xsd_errors) / sizeof (xsd_errors[0])) - 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev "XENBUS xen store gave: unknown error %s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Read a synchronous reply from xenstore. Since we can return early before
843e19887f64dde75055cf8842fc4db2171eff45johnlev * reading a relevant reply, we discard any messages not matching the request
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ID. Caller must free returned message on success.
843e19887f64dde75055cf8842fc4db2171eff45johnlevread_reply(struct xsd_sockmsg *req_hdr, struct xs_stored_msg **reply)
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else { /* polled mode needed for early probes */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Emergency write. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_debug_write(const char *str, unsigned int count)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is pretty unpleasant. First off, there's the horrible logic around
843e19887f64dde75055cf8842fc4db2171eff45johnlev * suspend_lock and transactions. Also, we can be interrupted either before we
843e19887f64dde75055cf8842fc4db2171eff45johnlev * write a message, or before we receive a reply. A client that wants to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * survive this can't know which case happened. Luckily all clients don't care
843e19887f64dde75055cf8842fc4db2171eff45johnlev * about signals currently, and the alternative (a hard wait on a userspace
843e19887f64dde75055cf8842fc4db2171eff45johnlev * daemon) isn't exactly preferable. Caller must free 'reply' on success.
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **reply)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Send message to xs, return errcode, rval filled in with pointer
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to kmem_alloc'ed reply.
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int num_vecs,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int *len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < num_vecs; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < num_vecs; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Simplified version of xs_talkv: single message. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int *len)
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic unsigned int
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Return the path to dir with /name appended. Buffer must be kmem_free()'ed */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlev buffer = kmem_alloc(strlen(dir) + slashlen + strlen(name) + 1,
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char **
843e19887f64dde75055cf8842fc4db2171eff45johnlevsplit(char *strings, unsigned int len, unsigned int *num)
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Count the strings. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Transfer to one big alloc for easy freeing. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = kmem_alloc(*num * sizeof (char *) + (len - 1), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (p = strings, *num = 0; p < strings + (len - 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, unsigned int *num)
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(t, XS_DIRECTORY, path, (void **)&strings, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* sigh, we lose error code info here */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/* Check if a path exists. */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_exists(const char *dir, const char *node)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (xenbus_read(XBT_NULL, dir, node, &p, &n) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/* Check if a directory path exists. */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_exists_dir(const char *dir, const char *node)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz d = xenbus_directory(XBT_NULL, dir, node, &dir_n);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Get the value of a single file.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Returns a kmem_alloced value in retp: call kmem_free() on it after use.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * len indicates length in bytes.
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, void **retp, unsigned int *len)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_read_str(const char *dir, const char *node, char **retp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Since we access the xenbus value immediatly we can't be
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * part of a transaction.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if ((err = xenbus_read(XBT_NULL, dir, node, (void **)&str, &n)) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Why bother with this? Because xenbus is truly annoying in the
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * fact that when it returns a string, it doesn't guarantee that
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * the memory that holds the string is of size strlen() + 1.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * This forces callers to keep track of the size of the memory
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * containing the string. Ugh. We'll work around this by
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * re-allocate strings to always be of size strlen() + 1.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Write the value of a single file.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Returns err on failure.
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *string)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Create a new directory. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_mkdir(xenbus_transaction_t t, const char *dir, const char *node)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Destroy a file or directory (directories must be empty). */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_rm(xenbus_transaction_t t, const char *dir, const char *node)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Start a transaction: changes by others will not be seen during this
843e19887f64dde75055cf8842fc4db2171eff45johnlev * transaction, and changes will not be visible to others until end.
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(XBT_NULL, XS_TRANSACTION_START, "", &id_str, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * End a transaction.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If abandon is true, transaction is discarded instead of committed.
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_transaction_end(xenbus_transaction_t t, int abort)
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Single read and scanf: returns errno or 0. This can only handle a single
843e19887f64dde75055cf8842fc4db2171eff45johnlev * conversion specifier.
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* SCANFLIKE4 */
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *fmt, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xenbus_read(t, dir, node, (void **)&val, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Single printf and write: returns errno or 0. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* PRINTFLIKE4 */
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *fmt, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_gather(xenbus_transaction_t t, const char *dir, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev *(char **)result = p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xs_talkv(XBT_NULL, XS_WATCH, iov, 2, NULL, NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xs_talkv(XBT_NULL, XS_UNWATCH, iov, 2, NULL, NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct xenbus_watch *
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_strtoul(token, NULL, 16, (unsigned long *)&cmp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = list_head(&watches); i != NULL; i = list_next(&watches, i))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (i);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Register a xenstore state notify callback */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbn = kmem_alloc(sizeof (struct xenbus_notify), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Make sure not already on the list
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (; xnp != NULL; xnp = list_next(¬ify_list, xnp)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Notify clients of xenstore state
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (; xnp != NULL; xnp = list_next(¬ify_list, xnp)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks,
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Register callback to watch this node. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Pointer in ascii is the token. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * May be re-registering a watch if xenstore daemon was restarted
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV3(xenbus__register__watch, const char *, watch->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, watch->callback, struct xenbus_watch *, watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Ignore errors due to multiple registration. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev len += strlen(msg->un.watch.vec[i]) + 1 + sizeof (char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV3(xenbus__unregister__watch, const char *, watch->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, watch->callback, struct xenbus_watch *, watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "XENBUS Failed to release watch %s: %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Cancel pending watch events. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *tmp = list_next(&watch_events, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Flush any currently-executing callback, unless we are it. :-) */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* No need for watches_lock: the suspend_lock is sufficient. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev watch->callback(watch, (const char **)msg->un.watch.vec,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev if ((msg->un.watch.handle = find_watch(token)) != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon * We have to wait for interrupts to be ready, so we don't clash
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon * with the polled-IO code in read_reply().
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When setting up xenbus, dom0 and domU have to take different paths, which
843e19887f64dde75055cf8842fc4db2171eff45johnlev * makes this code a little confusing. For dom0:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_early_init - mutex init only
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_dom0_init - called on xenbus dev attach: set up our xenstore page and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * event channel; start xenbus threads for responding to interrupts.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * And for domU:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_early_init - mutex init; set up our xenstore page and event channel
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_domu_init - installation of IRQ handler; start xenbus threads.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We need an early init on domU so we can use xenbus in polled mode to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * discover devices, VCPUs etc.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * On resume, we use xb_init() and xb_setup_intr() to restore xenbus to a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * working state.
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&xs_state.reply_list, sizeof (struct xs_stored_msg),
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&watch_events, sizeof (struct xs_stored_msg),
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(¬ify_list, sizeof (struct xenbus_notify),
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xs_state.reply_lock, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xs_state.request_mutex, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(¬ify_list_lock, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_init(&xs_state.suspend_lock, NULL, RW_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cv_init(&xs_state.reply_cv, NULL, CV_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) thread_create(NULL, 0, xenwatch_thread, NULL, 0, &p0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) thread_create(NULL, 0, xenbus_thread, NULL, 0, &p0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add interrupt handler for xenbus now, must wait till after
843e19887f64dde75055cf8842fc4db2171eff45johnlev * psm module is loaded. All use of xenbus is in polled mode
843e19887f64dde75055cf8842fc4db2171eff45johnlev * until xs_init is called since it is what kicks off the xs
843e19887f64dde75055cf8842fc4db2171eff45johnlev * server threads.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The xenbus driver might be re-attaching.