blob: 36de5255099781e5c45e8afafcb5e71f30dd2a7c [file] [log] [blame]
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +03001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) 2006 - Cambridge University
4 * (C) 2020 - EPAM Systems Inc.
5 *
6 * File: xenbus.c [1]
7 * Author: Steven Smith (sos22@cam.ac.uk)
8 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
9 * Changes: John D. Ramsdell
10 *
11 * Date: Jun 2006, changes Aug 2006
12 *
13 * Description: Minimal implementation of xenbus
14 *
15 * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary
16 */
17
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +030018#include <log.h>
19
20#include <asm/armv8/mmu.h>
21#include <asm/io.h>
22#include <asm/xen/system.h>
23
24#include <linux/bug.h>
25#include <linux/compat.h>
26
27#include <xen/events.h>
28#include <xen/hvm.h>
29#include <xen/xenbus.h>
30
31#include <xen/interface/io/xs_wire.h>
32
33#define map_frame_virt(v) (v << PAGE_SHIFT)
34
35#define SCNd16 "d"
36
37/* Wait for reply time out, ms */
38#define WAIT_XENBUS_TO_MS 5000
39/* Polling time out, ms */
40#define WAIT_XENBUS_POLL_TO_MS 1
41
42static struct xenstore_domain_interface *xenstore_buf;
43
44static char *errmsg(struct xsd_sockmsg *rep);
45
46u32 xenbus_evtchn;
47
48struct write_req {
49 const void *data;
50 unsigned int len;
51};
52
53static void memcpy_from_ring(const void *r, void *d, int off, int len)
54{
55 int c1, c2;
56 const char *ring = r;
57 char *dest = d;
58
59 c1 = min(len, XENSTORE_RING_SIZE - off);
60 c2 = len - c1;
61 memcpy(dest, ring + off, c1);
62 memcpy(dest + c1, ring, c2);
63}
64
65/**
66 * xenbus_get_reply() - Receive reply from xenbus
67 * @req_reply: reply message structure
68 *
69 * Wait for reply message event from the ring and copy received message
70 * to input xsd_sockmsg structure. Repeat until full reply is
71 * proceeded.
72 *
73 * Return: false - timeout
74 * true - reply is received
75 */
76static bool xenbus_get_reply(struct xsd_sockmsg **req_reply)
77{
78 struct xsd_sockmsg msg;
79 unsigned int prod = xenstore_buf->rsp_prod;
80
81again:
82 if (!wait_event_timeout(NULL, prod != xenstore_buf->rsp_prod,
83 WAIT_XENBUS_TO_MS)) {
84 printk("%s: wait_event timeout\n", __func__);
85 return false;
86 }
87
88 prod = xenstore_buf->rsp_prod;
89 if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
90 goto again;
91
92 rmb();
93 memcpy_from_ring(xenstore_buf->rsp, &msg,
94 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
95 sizeof(msg));
96
97 if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg) + msg.len)
98 goto again;
99
100 /* We do not support and expect any Xen bus wathes. */
101 BUG_ON(msg.type == XS_WATCH_EVENT);
102
103 *req_reply = malloc(sizeof(msg) + msg.len);
104 memcpy_from_ring(xenstore_buf->rsp, *req_reply,
105 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
106 msg.len + sizeof(msg));
107 mb();
108 xenstore_buf->rsp_cons += msg.len + sizeof(msg);
109
110 wmb();
111 notify_remote_via_evtchn(xenbus_evtchn);
112 return true;
113}
114
115char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path,
116 XenbusState state)
117{
118 char *current_state;
119 char *msg = NULL;
120 char *msg2 = NULL;
121 char value[2];
122 XenbusState rs;
123 int xbt_flag = 0;
124 int retry = 0;
125
126 do {
127 if (xbt == XBT_NIL) {
128 msg = xenbus_transaction_start(&xbt);
129 if (msg)
130 goto exit;
131 xbt_flag = 1;
132 }
133
134 msg = xenbus_read(xbt, path, &current_state);
135 if (msg)
136 goto exit;
137
138 rs = (XenbusState)(current_state[0] - '0');
139 free(current_state);
140 if (rs == state) {
141 msg = NULL;
142 goto exit;
143 }
144
145 snprintf(value, 2, "%d", state);
146 msg = xenbus_write(xbt, path, value);
147
148exit:
149 if (xbt_flag) {
150 msg2 = xenbus_transaction_end(xbt, 0, &retry);
151 xbt = XBT_NIL;
152 }
153 if (msg == NULL && msg2 != NULL)
154 msg = msg2;
155 else
156 free(msg2);
157 } while (retry);
158
159 return msg;
160}
161
162char *xenbus_wait_for_state_change(const char *path, XenbusState *state)
163{
164 for (;;) {
165 char *res, *msg;
166 XenbusState rs;
167
168 msg = xenbus_read(XBT_NIL, path, &res);
169 if (msg)
170 return msg;
171
172 rs = (XenbusState)(res[0] - 48);
173 free(res);
174
175 if (rs == *state) {
176 wait_event_timeout(NULL, false, WAIT_XENBUS_POLL_TO_MS);
177 } else {
178 *state = rs;
179 break;
180 }
181 }
182 return NULL;
183}
184
185/* Send data to xenbus. This can block. All of the requests are seen
186 * by xenbus as if sent atomically. The header is added
187 * automatically, using type %type, req_id %req_id, and trans_id
188 * %trans_id.
189 */
190static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
191 const struct write_req *req, int nr_reqs)
192{
193 XENSTORE_RING_IDX prod;
194 int r;
195 int len = 0;
196 const struct write_req *cur_req;
197 int req_off;
198 int total_off;
199 int this_chunk;
200 struct xsd_sockmsg m = {
201 .type = type,
202 .req_id = req_id,
203 .tx_id = trans_id
204 };
205 struct write_req header_req = {
206 &m,
207 sizeof(m)
208 };
209
210 for (r = 0; r < nr_reqs; r++)
211 len += req[r].len;
212 m.len = len;
213 len += sizeof(m);
214
215 cur_req = &header_req;
216
217 BUG_ON(len > XENSTORE_RING_SIZE);
218 prod = xenstore_buf->req_prod;
219 /* We are running synchronously, so it is a bug if we do not
220 * have enough room to send a message: please note that a message
221 * can occupy multiple slots in the ring buffer.
222 */
223 BUG_ON(prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE);
224
225 total_off = 0;
226 req_off = 0;
227 while (total_off < len) {
228 this_chunk = min(cur_req->len - req_off,
229 XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
230 memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
231 (char *)cur_req->data + req_off, this_chunk);
232 prod += this_chunk;
233 req_off += this_chunk;
234 total_off += this_chunk;
235 if (req_off == cur_req->len) {
236 req_off = 0;
237 if (cur_req == &header_req)
238 cur_req = req;
239 else
240 cur_req++;
241 }
242 }
243
244 BUG_ON(req_off != 0);
245 BUG_ON(total_off != len);
246 BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
247
248 /* Remote must see entire message before updating indexes */
249 wmb();
250
251 xenstore_buf->req_prod += len;
252
253 /* Send evtchn to notify remote */
254 notify_remote_via_evtchn(xenbus_evtchn);
255}
256
257/* Send a message to xenbus, in the same fashion as xb_write, and
258 * block waiting for a reply. The reply is malloced and should be
259 * freed by the caller.
260 */
261struct xsd_sockmsg *xenbus_msg_reply(int type,
262 xenbus_transaction_t trans,
263 struct write_req *io,
264 int nr_reqs)
265{
266 struct xsd_sockmsg *rep;
267
268 /* We do not use request identifier which is echoed in daemon's response. */
269 xb_write(type, 0, trans, io, nr_reqs);
270 /* Now wait for the message to arrive. */
271 if (!xenbus_get_reply(&rep))
272 return NULL;
273 return rep;
274}
275
276static char *errmsg(struct xsd_sockmsg *rep)
277{
278 char *res;
279
280 if (!rep) {
281 char msg[] = "No reply";
282 size_t len = strlen(msg) + 1;
283
284 return memcpy(malloc(len), msg, len);
285 }
286 if (rep->type != XS_ERROR)
287 return NULL;
288 res = malloc(rep->len + 1);
289 memcpy(res, rep + 1, rep->len);
290 res[rep->len] = 0;
291 free(rep);
292 return res;
293}
294
295/* List the contents of a directory. Returns a malloc()ed array of
296 * pointers to malloc()ed strings. The array is NULL terminated. May
297 * block.
298 */
299char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
300{
301 struct xsd_sockmsg *reply, *repmsg;
302 struct write_req req[] = { { pre, strlen(pre) + 1 } };
303 int nr_elems, x, i;
304 char **res, *msg;
305
306 repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
307 msg = errmsg(repmsg);
308 if (msg) {
309 *contents = NULL;
310 return msg;
311 }
312 reply = repmsg + 1;
313 for (x = nr_elems = 0; x < repmsg->len; x++)
314 nr_elems += (((char *)reply)[x] == 0);
315 res = malloc(sizeof(res[0]) * (nr_elems + 1));
316 for (x = i = 0; i < nr_elems; i++) {
317 int l = strlen((char *)reply + x);
318
319 res[i] = malloc(l + 1);
320 memcpy(res[i], (char *)reply + x, l + 1);
321 x += l + 1;
322 }
323 res[i] = NULL;
324 free(repmsg);
325 *contents = res;
326 return NULL;
327}
328
329char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
330{
331 struct write_req req[] = { {path, strlen(path) + 1} };
332 struct xsd_sockmsg *rep;
333 char *res, *msg;
334
335 rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
336 msg = errmsg(rep);
337 if (msg) {
338 *value = NULL;
339 return msg;
340 }
341 res = malloc(rep->len + 1);
342 memcpy(res, rep + 1, rep->len);
343 res[rep->len] = 0;
344 free(rep);
345 *value = res;
346 return NULL;
347}
348
349char *xenbus_write(xenbus_transaction_t xbt, const char *path,
350 const char *value)
351{
352 struct write_req req[] = {
353 {path, strlen(path) + 1},
354 {value, strlen(value)},
355 };
356 struct xsd_sockmsg *rep;
357 char *msg;
358
359 rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
360 msg = errmsg(rep);
361 if (msg)
362 return msg;
363 free(rep);
364 return NULL;
365}
366
367char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
368{
369 struct write_req req[] = { {path, strlen(path) + 1} };
370 struct xsd_sockmsg *rep;
371 char *msg;
372
373 rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
374 msg = errmsg(rep);
375 if (msg)
376 return msg;
377 free(rep);
378 return NULL;
379}
380
381char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
382{
383 struct write_req req[] = { {path, strlen(path) + 1} };
384 struct xsd_sockmsg *rep;
385 char *res, *msg;
386
387 rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
388 msg = errmsg(rep);
389 if (msg) {
390 *value = NULL;
391 return msg;
392 }
393 res = malloc(rep->len + 1);
394 memcpy(res, rep + 1, rep->len);
395 res[rep->len] = 0;
396 free(rep);
397 *value = res;
398 return NULL;
399}
400
401#define PERM_MAX_SIZE 32
402char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path,
403 domid_t dom, char perm)
404{
405 char value[PERM_MAX_SIZE];
406 struct write_req req[] = {
407 {path, strlen(path) + 1},
408 {value, 0},
409 };
410 struct xsd_sockmsg *rep;
411 char *msg;
412
413 snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
414 req[1].len = strlen(value) + 1;
415 rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
416 msg = errmsg(rep);
417 if (msg)
418 return msg;
419 free(rep);
420 return NULL;
421}
422
423char *xenbus_transaction_start(xenbus_transaction_t *xbt)
424{
425 /* Xenstored becomes angry if you send a length 0 message, so just
426 * shove a nul terminator on the end
427 */
428 struct write_req req = { "", 1};
429 struct xsd_sockmsg *rep;
430 char *err;
431
432 rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
433 err = errmsg(rep);
434 if (err)
435 return err;
436 sscanf((char *)(rep + 1), "%lu", xbt);
437 free(rep);
438 return NULL;
439}
440
441char *xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
442{
443 struct xsd_sockmsg *rep;
444 struct write_req req;
445 char *err;
446
447 *retry = 0;
448
449 req.data = abort ? "F" : "T";
450 req.len = 2;
451 rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
452 err = errmsg(rep);
453 if (err) {
454 if (!strcmp(err, "EAGAIN")) {
455 *retry = 1;
456 free(err);
457 return NULL;
458 } else {
459 return err;
460 }
461 }
462 free(rep);
463 return NULL;
464}
465
466int xenbus_read_integer(const char *path)
467{
468 char *res, *buf;
469 int t;
470
471 res = xenbus_read(XBT_NIL, path, &buf);
472 if (res) {
473 printk("Failed to read %s.\n", path);
474 free(res);
475 return -1;
476 }
477 sscanf(buf, "%d", &t);
478 free(buf);
479 return t;
480}
481
482int xenbus_read_uuid(const char *path, unsigned char uuid[16])
483{
484 char *res, *buf;
485
486 res = xenbus_read(XBT_NIL, path, &buf);
487 if (res) {
488 printk("Failed to read %s.\n", path);
489 free(res);
490 return 0;
491 }
492 if (strlen(buf) != ((2 * 16) + 4) /* 16 hex bytes and 4 hyphens */
493 || sscanf(buf,
494 "%2hhx%2hhx%2hhx%2hhx-"
495 "%2hhx%2hhx-"
496 "%2hhx%2hhx-"
497 "%2hhx%2hhx-"
498 "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
499 uuid, uuid + 1, uuid + 2, uuid + 3,
500 uuid + 4, uuid + 5, uuid + 6, uuid + 7,
501 uuid + 8, uuid + 9, uuid + 10, uuid + 11,
502 uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
503 printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
504 free(buf);
505 return 0;
506 }
507 free(buf);
508 return 1;
509}
510
511char *xenbus_printf(xenbus_transaction_t xbt,
512 const char *node, const char *path,
513 const char *fmt, ...)
514{
515#define BUFFER_SIZE 256
516 char fullpath[BUFFER_SIZE];
517 char val[BUFFER_SIZE];
518 va_list args;
519
520 BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
521 sprintf(fullpath, "%s/%s", node, path);
522 va_start(args, fmt);
523 vsprintf(val, fmt, args);
524 va_end(args);
525 return xenbus_write(xbt, fullpath, val);
526}
527
528domid_t xenbus_get_self_id(void)
529{
530 char *dom_id;
531 domid_t ret;
532
533 BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
534 sscanf(dom_id, "%"SCNd16, &ret);
535
536 return ret;
537}
538
539void init_xenbus(void)
540{
541 u64 v;
542
543 debug("%s\n", __func__);
544 if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v))
545 BUG();
546 xenbus_evtchn = v;
547
548 if (hvm_get_parameter(HVM_PARAM_STORE_PFN, &v))
549 BUG();
550 xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v);
551}
552
553void fini_xenbus(void)
554{
555 debug("%s\n", __func__);
556}