Xen Test Framework
xenbus.c
Go to the documentation of this file.
1 #include <xtf/atomic.h>
2 #include <xtf/bitops.h>
3 #include <xtf/hypercall.h>
4 #include <xtf/lib.h>
5 #include <xtf/traps.h>
6 #include <xtf/xenbus.h>
7 
10 static char payload[XENSTORE_PAYLOAD_MAX + 1];
11 
13 {
14  if ( port >= (sizeof(shared_info.evtchn_pending) * CHAR_BIT) )
15  panic("evtchn %u out of evtchn_pending[] range\n", port);
16 
17  xb_ring = ring;
18  xb_port = port;
19 }
20 
21 /*
22  * Write some raw data into the xenbus ring. Waits for sufficient space to
23  * appear if necessary.
24  */
25 static void xenbus_write(const void *data, size_t len)
26 {
27  uint32_t part, done = 0;
28 
29  while ( len )
30  {
31  uint32_t prod = ACCESS_ONCE(xb_ring->req_prod);
32  uint32_t cons = ACCESS_ONCE(xb_ring->req_cons);
33 
34  part = (XENBUS_RING_SIZE - 1) - mask_xenbus_idx(prod - cons);
35 
36  /* No space? Kick xenstored and wait for it to consume some data. */
37  if ( !part )
38  {
40 
43 
44  continue;
45  }
46 
47  /* Don't overrun the ring. */
48  part = min(part, XENBUS_RING_SIZE - mask_xenbus_idx(prod));
49 
50  /* Don't write more than necessary. */
51  part = min(part, (unsigned int)len);
52 
53  memcpy(xb_ring->req + mask_xenbus_idx(prod), data + done, part);
54 
55  /* Complete the data read before updating the new producer index. */
56  smp_wmb();
57 
58  ACCESS_ONCE(xb_ring->req_prod) = prod + part;
59 
60  len -= part;
61  done += part;
62  }
63 }
64 
65 /*
66  * Read some raw data from the xenbus ring. Waits for sufficient data to
67  * appear if necessary.
68  */
69 static void xenbus_read(void *data, size_t len)
70 {
71  uint32_t part, done = 0;
72 
73  while ( len )
74  {
75  uint32_t prod = ACCESS_ONCE(xb_ring->rsp_prod);
76  uint32_t cons = ACCESS_ONCE(xb_ring->rsp_cons);
77 
78  part = prod - cons;
79 
80  /* No data? Kick xenstored and wait for it to produce some data. */
81  if ( !part )
82  {
84 
87 
88  continue;
89  }
90 
91  /* Avoid overrunning the ring. */
92  part = min(part, XENBUS_RING_SIZE - mask_xenbus_idx(cons));
93 
94  /* Don't read more than necessary. */
95  part = min(part, (unsigned int)len);
96 
97  memcpy(data + done, xb_ring->rsp + mask_xenbus_idx(cons), part);
98 
99  /* Complete the data read before updating the new consumer index. */
100  smp_mb();
101 
102  ACCESS_ONCE(xb_ring->rsp_cons) = cons + part;
103 
104  len -= part;
105  done += part;
106  }
107 }
108 
109 int xenstore_init(void)
110 {
111  /* Nothing to initialise. Report the presence of the xenbus ring. */
112  return xb_port ? 0 : -ENODEV;
113 }
114 
115 const char *xenstore_read(const char *path)
116 {
117  struct xenstore_msg_hdr hdr = {
118  .type = XS_READ,
119  .len = strlen(path) + 1, /* Must send the NUL terminator. */
120  };
121 
122  /* Write the header and path to read. */
123  xenbus_write(&hdr, sizeof(hdr));
124  xenbus_write(path, hdr.len);
125 
126  /* Kick xenstored. */
128 
129  /* Read the response header. */
130  xenbus_read(&hdr, sizeof(hdr));
131 
132  if ( hdr.type != XS_READ )
133  return NULL;
134 
135  if ( hdr.len > XENSTORE_PAYLOAD_MAX )
136  {
137  /*
138  * Xenstored handed back too much data. Drain it safely attempt to
139  * prevent the protocol from stalling.
140  */
141  while ( hdr.len )
142  {
143  unsigned int part = min(hdr.len, XENSTORE_PAYLOAD_MAX + 0u);
144 
145  xenbus_read(payload, part);
146 
147  hdr.len -= part;
148  }
149 
150  return NULL;
151  }
152 
153  /* Read the response payload. */
154  xenbus_read(payload, hdr.len);
155 
156  /* Safely terminate the reply, just in case xenstored didn't. */
157  payload[hdr.len] = '\0';
158 
159  return payload;
160 }
161 
162 /*
163  * Local variables:
164  * mode: C
165  * c-file-style: "BSD"
166  * c-basic-offset: 4
167  * tab-width: 4
168  * indent-tabs-mode: nil
169  * End:
170  */
static int hypercall_evtchn_send(evtchn_port_t port)
Definition: hypercall.h:223
#define smp_mb()
Definition: barrier.h:33
static evtchn_port_t xb_port
Definition: xenbus.c:9
#define strlen(s)
Definition: libc.h:18
static xenbus_interface_t * xb_ring
Definition: xenbus.c:8
uint32_t evtchn_port_t
Definition: event_channel.h:11
void panic(const char *fmt,...)
Definition: lib.c:15
#define CHAR_BIT
Definition: limits.h:9
static uint32_t mask_xenbus_idx(uint32_t idx)
Definition: xs_wire.h:7
#define smp_wmb()
Definition: barrier.h:36
unsigned long evtchn_pending[sizeof(unsigned long) *8]
Definition: xen.h:186
static void xenbus_write(const void *data, size_t len)
Definition: xenbus.c:25
void init_xenbus(xenbus_interface_t *ring, evtchn_port_t port)
Definition: xenbus.c:12
char req[XENBUS_RING_SIZE]
Definition: xs_wire.h:13
int xenstore_init(void)
Initialise XTF ready for xenstore communication.
Definition: xenbus.c:109
#define NULL
Definition: stddef.h:12
char rsp[XENBUS_RING_SIZE]
Definition: xs_wire.h:14
#define memcpy(d, s, n)
Definition: libc.h:36
#define XENSTORE_PAYLOAD_MAX
Definition: xs_wire.h:69
uint32_t req_prod
Definition: xs_wire.h:15
__UINT32_TYPE__ uint32_t
Definition: stdint.h:16
Low level bit operations.
uint32_t rsp_cons
Definition: xs_wire.h:16
const char * xenstore_read(const char *path)
Issue a XS_READ operation for key, waiting synchronously for the reply.
Definition: xenbus.c:115
#define ENODEV
Definition: errno.h:32
uint32_t rsp_prod
Definition: xs_wire.h:16
uint32_t len
Definition: xs_wire.h:34
static void xenbus_read(void *data, size_t len)
Definition: xenbus.c:69
static long hypercall_poll(evtchn_port_t port)
Definition: hypercall.h:211
#define XENBUS_RING_SIZE
Definition: xs_wire.h:6
uint32_t type
Definition: xs_wire.h:31
static char payload[XENSTORE_PAYLOAD_MAX+1]
Definition: xenbus.c:10
static bool test_and_clear_bit(unsigned int bit, volatile void *addr)
Definition: bitops.h:53
#define min(a, b)
Definition: lib.h:28
#define ACCESS_ONCE(x)
Definition: lib.h:10
uint32_t req_cons
Definition: xs_wire.h:15