+#include <xtf/atomic.h>
+#include <xtf/bitops.h>
+#include <xtf/hypercall.h>
#include <xtf/lib.h>
#include <xtf/traps.h>
#include <xtf/xenbus.h>
static xenbus_interface_t *xb_ring;
static evtchn_port_t xb_port;
+static char payload[XENSTORE_PAYLOAD_MAX + 1];
void init_xenbus(xenbus_interface_t *ring, evtchn_port_t port)
{
xb_port = port;
}
+/*
+ * Write some raw data into the xenbus ring. Waits for sufficient space to
+ * appear if necessary.
+ */
+static void xenbus_write(const void *data, size_t len)
+{
+ uint32_t part, done = 0;
+
+ while ( len )
+ {
+ uint32_t prod = ACCESS_ONCE(xb_ring->req_prod);
+ uint32_t cons = ACCESS_ONCE(xb_ring->req_cons);
+
+ uint32_t used = mask_xenbus_idx(prod - cons);
+
+ part = (XENBUS_RING_SIZE - 1) - used;
+
+ /* No space? Kick xenstored and wait for it to consume some data. */
+ if ( !part )
+ {
+ hypercall_evtchn_send(xb_port);
+
+ if ( !test_and_clear_bit(xb_port, shared_info.evtchn_pending) )
+ hypercall_poll(xb_port);
+
+ continue;
+ }
+
+ /* Don't overrun the ring. */
+ part = min(part, XENBUS_RING_SIZE - used);
+
+ /* Don't write more than necessary. */
+ part = min(part, (unsigned int)len);
+
+ memcpy(xb_ring->req + mask_xenbus_idx(prod), data + done, part);
+
+ /* Complete the data read before updating the new producer index. */
+ smp_wmb();
+
+ ACCESS_ONCE(xb_ring->req_prod) = prod + part;
+
+ len -= part;
+ done += part;
+ }
+}
+
+/*
+ * Read some raw data from the xenbus ring. Waits for sufficient data to
+ * appear if necessary.
+ */
+static void xenbus_read(void *data, size_t len)
+{
+ uint32_t part, done = 0;
+
+ while ( len )
+ {
+ uint32_t prod = ACCESS_ONCE(xb_ring->rsp_prod);
+ uint32_t cons = ACCESS_ONCE(xb_ring->rsp_cons);
+
+ part = mask_xenbus_idx(prod - cons);
+
+ /* No data? Kick xenstored and wait for it to produce some data. */
+ if ( !part )
+ {
+ hypercall_evtchn_send(xb_port);
+
+ if ( !test_and_clear_bit(xb_port, shared_info.evtchn_pending) )
+ hypercall_poll(xb_port);
+
+ continue;
+ }
+
+ /* Avoid overrunning the ring. */
+ part = min(part, XENBUS_RING_SIZE - mask_xenbus_idx(cons));
+
+ /* Don't read more than necessary. */
+ part = min(part, (unsigned int)len);
+
+ memcpy(data + done, xb_ring->rsp + mask_xenbus_idx(cons), part);
+
+ /* Complete the data read before updating the new consumer index. */
+ smp_mb();
+
+ ACCESS_ONCE(xb_ring->rsp_cons) = cons + part;
+
+ len -= part;
+ done += part;
+ }
+}
+
+const char *xenstore_read(const char *path)
+{
+ struct xenstore_msg_hdr hdr = {
+ .type = XS_READ,
+ .len = strlen(path) + 1, /* Must send the NUL terminator. */
+ };
+
+ /* Write the header and path to read. */
+ xenbus_write(&hdr, sizeof(hdr));
+ xenbus_write(path, hdr.len);
+
+ /* Kick xenstored. */
+ hypercall_evtchn_send(xb_port);
+
+ /* Read the response header. */
+ xenbus_read(&hdr, sizeof(hdr));
+
+ if ( hdr.type != XS_READ )
+ return NULL;
+
+ if ( hdr.len > XENSTORE_PAYLOAD_MAX )
+ {
+ /*
+ * Xenstored handed back too much data. Drain it safely attempt to
+ * prevent the protocol from stalling.
+ */
+ while ( hdr.len )
+ {
+ unsigned int part = min(hdr.len, XENSTORE_PAYLOAD_MAX + 0u);
+
+ xenbus_read(payload, part);
+
+ hdr.len -= part;
+ }
+
+ return NULL;
+ }
+
+ /* Read the response payload. */
+ xenbus_read(payload, hdr.len);
+
+ /* Safely terminate the reply, just in case xenstored didn't. */
+ payload[hdr.len] = '\0';
+
+ return payload;
+}
+
/*
* Local variables:
* mode: C
#define XENBUS_CONNECTED 0
#define XENBUS_RECONNECT 1
+
+/* API/ABI relevent to the Xenstore protocol. */
+
+struct xenstore_msg_hdr {
+ uint32_t type;
+ uint32_t req_id;
+ uint32_t tx_id;
+ uint32_t len;
+};
+
+enum xenstore_msg_type
+{
+ XS_CONTROL,
+ XS_DIRECTORY,
+ XS_READ,
+ XS_GET_PERMS,
+ XS_WATCH,
+ XS_UNWATCH,
+ XS_TRANSACTION_START,
+ XS_TRANSACTION_END,
+ XS_INTRODUCE,
+ XS_RELEASE,
+ XS_GET_DOMAIN_PATH,
+ XS_WRITE,
+ XS_MKDIR,
+ XS_RM,
+ XS_SET_PERMS,
+ XS_WATCH_EVENT,
+ XS_ERROR,
+ XS_IS_DOMAIN_INTRODUCED,
+ XS_RESUME,
+ XS_SET_TARGET,
+ /* XS_RESTRICT has been removed */
+ XS_RESET_WATCHES = XS_SET_TARGET + 2,
+ XS_DIRECTORY_PART,
+
+ XS_TYPE_COUNT, /* Number of valid types. */
+
+ XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
+};
+
+
+#define XENSTORE_PAYLOAD_MAX 4096
+
+#define XENSTORE_ABS_PATH_MAX 3072
+#define XENSTORE_REL_PATH_MAX 2048
+
#endif /* XEN_PUBLIC_IO_XS_WIRE_H */
/*
const char test_title[] = "XTF Selftests";
+static void test_xenstore(void)
+{
+ printk("Test: Xenstore read\n");
+
+ const char *domid_str = xenstore_read("domid");
+
+ if ( !domid_str )
+ return xtf_failure("Fail: No domid value returned\n");
+
+ if ( domid_str[0] == '\0' )
+ return xtf_failure("Fail: domid value empty\n");
+
+ unsigned int i;
+ for ( i = 0; domid_str[i]; ++i )
+ {
+ if ( domid_str[i] < '0' || domid_str[i] > '9' )
+ return xtf_failure("Fail: unexpected domid value '%s'\n",
+ domid_str);
+ }
+
+ printk(" Found domid %s\n", domid_str);
+}
+
static void test_extable(void)
{
printk("Test: Exception Table\n");
write_cr4(cr4);
}
+ test_xenstore();
test_extable();
test_exlog();
test_exec_user();