[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v2 04/10] plat/xen: Add support for communication with Xenstore daemon
Hi Yuri, Please see my comments inline. On 08/29/2018 03:38 PM, Yuri Volchkov wrote: > Hey Costin. > > I found just a couple of important things. But both of them are really > tiny. > > The comments are inline > > -Yuri. > > Costin Lupu <costin.lupu@xxxxxxxxx> writes: > >> Add support for communication with Xenstore daemon via the shared >> page. In Unikraft, the incoming messages are processed by the >> Xenstore thread. >> >> Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> >> --- >> plat/xen/Makefile.uk | 1 + >> plat/xen/xenbus/xenbus.c | 8 + >> plat/xen/xenbus/xs_comms.c | 535 >> +++++++++++++++++++++++++++++++++++++++++++++ >> plat/xen/xenbus/xs_comms.h | 64 ++++++ >> 4 files changed, 608 insertions(+) >> create mode 100644 plat/xen/xenbus/xs_comms.c >> create mode 100644 plat/xen/xenbus/xs_comms.h >> >> diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk >> index b8c70e1..2703a54 100644 >> --- a/plat/xen/Makefile.uk >> +++ b/plat/xen/Makefile.uk >> @@ -79,4 +79,5 @@ LIBXENBUS_ASINCLUDES-y += >> $(LIBXENPLAT_ASINCLUDES-y) >> LIBXENBUS_CFLAGS-y += $(LIBXENPLAT_CFLAGS-y) >> LIBXENBUS_CINCLUDES-y += $(LIBXENPLAT_CINCLUDES-y) >> LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xenbus.c >> +LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xs_comms.c >> endif >> diff --git a/plat/xen/xenbus/xenbus.c b/plat/xen/xenbus/xenbus.c >> index 1bc57c3..a20546b 100644 >> --- a/plat/xen/xenbus/xenbus.c >> +++ b/plat/xen/xenbus/xenbus.c >> @@ -43,6 +43,7 @@ >> #include <uk/errptr.h> >> #include <uk/assert.h> >> #include <xenbus/xenbus.h> >> +#include "xs_comms.h" >> >> static struct xenbus_handler xbh; >> >> @@ -86,6 +87,13 @@ static int xenbus_init(struct uk_alloc *a) >> >> xbh.a = a; >> >> + ret = xs_comms_init(); >> + if (ret) { >> + uk_printd(DLVL_ERR, >> + "Error initializing Xenstore communication."); >> + return ret; >> + } >> + >> UK_TAILQ_FOREACH_SAFE(drv, &xbh.drv_list, next, drv_next) { >> if (drv->init) { >> ret = drv->init(a); >> diff --git a/plat/xen/xenbus/xs_comms.c b/plat/xen/xenbus/xs_comms.c >> new file mode 100644 >> index 0000000..df3739d >> --- /dev/null >> +++ b/plat/xen/xenbus/xs_comms.c >> @@ -0,0 +1,535 @@ >> +/* SPDX-License-Identifier: BSD-3-Clause */ >> +/* >> + * Authors: Steven Smith (sos22@xxxxxxxxx) >> + * Grzegorz Milos (gm281@xxxxxxxxx) >> + * John D. Ramsdell >> + * Costin Lupu <costin.lupu@xxxxxxxxx> >> + * >> + * Copyright (c) 2006, Cambridge University >> + * 2018, NEC Europe Ltd., NEC Corporation. All rights >> reserved. >> + * >> + * Redistribution and use in source and binary forms, with or without >> + * modification, are permitted provided that the following conditions >> + * are met: >> + * >> + * 1. Redistributions of source code must retain the above copyright >> + * notice, this list of conditions and the following disclaimer. >> + * 2. Redistributions in binary form must reproduce the above copyright >> + * notice, this list of conditions and the following disclaimer in the >> + * documentation and/or other materials provided with the distribution. >> + * 3. Neither the name of the copyright holder nor the names of its >> + * contributors may be used to endorse or promote products derived from >> + * this software without specific prior written permission. >> + * >> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS >> IS" >> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >> PURPOSE >> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE >> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >> THE >> + * POSSIBILITY OF SUCH DAMAGE. >> + * >> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. >> + */ >> +/* >> + * Communication with Xenstore >> + * Ported from Mini-OS xenbus.c >> + */ >> + >> +#include <string.h> >> +#include <uk/errptr.h> >> +#include <uk/bitmap.h> >> +#include <uk/wait.h> >> +#include <uk/arch/spinlock.h> >> +#include <common/events.h> >> +#include <xen-x86/mm.h> >> +#include <xen-x86/setup.h> >> +#include "xs_comms.h" >> + >> + >> +/* >> + * Xenstore handler structure >> + */ >> +struct xs_handler { >> + /**< Communication: event channel */ >> + evtchn_port_t evtchn; >> + /**< Communication: shared memory */ >> + struct xenstore_domain_interface *buf; >> + /**< Thread processing incoming xs replies */ >> + struct uk_thread *thread; >> + /**< Waiting queue for notifying incoming xs replies */ >> + struct uk_waitq waitq; >> +}; >> + >> +static struct xs_handler xsh = { >> + .waitq = __WAIT_QUEUE_INITIALIZER(xsh.waitq), >> +}; >> + >> +static int xs_avail_space_for_read(unsigned int req_size) >> +{ >> + return (xsh.buf->rsp_prod - xsh.buf->rsp_cons >= req_size); >> +} >> + >> +static int xs_avail_space_for_write(unsigned int req_size) >> +{ >> + return (xsh.buf->req_prod - xsh.buf->req_cons + >> + req_size <= XENSTORE_RING_SIZE); >> +} >> + >> +/* >> + * In-flight request structure. >> + */ >> +struct xs_request { >> + /**< Waiting queue for incoming reply notification */ >> + struct uk_waitq waitq; >> + /**< Request header */ >> + struct xsd_sockmsg hdr; >> + /**< Received reply */ >> + struct { >> + /**< Reply string + size */ >> + struct xs_iovec iovec; >> + /**< Error number */ >> + int errornum; >> + /**< Non-zero for incoming replies */ >> + int recvd; >> + } reply; >> +}; >> + >> +/* >> + * Pool of in-flight requests. >> + * Request IDs are reused, hence the limited set of entries. >> + * >> + * TODO sequential IDs >> + */ >> +struct xs_request_pool { >> + /**< Number of live requests */ >> + __u32 num_live; >> + /**< Lock */ >> + spinlock_t lock; >> + /**< Waiting queue for 'not-full' notifications */ >> + struct uk_waitq waitq; >> + >> + /* Map size is power of 2 */ >> +#define REQID_MAP_SHIFT 5 >> +#define REQID_MAP_SIZE (1 << REQID_MAP_SHIFT) >> + unsigned long entries_bm[BITS_TO_LONGS(REQID_MAP_SIZE) * sizeof(long)]; >> + /**< Entries */ >> + struct xs_request entries[REQID_MAP_SIZE]; >> +}; >> + >> +static struct xs_request_pool xs_req_pool; >> + >> +static void xs_request_pool_init(struct xs_request_pool *pool) >> +{ >> + struct xs_request *xs_req; >> + >> + pool->num_live = 0; >> + ukarch_spin_lock_init(&pool->lock); >> + uk_waitq_init(&pool->waitq); >> + bitmap_zero(pool->entries_bm, REQID_MAP_SIZE); >> + for (int i = 0; i < REQID_MAP_SIZE; i++) { >> + xs_req = &pool->entries[i]; >> + xs_req->hdr.req_id = i; >> + uk_waitq_init(&xs_req->waitq); >> + } >> +} >> + >> +/* >> + * Allocate an identifier for a Xenstore request. >> + * Blocks if none are available. >> + */ >> +static struct xs_request *xs_request_get(void) >> +{ >> + unsigned long entry_idx; >> + >> + /* wait for an available entry */ >> + while (1) { >> + ukarch_spin_lock(&xs_req_pool.lock); >> + >> + if (xs_req_pool.num_live < REQID_MAP_SIZE) >> + break; >> + >> + ukarch_spin_unlock(&xs_req_pool.lock); >> + >> + uk_waitq_wait_event(&xs_req_pool.waitq, >> + (xs_req_pool.num_live < REQID_MAP_SIZE)); >> + } >> + >> + /* find an available entry */ >> + entry_idx = >> + find_first_zero_bit(xs_req_pool.entries_bm, REQID_MAP_SIZE); >> + >> + set_bit(entry_idx, xs_req_pool.entries_bm); >> + xs_req_pool.num_live++; >> + >> + ukarch_spin_unlock(&xs_req_pool.lock); >> + >> + return &xs_req_pool.entries[entry_idx]; >> +} >> + >> +/* Release a request identifier */ >> +static void xs_request_put(struct xs_request *xs_req) >> +{ >> + __u32 reqid = xs_req->hdr.req_id; >> + >> + ukarch_spin_lock(&xs_req_pool.lock); >> + >> + UK_ASSERT(test_bit(reqid, xs_req_pool.entries_bm) == 1); >> + >> + clear_bit(reqid, xs_req_pool.entries_bm); >> + xs_req_pool.num_live--; >> + >> + if (xs_req_pool.num_live == 0 || >> + xs_req_pool.num_live == REQID_MAP_SIZE - 1) > I understand the second condition, but why we need to wake up waiter if > num_live == 0? The first condition is used for suspending. We should wait until all requests were answered, that's why we're waiting for num_live to get to zero. Maybe it would be better to remove the first condition and add it back when we'll have the suspend/resume functionality ready. > And, in the second condition, you probably meant "REQID_MAP_SIZE - 2", > not "- 1". We want to wake up waiters if all request from the pull _WAS_ > in-flight. All requests are in-flight iff num_live == REQID_MAP_SIZE (which btw I have to rename). > So, if we entered xs_request_put at the point of time, when there was no > free requests in the pull, num_live will be "REQID_MAP_SIZE - 1". After > the decrementing, it becomes "REQID_MAP_SIZE - 2". I'm afraid here it should be REQID_MAP_SIZE - 1, in other words if we have at least on slot free then we can signal that it's "non-full". > > >> + uk_waitq_wake_up(&xs_req_pool.waitq); >> + >> + ukarch_spin_unlock(&xs_req_pool.lock); >> +} >> + >> +/* >> + * Send request to Xenstore. A request is made of multiple iovecs which are >> + * preceded by a single iovec referencing the request header. The iovecs are >> + * seen by Xenstore as if sent atomically. This can block. >> + * >> + * TODO A different thread (e.g. Xenbus thread) should write the messages if >> + * we expect high loads of requests. >> + */ >> +static int xs_msg_write(struct xsd_sockmsg *xsd_req, >> + const struct xs_iovec *iovec) >> +{ >> + XENSTORE_RING_IDX prod; >> + const struct xs_iovec *crnt_iovec; >> + struct xs_iovec hdr_iovec; >> + unsigned int req_size, req_off; >> + unsigned int buf_off; >> + unsigned int this_chunk_len; >> + int rc; >> + >> + req_size = sizeof(*xsd_req) + xsd_req->len; >> + if (req_size > XENSTORE_RING_SIZE) >> + return -ENOSPC; >> + >> + hdr_iovec.data = xsd_req; >> + hdr_iovec.len = sizeof(*xsd_req); >> + >> + /* The batched iovecs are preceded by a single header. */ >> + crnt_iovec = &hdr_iovec; >> + >> + /* >> + * Wait for the ring to drain to the point where >> + * we can send the message. >> + */ >> + while (!xs_avail_space_for_write(req_size)) { >> + /* Wait for there to be space on the ring */ >> + uk_printd(DLVL_EXTRA, >> + "prod %d, len %d, cons %d, size %d; waiting.\n", >> + xsh.buf->req_prod, req_size, >> + xsh.buf->req_cons, XENSTORE_RING_SIZE); >> + >> + uk_waitq_wait_event(&xsh.waitq, >> + xs_avail_space_for_write(req_size)); >> + uk_printd(DLVL_EXTRA, "Back from wait.\n"); >> + } > This will work with cooperative scheduler for sure. But I guess that > here will be a problem in case of preemptive one. If we was preempted at > this point, and another thread wants to write to the ring buffer too, we > are screwed. For example, the other thread could use the free space in > the ring buffer, and when we get cpu time back, we will continue with > confidence that there is enough space for us. > > So far we was ignoring places like this. How about we start to leave at > least notes. For example /* TODO: disable preemption here */. > > Or, a dedicated thread would solve this problem, as discussed in v1 and > as you mentioned in the comment above this function. In deed, for preemptive scheduling we would have a problem here. I guess the best solution would be to delegate the writes to the xenstore thread. >> + >> + /* We must write requests after reading the consumer index. */ >> + mb(); > Maybe rmb() here is enough? Or do we actually need a full barrier? Before the barrier we have a read operation (reading the consumer index), while after we have write operations (writing the requests). So we need to order the writes after reads with full barrier. >> + >> + /* >> + * We're now guaranteed to be able to send the message >> + * without overflowing the ring. Do so. >> + */ >> + >> + prod = xsh.buf->req_prod; >> + req_off = 0; >> + buf_off = 0; >> + while (req_off < req_size) { >> + this_chunk_len = MIN(crnt_iovec->len - buf_off, >> + XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); >> + >> + memcpy( >> + (char *) xsh.buf->req + MASK_XENSTORE_IDX(prod), >> + (char *) crnt_iovec->data + buf_off, >> + this_chunk_len >> + ); >> + >> + prod += this_chunk_len; >> + req_off += this_chunk_len; >> + buf_off += this_chunk_len; >> + >> + if (buf_off == crnt_iovec->len) { >> + buf_off = 0; >> + if (crnt_iovec == &hdr_iovec) >> + crnt_iovec = iovec; >> + else >> + crnt_iovec++; >> + } >> + } >> + >> + uk_printd(DLVL_EXTRA, "Complete main loop of %s.\n", __func__); >> + UK_ASSERT(buf_off == 0); >> + UK_ASSERT(req_off == req_size); >> + UK_ASSERT(prod <= xsh.buf->req_cons + XENSTORE_RING_SIZE); >> + >> + /* Remote must see entire message before updating indexes */ >> + wmb(); >> + >> + xsh.buf->req_prod += req_size; >> + >> + /* Send evtchn to notify remote */ >> + rc = notify_remote_via_evtchn(xsh.evtchn); >> + UK_ASSERT(rc == 0); >> + >> + return 0; >> +} >> + >> +int xs_msg_reply(enum xsd_sockmsg_type msg_type, xenbus_transaction_t xbt, >> + const struct xs_iovec *req_iovecs, int req_iovecs_num, >> + struct xs_iovec *rep_iovec) >> +{ >> + struct xs_request *xs_req; >> + int err; >> + >> + if (req_iovecs == NULL) >> + return -EINVAL; >> + >> + xs_req = xs_request_get(); >> + xs_req->hdr.type = msg_type; >> + /* req_id was on pool init */ >> + xs_req->hdr.tx_id = xbt; >> + xs_req->hdr.len = 0; >> + for (int i = 0; i < req_iovecs_num; i++) >> + xs_req->hdr.len += req_iovecs[i].len; >> + >> + xs_req->reply.recvd = 0; >> + >> + /* send the request */ >> + err = xs_msg_write(&xs_req->hdr, req_iovecs); >> + if (err) >> + goto out; >> + >> + /* wait reply */ >> + uk_waitq_wait_event(&xs_req->waitq, >> + xs_req->reply.recvd != 0); >> + >> + err = xs_req->reply.errornum; >> + if (err == 0) { >> + if (rep_iovec) >> + *rep_iovec = xs_req->reply.iovec; >> + else >> + free(xs_req->reply.iovec.data); >> + } >> + >> +out: >> + xs_request_put(xs_req); >> + >> + return (-err); > xs_msg_write already returns a negative error code. This line will make > it positive. I guess you want to invert it when reading from > xs_req->reply.errornum, a few lines above, instead of doing it here Yes, good catch! >> +} >> + >> +/* >> + * Converts a Xenstore reply error to a positive error number. >> + * Returns 0 if the reply is successful. >> + */ >> +static int reply_to_errno(const char *reply) >> +{ >> + int err = 0; >> + >> + for (int i = 0; i < (int) ARRAY_SIZE(xsd_errors); i++) { >> + if (!strcmp(reply, xsd_errors[i].errstring)) { >> + err = xsd_errors[i].errnum; >> + goto out; >> + } >> + } >> + >> + uk_printd(DLVL_WARN, "Unknown Xenstore error: %s\n", reply); >> + err = EINVAL; >> + >> +out: >> + return err; >> +} >> + >> +/* Process an incoming xs reply */ >> +static void process_reply(struct xsd_sockmsg *hdr, char *payload) >> +{ >> + struct xs_request *xs_req; >> + >> + if (!test_bit(hdr->req_id, xs_req_pool.entries_bm)) { >> + uk_printd(DLVL_WARN, "Invalid reply id=%d", hdr->req_id); >> + free(payload); >> + return; >> + } >> + >> + xs_req = &xs_req_pool.entries[hdr->req_id]; >> + >> + if (hdr->type == XS_ERROR) { >> + xs_req->reply.errornum = reply_to_errno(payload); >> + free(payload); >> + >> + } else if (hdr->type != xs_req->hdr.type) { >> + uk_printd(DLVL_WARN, "Mismatching message type: %d", hdr->type); >> + free(payload); >> + return; >> + >> + } else { >> + /* set reply */ >> + xs_req->reply.iovec.data = payload; >> + xs_req->reply.iovec.len = hdr->len; >> + xs_req->reply.errornum = 0; >> + } >> + >> + xs_req->reply.recvd = 1; >> + >> + /* notify waiting requester */ >> + uk_waitq_wake_up(&xs_req->waitq); >> +} >> + >> +/* Process an incoming xs watch event */ >> +static void process_watch_event(char *watch_msg) >> +{ >> + /* TODO */ >> +} >> + >> +static void memcpy_from_ring(const char *ring, char *dest, int off, int len) >> +{ >> + int c1, c2; >> + >> + c1 = MIN(len, XENSTORE_RING_SIZE - off); >> + c2 = len - c1; >> + >> + memcpy(dest, ring + off, c1); >> + if (c2) >> + memcpy(dest + c1, ring, c2); >> +} >> + >> +static void xs_msg_read(struct xsd_sockmsg *hdr) >> +{ >> + XENSTORE_RING_IDX cons; >> + char *payload; >> + >> + payload = malloc(hdr->len + 1); >> + if (payload == NULL) { >> + uk_printd(DLVL_WARN, >> + "No memory available for saving Xenstore message!"); >> + return; >> + } >> + >> + cons = xsh.buf->rsp_cons; >> + >> + /* copy payload */ >> + memcpy_from_ring( >> + xsh.buf->rsp, >> + payload, >> + MASK_XENSTORE_IDX(cons + sizeof(*hdr)), >> + hdr->len >> + ); >> + payload[hdr->len] = '\0'; >> + >> + /* Remote must not see available space until we've copied the reply */ >> + mb(); > Maybe wmb() here is enough? Or do we actually need a full barrier? Similarly to the previous situation, before the barrier we have a read operation (reading the request data), while after the barrier we have a write operation (writing the consumer index). So we need to order write after read with full barrier. >> + xsh.buf->rsp_cons += sizeof(*hdr) + hdr->len; >> + >> + if (xsh.buf->rsp_prod - cons >= XENSTORE_RING_SIZE) >> + notify_remote_via_evtchn(xsh.evtchn); >> + >> + if (hdr->type == XS_WATCH_EVENT) >> + process_watch_event(payload); >> + else >> + process_reply(hdr, payload); >> +} >> + >> +static void xs_thread_func(void *ign __unused) >> +{ >> + struct xsd_sockmsg msg; >> + XENSTORE_RING_IDX prod = xsh.buf->rsp_prod; >> + >> + for (;;) { >> + /* wait for incoming xs response */ >> + uk_waitq_wait_event(&xsh.waitq, prod != xsh.buf->rsp_prod); >> + >> + while (1) { >> + prod = xsh.buf->rsp_prod; >> + >> + uk_printd(DLVL_EXTRA, "Rsp_cons %d, rsp_prod %d.\n", >> + xsh.buf->rsp_cons, xsh.buf->rsp_prod); >> + >> + if (!xs_avail_space_for_read(sizeof(msg))) >> + break; >> + >> + /* Make sure data is read after reading the indexes */ >> + rmb(); >> + >> + /* copy the message header */ >> + memcpy_from_ring( >> + xsh.buf->rsp, >> + (char *) &msg, >> + MASK_XENSTORE_IDX(xsh.buf->rsp_cons), >> + sizeof(msg) >> + ); >> + >> + uk_printd(DLVL_EXTRA, "Msg len %lu, %u avail, id %u.\n", >> + msg.len + sizeof(msg), >> + xsh.buf->rsp_prod - xsh.buf->rsp_cons, >> + msg.req_id); >> + >> + if (!xs_avail_space_for_read(sizeof(msg) + msg.len)) >> + break; >> + >> + /* Make sure data is read after reading the indexes */ >> + rmb(); >> + >> + uk_printd(DLVL_EXTRA, "Message is good.\n"); >> + xs_msg_read(&msg); >> + } >> + } >> +} >> + >> +static void xs_evtchn_handler(evtchn_port_t port, >> + struct __regs *regs __unused, void *ign __unused) >> +{ >> + UK_ASSERT(xsh.evtchn == port); >> + uk_waitq_wake_up(&xsh.waitq); >> +} >> + >> +int xs_comms_init(void) >> +{ >> + struct uk_thread *thread; >> + evtchn_port_t port; >> + >> + xs_request_pool_init(&xs_req_pool); >> + >> + uk_waitq_init(&xsh.waitq); >> + >> + thread = uk_thread_create("xenstore", xs_thread_func, NULL); >> + if (PTRISERR(thread)) >> + return PTR2ERR(thread); >> + >> + xsh.thread = thread; >> + >> + xsh.evtchn = HYPERVISOR_start_info->store_evtchn; >> + xsh.buf = mfn_to_virt(HYPERVISOR_start_info->store_mfn); >> + >> + port = bind_evtchn(xsh.evtchn, xs_evtchn_handler, NULL); >> + UK_ASSERT(port == xsh.evtchn); >> + unmask_evtchn(xsh.evtchn); >> + >> + uk_printd(DLVL_INFO, >> + "Xenstore connection initialised on port %d, buf %p (mfn >> %#lx)\n", >> + port, xsh.buf, HYPERVISOR_start_info->store_mfn); >> + >> + return 0; >> +} >> + >> +void xs_comms_fini(void) >> +{ >> + mask_evtchn(xsh.evtchn); >> + unbind_evtchn(xsh.evtchn); >> + >> + xsh.buf = NULL; >> + >> + /* TODO stop thread, instead of killing it */ >> + uk_thread_destroy(xsh.thread); >> + xsh.thread = NULL; >> +} >> diff --git a/plat/xen/xenbus/xs_comms.h b/plat/xen/xenbus/xs_comms.h >> new file mode 100644 >> index 0000000..9b558d0 >> --- /dev/null >> +++ b/plat/xen/xenbus/xs_comms.h >> @@ -0,0 +1,64 @@ >> +/* SPDX-License-Identifier: BSD-3-Clause */ >> +/* >> + * Authors: Costin Lupu <costin.lupu@xxxxxxxxx> >> + * >> + * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights >> reserved. >> + * >> + * Redistribution and use in source and binary forms, with or without >> + * modification, are permitted provided that the following conditions >> + * are met: >> + * >> + * 1. Redistributions of source code must retain the above copyright >> + * notice, this list of conditions and the following disclaimer. >> + * 2. Redistributions in binary form must reproduce the above copyright >> + * notice, this list of conditions and the following disclaimer in the >> + * documentation and/or other materials provided with the distribution. >> + * 3. Neither the name of the copyright holder nor the names of its >> + * contributors may be used to endorse or promote products derived from >> + * this software without specific prior written permission. >> + * >> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS >> IS" >> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >> PURPOSE >> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE >> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >> THE >> + * POSSIBILITY OF SUCH DAMAGE. >> + * >> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. >> + */ >> + >> +#ifndef __XS_COMMS_H__ >> +#define __XS_COMMS_H__ >> + >> +#include <xen/io/xs_wire.h> >> +#include <xenbus/xs.h> >> + >> +int xs_comms_init(void); >> +void xs_comms_fini(void); >> + >> +struct xs_iovec { >> + void *data; >> + unsigned int len; >> +}; >> + >> +/* >> + * Sends a message to Xenstore and blocks waiting for a reply. >> + * The reply is malloc'ed and should be freed by the caller. >> + * >> + * @param msg_type Xenstore message type >> + * @param xbt Xenbus transaction id >> + * @param req_iovecs Array of request strings buffers >> + * @param req_iovecs_num Request strings buffers number >> + * @param rep_iovec Incoming reply string buffer (optional) >> + * @return 0 on success, a negative errno value on error. >> + */ >> +int xs_msg_reply(enum xsd_sockmsg_type msg_type, xenbus_transaction_t xbt, >> + const struct xs_iovec *req_iovecs, int req_iovecs_num, >> + struct xs_iovec *rep_iovec); >> + >> +#endif /* __XS_COMMS_H__ */ >> -- >> 2.11.0 >> > _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |