From: Daniel Castro <evil.dani@gmail.com>
To: xen-devel@lists.xensource.com
Cc: Daniel Castro <evil.dani@gmail.com>
Subject: [PATCH 09/10] Xen: Xenstore communication via xenbus
Date: Fri, 19 Aug 2011 01:03:26 +0900 [thread overview]
Message-ID: <1313683408-32306-10-git-send-email-evil.dani@gmail.com> (raw)
In-Reply-To: <1313683408-32306-1-git-send-email-evil.dani@gmail.com>
Communication with Xenstore is now possible via xenbus. Initially
only xenstore_read and xenstore_directory are provided, but more
operations will be added. Xenbus rings are initialized on post.c
hardware init.
Signed-off-by: Daniel Castro <evil.dani@gmail.com>
---
Makefile | 2 +-
src/post.c | 2 +
src/xen-xs.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/xen-xs.h | 8 ++
4 files changed, 254 insertions(+), 1 deletions(-)
create mode 100644 src/xen-xs.c
create mode 100644 src/xen-xs.h
diff --git a/Makefile b/Makefile
index 109091b..e4dd814 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ SRC16=$(SRCBOTH) system.c disk.c font.c
SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c \
- biostables.c xen.c bmp.c
+ biostables.c xen.c bmp.c xen-xs.c
SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
diff --git a/src/post.c b/src/post.c
index e195e89..be8f5ed 100644
--- a/src/post.c
+++ b/src/post.c
@@ -26,6 +26,7 @@
#include "xen.h" // xen_probe_hvm_info
#include "ps2port.h" // ps2port_setup
#include "virtio-blk.h" // virtio_blk_setup
+#include "xen-xs.h"
/****************************************************************
@@ -190,6 +191,7 @@ init_hw(void)
cbfs_payload_setup();
ramdisk_setup();
virtio_blk_setup();
+ xenbus_setup();
}
// Begin the boot process by invoking an int0x19 in 16bit mode.
diff --git a/src/xen-xs.c b/src/xen-xs.c
new file mode 100644
index 0000000..d4b6b26
--- /dev/null
+++ b/src/xen-xs.c
@@ -0,0 +1,243 @@
+/*
+ * xenbus.c: static, synchronous, read-only xenbus client for hvmloader.
+ *
+ * Copyright (c) 2009 Tim Deegan, Citrix Systems (R&D) Ltd.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ */
+
+#include "xen.h" // hypercalls
+#include "config.h" // CONFIG_*
+#include "util.h"
+#include "bitops.h"
+#include "memmap.h"
+
+
+static struct xenstore_domain_interface *rings; /* Shared ring with dom0 */
+static evtchn_port_t event; /* Event-channel to dom0 */
+static char payload[XENSTORE_PAYLOAD_MAX + 1]; /* Unmarshalling area */
+
+
+/*
+ * Connect our xenbus client to the backend.
+ * Call once, before any other xenbus actions.
+ */
+void xenbus_setup(void)
+{
+ struct xen_hvm_param param;
+ if (!CONFIG_XEN)
+ return;
+
+ /* Ask Xen where the xenbus shared page is. */
+ param.domid = DOMID_SELF;
+ param.index = HVM_PARAM_STORE_PFN;
+ if (hypercall_hvm_op(HVMOP_get_param, ¶m))
+ panic("Error on setup");
+ rings = (void *) (unsigned long) (param.value << PAGE_SHIFT);
+
+ /* Ask Xen where the xenbus event channel is. */
+ param.domid = DOMID_SELF;
+ param.index = HVM_PARAM_STORE_EVTCHN;
+ if (hypercall_hvm_op(HVMOP_get_param, ¶m))
+ panic("error on hypercall to define rings and channel");
+ event = param.value;
+ dprintf(1,"Xenbus rings @0x%lx, event channel %lu\n",
+ (unsigned long) rings, (unsigned long) event);
+}
+
+/*
+ * Reset the xenbus connection
+ */
+void xenbus_shutdown(void)
+{
+ if (rings == NULL)
+ panic("rings not defined");
+ memset(rings, 0, sizeof *rings);
+ memset(get_shared_info(), 0, 1024);
+ rings = NULL;
+}
+
+/*
+ * 1. Get xen shared info
+ * 2. get the guest event handle
+ * 3. while no events pending
+ * 4 .issue a yield to the CPU until event arrives
+ */
+static void ring_wait(void)
+{
+ struct shared_info *shinfo = get_shared_info();
+ struct sched_poll poll;
+
+ memset(&poll, 0, sizeof(poll));
+ set_xen_guest_handle(poll.ports, &event);
+ poll.nr_ports = 1;
+
+ while (!test_and_clear_bit(event, shinfo->evtchn_pending))
+ hypercall_sched_op(SCHEDOP_poll, &poll);
+}
+
+/*
+ * Writes data to xenstore ring
+ */
+static void ring_write(char *data, u32 len)
+{
+ u32 part;
+
+ if (len >= XENSTORE_PAYLOAD_MAX)
+ panic("Write Error on RINGS, more data than available buffer");
+
+ while (len)
+ {
+ while ((part = (XENSTORE_RING_SIZE - 1) -
+ MASK_XENSTORE_IDX(rings->req_prod - rings->req_cons)) == 0) {
+ ring_wait();
+ //The ring is not empty or not ready
+ }
+ if (part > (XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->req_prod)))
+ part = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->req_prod);
+
+ if (part > len) /* Don't write more than we were asked for */
+ part = len;
+ memcpy(rings->req + MASK_XENSTORE_IDX(rings->req_prod), data, part);
+ barrier();
+ rings->req_prod += part;
+ len -= part;
+ }
+}
+
+/*
+ * reads response from xenstore ring
+ */
+static void ring_read(char *data, u32 len)
+{
+ u32 part;
+
+ if (len >= XENSTORE_PAYLOAD_MAX)
+ panic("RING READ ERROR, more data that buffer space on rings");
+
+ while (len) {
+ while ((part = MASK_XENSTORE_IDX(rings->rsp_prod -rings->rsp_cons)) == 0) {
+ ring_wait(); //The ring is not ready or not empty
+ }
+ /* Don't overrun the end of the ring */
+ if (part > (XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->rsp_cons)))
+ part = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(rings->rsp_cons);
+
+ if (part > len) /* Don't read more than we were asked for */
+ part = len;
+ memcpy(data, rings->rsp + MASK_XENSTORE_IDX(rings->rsp_cons), part);
+ barrier();
+ rings->rsp_cons += part;
+ len -= part;
+ }
+}
+
+
+/*
+ * Send a request and wait for the answer.
+ * Returns 0 for success, or an errno for error.
+ */
+static int xenbus_send(u32 type, u32 len, char *data,
+ u32 *reply_len, char **reply_data)
+{
+ struct xsd_sockmsg hdr;
+ evtchn_send_t send;
+ int i,ret;
+
+ /* Not acceptable to use xenbus before setting it up */
+ if (rings == NULL)
+ panic("XENBUS rings not defined\n");
+
+ /* Put the request on the ring */
+ hdr.type = type;
+ /* We only ever issue one request at a time */
+ hdr.req_id = 222;
+ /* We never use transactions */
+ hdr.tx_id = 0;
+ hdr.len = len;
+ ring_write((char *) &hdr, sizeof hdr);
+ ring_write(data, len);
+ /* Tell the other end about the request */
+ send.port = event;
+ ret = hypercall_event_channel_op(EVTCHNOP_send, &send);
+ dprintf(1,"Hypercall event channel notification %d\n",ret);
+ /* Properly we should poll the event channel now but that involves
+ * mapping the shared-info page and handling the bitmaps. */
+ /* Pull the reply off the ring */
+ ring_read((char *) &hdr, sizeof(hdr));
+ ring_read(payload, hdr.len);
+ /* For sanity's sake, nul-terminate the answer */
+ payload[hdr.len] = '\0';
+ /* Handle errors */
+ if ( hdr.type == XS_ERROR )
+ {
+ *reply_len = 0;
+ for ( i = 0; i < ((sizeof xsd_errors) / (sizeof xsd_errors[0])); i++ ){
+ if ( !strcmp(xsd_errors[i].errstring, payload) ){
+ return xsd_errors[i].errnum;
+ }
+ }
+ return EIO;
+ }
+ *reply_data = payload;
+ *reply_len = hdr.len;
+ return hdr.type;
+}
+
+
+/*
+ * Read a xenstore key. Returns a nul-terminated string (even if the XS
+ * data wasn't nul-terminated) or NULL. The returned string is in a
+ * static buffer, so only valid until the next xenstore/xenbus operation.
+ */
+char * xenstore_read(char *path){
+ if (rings == NULL)
+ panic("rings not defined");
+ u32 len = 0;
+ char *answer = NULL;
+
+ /* Include the nul in the request */
+ if ( xenbus_send(XS_READ, strlen(path)+1, path, &len, &answer)== XS_ERROR ){
+ return NULL;
+ }
+ /* We know xenbus_send() nul-terminates its answer, so just pass it on. */
+ return answer;
+}
+
+/*
+ * Read a xenstore directory. Returns a nul-separeted and nul-terminated string (even if the XS
+ * data wasn't nul-terminated) or NULL. The returned string is in a
+ * static buffer, so only valid until the next xenstore/xenbus operation.
+ * ans_len will tell the caller the length of the response
+ */
+char * xenstore_directory(char *path, u32 *ans_len){
+ if (rings == NULL)
+ panic("rings not defined");
+ char *answer = NULL;
+
+ /* Include the nul in the request */
+ if ( xenbus_send(XS_DIRECTORY, strlen(path)+1, path, ans_len, &answer)== XS_ERROR ){
+ return NULL;
+ }
+ /* We know xenbus_send() nul-terminates its answer, so just pass it on. */
+ return answer;
+}
diff --git a/src/xen-xs.h b/src/xen-xs.h
new file mode 100644
index 0000000..91e8da0
--- /dev/null
+++ b/src/xen-xs.h
@@ -0,0 +1,8 @@
+#ifndef _XEN_XS_H
+#define _XEN_XS_H
+
+void xenbus_setup(void);
+char * xenstore_read(char *path);
+char * xenstore_directory(char *path, u32 *ans_len);
+
+#endif
--
1.7.4.1
next prev parent reply other threads:[~2011-08-18 16:03 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-18 16:03 [PATCH 00/10] Xenstore communication support for Seabios Daniel Castro
2011-08-18 16:03 ` [PATCH 01/10] Xen: Guest Handlers and Copyrights Daniel Castro
2011-08-18 16:03 ` [PATCH 02/10] Move PAGE_SHIFT to memmap.h Daniel Castro
2011-08-24 17:51 ` Konrad Rzeszutek Wilk
2011-08-24 21:08 ` Ian Campbell
2011-08-18 16:03 ` [PATCH 03/10] Xen: Use PAGE_SHIFT as a constant Daniel Castro
2011-08-18 16:03 ` [PATCH 04/10] Xen: Support for interdomain event channel Daniel Castro
2011-08-18 16:03 ` [PATCH 05/10] Xen: Support for HVM_op Hypercall Daniel Castro
2011-08-18 16:03 ` [PATCH 06/10] Xen: Support for memory_op Hypercall Daniel Castro
2011-08-18 16:03 ` [PATCH 07/10] Xen: Support for sched_op hypercall Daniel Castro
2011-08-18 16:03 ` [PATCH 08/10] Xen: Shared info for CPU yield support and xenbus protocol Daniel Castro
2011-08-18 16:03 ` Daniel Castro [this message]
2011-08-18 16:03 ` [PATCH 10/10] Xen: Xenstore example -do not apply Daniel Castro
2011-08-18 16:03 ` [PATCH 10/10] Xen: Xenstore example Daniel Castro
2011-08-24 17:56 ` [PATCH 00/10] Xenstore communication support for Seabios Konrad Rzeszutek Wilk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1313683408-32306-10-git-send-email-evil.dani@gmail.com \
--to=evil.dani@gmail.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.