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