xenbus.c 12 KB

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