xen-9p-backend.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. * Xen 9p backend
  3. *
  4. * Copyright Aporeto 2017
  5. *
  6. * Authors:
  7. * Stefano Stabellini <stefano@aporeto.com>
  8. *
  9. */
  10. #include "qemu/osdep.h"
  11. #include "hw/9pfs/9p.h"
  12. #include "hw/xen/xen-legacy-backend.h"
  13. #include "hw/9pfs/xen-9pfs.h"
  14. #include "qapi/error.h"
  15. #include "qemu/config-file.h"
  16. #include "qemu/main-loop.h"
  17. #include "qemu/option.h"
  18. #include "fsdev/qemu-fsdev.h"
  19. #define VERSIONS "1"
  20. #define MAX_RINGS 8
  21. #define MAX_RING_ORDER 8
  22. typedef struct Xen9pfsRing {
  23. struct Xen9pfsDev *priv;
  24. int ref;
  25. xenevtchn_handle *evtchndev;
  26. int evtchn;
  27. int local_port;
  28. int ring_order;
  29. struct xen_9pfs_data_intf *intf;
  30. unsigned char *data;
  31. struct xen_9pfs_data ring;
  32. struct iovec *sg;
  33. QEMUBH *bh;
  34. /* local copies, so that we can read/write PDU data directly from
  35. * the ring */
  36. RING_IDX out_cons, out_size, in_cons;
  37. bool inprogress;
  38. } Xen9pfsRing;
  39. typedef struct Xen9pfsDev {
  40. struct XenLegacyDevice xendev; /* must be first */
  41. V9fsState state;
  42. char *path;
  43. char *security_model;
  44. char *tag;
  45. char *id;
  46. int num_rings;
  47. Xen9pfsRing *rings;
  48. } Xen9pfsDev;
  49. static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
  50. static void xen_9pfs_in_sg(Xen9pfsRing *ring,
  51. struct iovec *in_sg,
  52. int *num,
  53. uint32_t idx,
  54. uint32_t size)
  55. {
  56. RING_IDX cons, prod, masked_prod, masked_cons;
  57. cons = ring->intf->in_cons;
  58. prod = ring->intf->in_prod;
  59. xen_rmb();
  60. masked_prod = xen_9pfs_mask(prod, XEN_FLEX_RING_SIZE(ring->ring_order));
  61. masked_cons = xen_9pfs_mask(cons, XEN_FLEX_RING_SIZE(ring->ring_order));
  62. if (masked_prod < masked_cons) {
  63. in_sg[0].iov_base = ring->ring.in + masked_prod;
  64. in_sg[0].iov_len = masked_cons - masked_prod;
  65. *num = 1;
  66. } else {
  67. in_sg[0].iov_base = ring->ring.in + masked_prod;
  68. in_sg[0].iov_len = XEN_FLEX_RING_SIZE(ring->ring_order) - masked_prod;
  69. in_sg[1].iov_base = ring->ring.in;
  70. in_sg[1].iov_len = masked_cons;
  71. *num = 2;
  72. }
  73. }
  74. static void xen_9pfs_out_sg(Xen9pfsRing *ring,
  75. struct iovec *out_sg,
  76. int *num,
  77. uint32_t idx)
  78. {
  79. RING_IDX cons, prod, masked_prod, masked_cons;
  80. cons = ring->intf->out_cons;
  81. prod = ring->intf->out_prod;
  82. xen_rmb();
  83. masked_prod = xen_9pfs_mask(prod, XEN_FLEX_RING_SIZE(ring->ring_order));
  84. masked_cons = xen_9pfs_mask(cons, XEN_FLEX_RING_SIZE(ring->ring_order));
  85. if (masked_cons < masked_prod) {
  86. out_sg[0].iov_base = ring->ring.out + masked_cons;
  87. out_sg[0].iov_len = ring->out_size;
  88. *num = 1;
  89. } else {
  90. if (ring->out_size >
  91. (XEN_FLEX_RING_SIZE(ring->ring_order) - masked_cons)) {
  92. out_sg[0].iov_base = ring->ring.out + masked_cons;
  93. out_sg[0].iov_len = XEN_FLEX_RING_SIZE(ring->ring_order) -
  94. masked_cons;
  95. out_sg[1].iov_base = ring->ring.out;
  96. out_sg[1].iov_len = ring->out_size -
  97. (XEN_FLEX_RING_SIZE(ring->ring_order) -
  98. masked_cons);
  99. *num = 2;
  100. } else {
  101. out_sg[0].iov_base = ring->ring.out + masked_cons;
  102. out_sg[0].iov_len = ring->out_size;
  103. *num = 1;
  104. }
  105. }
  106. }
  107. static ssize_t xen_9pfs_pdu_vmarshal(V9fsPDU *pdu,
  108. size_t offset,
  109. const char *fmt,
  110. va_list ap)
  111. {
  112. Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
  113. struct iovec in_sg[2];
  114. int num;
  115. ssize_t ret;
  116. xen_9pfs_in_sg(&xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings],
  117. in_sg, &num, pdu->idx, ROUND_UP(offset + 128, 512));
  118. ret = v9fs_iov_vmarshal(in_sg, num, offset, 0, fmt, ap);
  119. if (ret < 0) {
  120. xen_pv_printf(&xen_9pfs->xendev, 0,
  121. "Failed to encode VirtFS request type %d\n", pdu->id + 1);
  122. xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
  123. xen_9pfs_disconnect(&xen_9pfs->xendev);
  124. }
  125. return ret;
  126. }
  127. static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu,
  128. size_t offset,
  129. const char *fmt,
  130. va_list ap)
  131. {
  132. Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
  133. struct iovec out_sg[2];
  134. int num;
  135. ssize_t ret;
  136. xen_9pfs_out_sg(&xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings],
  137. out_sg, &num, pdu->idx);
  138. ret = v9fs_iov_vunmarshal(out_sg, num, offset, 0, fmt, ap);
  139. if (ret < 0) {
  140. xen_pv_printf(&xen_9pfs->xendev, 0,
  141. "Failed to decode VirtFS request type %d\n", pdu->id);
  142. xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
  143. xen_9pfs_disconnect(&xen_9pfs->xendev);
  144. }
  145. return ret;
  146. }
  147. static void xen_9pfs_init_out_iov_from_pdu(V9fsPDU *pdu,
  148. struct iovec **piov,
  149. unsigned int *pniov,
  150. size_t size)
  151. {
  152. Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
  153. Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings];
  154. int num;
  155. g_free(ring->sg);
  156. ring->sg = g_new0(struct iovec, 2);
  157. xen_9pfs_out_sg(ring, ring->sg, &num, pdu->idx);
  158. *piov = ring->sg;
  159. *pniov = num;
  160. }
  161. static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu,
  162. struct iovec **piov,
  163. unsigned int *pniov,
  164. size_t size)
  165. {
  166. Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
  167. Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings];
  168. int num;
  169. size_t buf_size;
  170. g_free(ring->sg);
  171. ring->sg = g_new0(struct iovec, 2);
  172. xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
  173. buf_size = iov_size(ring->sg, num);
  174. if (buf_size < size) {
  175. xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d"
  176. "needs %zu bytes, buffer has %zu\n", pdu->id, size,
  177. buf_size);
  178. xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
  179. xen_9pfs_disconnect(&xen_9pfs->xendev);
  180. }
  181. *piov = ring->sg;
  182. *pniov = num;
  183. }
  184. static void xen_9pfs_push_and_notify(V9fsPDU *pdu)
  185. {
  186. RING_IDX prod;
  187. Xen9pfsDev *priv = container_of(pdu->s, Xen9pfsDev, state);
  188. Xen9pfsRing *ring = &priv->rings[pdu->tag % priv->num_rings];
  189. g_free(ring->sg);
  190. ring->sg = NULL;
  191. ring->intf->out_cons = ring->out_cons;
  192. xen_wmb();
  193. prod = ring->intf->in_prod;
  194. xen_rmb();
  195. ring->intf->in_prod = prod + pdu->size;
  196. xen_wmb();
  197. ring->inprogress = false;
  198. xenevtchn_notify(ring->evtchndev, ring->local_port);
  199. qemu_bh_schedule(ring->bh);
  200. }
  201. static const V9fsTransport xen_9p_transport = {
  202. .pdu_vmarshal = xen_9pfs_pdu_vmarshal,
  203. .pdu_vunmarshal = xen_9pfs_pdu_vunmarshal,
  204. .init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu,
  205. .init_out_iov_from_pdu = xen_9pfs_init_out_iov_from_pdu,
  206. .push_and_notify = xen_9pfs_push_and_notify,
  207. };
  208. static int xen_9pfs_init(struct XenLegacyDevice *xendev)
  209. {
  210. return 0;
  211. }
  212. static int xen_9pfs_receive(Xen9pfsRing *ring)
  213. {
  214. P9MsgHeader h;
  215. RING_IDX cons, prod, masked_prod, masked_cons, queued;
  216. V9fsPDU *pdu;
  217. if (ring->inprogress) {
  218. return 0;
  219. }
  220. cons = ring->intf->out_cons;
  221. prod = ring->intf->out_prod;
  222. xen_rmb();
  223. queued = xen_9pfs_queued(prod, cons, XEN_FLEX_RING_SIZE(ring->ring_order));
  224. if (queued < sizeof(h)) {
  225. return 0;
  226. }
  227. ring->inprogress = true;
  228. masked_prod = xen_9pfs_mask(prod, XEN_FLEX_RING_SIZE(ring->ring_order));
  229. masked_cons = xen_9pfs_mask(cons, XEN_FLEX_RING_SIZE(ring->ring_order));
  230. xen_9pfs_read_packet((uint8_t *) &h, ring->ring.out, sizeof(h),
  231. masked_prod, &masked_cons,
  232. XEN_FLEX_RING_SIZE(ring->ring_order));
  233. if (queued < le32_to_cpu(h.size_le)) {
  234. return 0;
  235. }
  236. /* cannot fail, because we only handle one request per ring at a time */
  237. pdu = pdu_alloc(&ring->priv->state);
  238. ring->out_size = le32_to_cpu(h.size_le);
  239. ring->out_cons = cons + le32_to_cpu(h.size_le);
  240. pdu_submit(pdu, &h);
  241. return 0;
  242. }
  243. static void xen_9pfs_bh(void *opaque)
  244. {
  245. Xen9pfsRing *ring = opaque;
  246. xen_9pfs_receive(ring);
  247. }
  248. static void xen_9pfs_evtchn_event(void *opaque)
  249. {
  250. Xen9pfsRing *ring = opaque;
  251. evtchn_port_t port;
  252. port = xenevtchn_pending(ring->evtchndev);
  253. xenevtchn_unmask(ring->evtchndev, port);
  254. qemu_bh_schedule(ring->bh);
  255. }
  256. static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
  257. {
  258. Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
  259. int i;
  260. for (i = 0; i < xen_9pdev->num_rings; i++) {
  261. if (xen_9pdev->rings[i].evtchndev != NULL) {
  262. qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev),
  263. NULL, NULL, NULL);
  264. xenevtchn_unbind(xen_9pdev->rings[i].evtchndev,
  265. xen_9pdev->rings[i].local_port);
  266. xen_9pdev->rings[i].evtchndev = NULL;
  267. }
  268. }
  269. }
  270. static int xen_9pfs_free(struct XenLegacyDevice *xendev)
  271. {
  272. Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
  273. int i;
  274. if (xen_9pdev->rings[0].evtchndev != NULL) {
  275. xen_9pfs_disconnect(xendev);
  276. }
  277. for (i = 0; i < xen_9pdev->num_rings; i++) {
  278. if (xen_9pdev->rings[i].data != NULL) {
  279. xen_be_unmap_grant_refs(&xen_9pdev->xendev,
  280. xen_9pdev->rings[i].data,
  281. (1 << xen_9pdev->rings[i].ring_order));
  282. }
  283. if (xen_9pdev->rings[i].intf != NULL) {
  284. xen_be_unmap_grant_refs(&xen_9pdev->xendev,
  285. xen_9pdev->rings[i].intf,
  286. 1);
  287. }
  288. if (xen_9pdev->rings[i].bh != NULL) {
  289. qemu_bh_delete(xen_9pdev->rings[i].bh);
  290. }
  291. }
  292. g_free(xen_9pdev->id);
  293. g_free(xen_9pdev->tag);
  294. g_free(xen_9pdev->path);
  295. g_free(xen_9pdev->security_model);
  296. g_free(xen_9pdev->rings);
  297. return 0;
  298. }
  299. static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
  300. {
  301. Error *err = NULL;
  302. int i;
  303. Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
  304. V9fsState *s = &xen_9pdev->state;
  305. QemuOpts *fsdev;
  306. if (xenstore_read_fe_int(&xen_9pdev->xendev, "num-rings",
  307. &xen_9pdev->num_rings) == -1 ||
  308. xen_9pdev->num_rings > MAX_RINGS || xen_9pdev->num_rings < 1) {
  309. return -1;
  310. }
  311. xen_9pdev->rings = g_new0(Xen9pfsRing, xen_9pdev->num_rings);
  312. for (i = 0; i < xen_9pdev->num_rings; i++) {
  313. char *str;
  314. int ring_order;
  315. xen_9pdev->rings[i].priv = xen_9pdev;
  316. xen_9pdev->rings[i].evtchn = -1;
  317. xen_9pdev->rings[i].local_port = -1;
  318. str = g_strdup_printf("ring-ref%u", i);
  319. if (xenstore_read_fe_int(&xen_9pdev->xendev, str,
  320. &xen_9pdev->rings[i].ref) == -1) {
  321. g_free(str);
  322. goto out;
  323. }
  324. g_free(str);
  325. str = g_strdup_printf("event-channel-%u", i);
  326. if (xenstore_read_fe_int(&xen_9pdev->xendev, str,
  327. &xen_9pdev->rings[i].evtchn) == -1) {
  328. g_free(str);
  329. goto out;
  330. }
  331. g_free(str);
  332. xen_9pdev->rings[i].intf =
  333. xen_be_map_grant_ref(&xen_9pdev->xendev,
  334. xen_9pdev->rings[i].ref,
  335. PROT_READ | PROT_WRITE);
  336. if (!xen_9pdev->rings[i].intf) {
  337. goto out;
  338. }
  339. ring_order = xen_9pdev->rings[i].intf->ring_order;
  340. if (ring_order > MAX_RING_ORDER) {
  341. goto out;
  342. }
  343. xen_9pdev->rings[i].ring_order = ring_order;
  344. xen_9pdev->rings[i].data =
  345. xen_be_map_grant_refs(&xen_9pdev->xendev,
  346. xen_9pdev->rings[i].intf->ref,
  347. (1 << ring_order),
  348. PROT_READ | PROT_WRITE);
  349. if (!xen_9pdev->rings[i].data) {
  350. goto out;
  351. }
  352. xen_9pdev->rings[i].ring.in = xen_9pdev->rings[i].data;
  353. xen_9pdev->rings[i].ring.out = xen_9pdev->rings[i].data +
  354. XEN_FLEX_RING_SIZE(ring_order);
  355. xen_9pdev->rings[i].bh = qemu_bh_new(xen_9pfs_bh, &xen_9pdev->rings[i]);
  356. xen_9pdev->rings[i].out_cons = 0;
  357. xen_9pdev->rings[i].out_size = 0;
  358. xen_9pdev->rings[i].inprogress = false;
  359. xen_9pdev->rings[i].evtchndev = xenevtchn_open(NULL, 0);
  360. if (xen_9pdev->rings[i].evtchndev == NULL) {
  361. goto out;
  362. }
  363. qemu_set_cloexec(xenevtchn_fd(xen_9pdev->rings[i].evtchndev));
  364. xen_9pdev->rings[i].local_port = xenevtchn_bind_interdomain
  365. (xen_9pdev->rings[i].evtchndev,
  366. xendev->dom,
  367. xen_9pdev->rings[i].evtchn);
  368. if (xen_9pdev->rings[i].local_port == -1) {
  369. xen_pv_printf(xendev, 0,
  370. "xenevtchn_bind_interdomain failed port=%d\n",
  371. xen_9pdev->rings[i].evtchn);
  372. goto out;
  373. }
  374. xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
  375. qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev),
  376. xen_9pfs_evtchn_event, NULL, &xen_9pdev->rings[i]);
  377. }
  378. xen_9pdev->security_model = xenstore_read_be_str(xendev, "security_model");
  379. xen_9pdev->path = xenstore_read_be_str(xendev, "path");
  380. xen_9pdev->id = s->fsconf.fsdev_id =
  381. g_strdup_printf("xen9p%d", xendev->dev);
  382. xen_9pdev->tag = s->fsconf.tag = xenstore_read_fe_str(xendev, "tag");
  383. fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
  384. s->fsconf.tag,
  385. 1, NULL);
  386. qemu_opt_set(fsdev, "fsdriver", "local", NULL);
  387. qemu_opt_set(fsdev, "path", xen_9pdev->path, NULL);
  388. qemu_opt_set(fsdev, "security_model", xen_9pdev->security_model, NULL);
  389. qemu_opts_set_id(fsdev, s->fsconf.fsdev_id);
  390. qemu_fsdev_add(fsdev, &err);
  391. if (err) {
  392. error_report_err(err);
  393. }
  394. v9fs_device_realize_common(s, &xen_9p_transport, NULL);
  395. return 0;
  396. out:
  397. xen_9pfs_free(xendev);
  398. return -1;
  399. }
  400. static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
  401. {
  402. xenstore_write_be_str(xendev, "versions", VERSIONS);
  403. xenstore_write_be_int(xendev, "max-rings", MAX_RINGS);
  404. xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
  405. }
  406. struct XenDevOps xen_9pfs_ops = {
  407. .size = sizeof(Xen9pfsDev),
  408. .flags = DEVOPS_FLAG_NEED_GNTDEV,
  409. .alloc = xen_9pfs_alloc,
  410. .init = xen_9pfs_init,
  411. .initialise = xen_9pfs_connect,
  412. .disconnect = xen_9pfs_disconnect,
  413. .free = xen_9pfs_free,
  414. };