WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 09/10] Xen: Xenstore communication via xenbus

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 09/10] Xen: Xenstore communication via xenbus
From: Daniel Castro <evil.dani@xxxxxxxxx>
Date: Fri, 19 Aug 2011 01:03:26 +0900
Cc: Daniel Castro <evil.dani@xxxxxxxxx>
Delivery-date: Thu, 18 Aug 2011 09:16:38 -0700
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=7+zCjI8oYmXU+z6A5h7wB0A1ua7sOQ55VBqpyBgENxE=; b=QbAjO6BWcW3X6MfIyYgvBnL3acl5OaKHo8ObUVKSVcS0wIJQzr2YGFp5TS/txgQHx0 9qREinW+YtMCJJmS1QCYzsrpIkYg2jtypBxr08Shhs2/SOaZLMnW+TbIwdUCiByRczP0 L7OZtzhy78Tar1o53ffFObAWO/hE6achmwGPA=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1313683408-32306-1-git-send-email-evil.dani@xxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1313683408-32306-1-git-send-email-evil.dani@xxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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@xxxxxxxxx>
---
 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, &param))
+               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, &param))
+               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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel