xen-operations.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. * QEMU Xen backend support: Operations for true Xen
  3. *
  4. * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  5. *
  6. * Authors: David Woodhouse <dwmw2@infradead.org>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  9. * See the COPYING file in the top-level directory.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/uuid.h"
  13. #include "qapi/error.h"
  14. #include "hw/xen/xen_native.h"
  15. #include "hw/xen/xen_backend_ops.h"
  16. /*
  17. * If we have new enough libxenctrl then we do not want/need these compat
  18. * interfaces, despite what the user supplied cflags might say. They
  19. * must be undefined before including xenctrl.h
  20. */
  21. #undef XC_WANT_COMPAT_EVTCHN_API
  22. #undef XC_WANT_COMPAT_GNTTAB_API
  23. #undef XC_WANT_COMPAT_MAP_FOREIGN_API
  24. #include <xenctrl.h>
  25. /*
  26. * We don't support Xen prior to 4.2.0.
  27. */
  28. /* Xen 4.2 through 4.6 */
  29. #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40701
  30. typedef xc_evtchn xenevtchn_handle;
  31. typedef evtchn_port_or_error_t xenevtchn_port_or_error_t;
  32. #define xenevtchn_open(l, f) xc_evtchn_open(l, f);
  33. #define xenevtchn_close(h) xc_evtchn_close(h)
  34. #define xenevtchn_fd(h) xc_evtchn_fd(h)
  35. #define xenevtchn_pending(h) xc_evtchn_pending(h)
  36. #define xenevtchn_notify(h, p) xc_evtchn_notify(h, p)
  37. #define xenevtchn_bind_interdomain(h, d, p) xc_evtchn_bind_interdomain(h, d, p)
  38. #define xenevtchn_unmask(h, p) xc_evtchn_unmask(h, p)
  39. #define xenevtchn_unbind(h, p) xc_evtchn_unbind(h, p)
  40. typedef xc_gnttab xengnttab_handle;
  41. #define xengnttab_open(l, f) xc_gnttab_open(l, f)
  42. #define xengnttab_close(h) xc_gnttab_close(h)
  43. #define xengnttab_set_max_grants(h, n) xc_gnttab_set_max_grants(h, n)
  44. #define xengnttab_map_grant_ref(h, d, r, p) xc_gnttab_map_grant_ref(h, d, r, p)
  45. #define xengnttab_unmap(h, a, n) xc_gnttab_munmap(h, a, n)
  46. #define xengnttab_map_grant_refs(h, c, d, r, p) \
  47. xc_gnttab_map_grant_refs(h, c, d, r, p)
  48. #define xengnttab_map_domain_grant_refs(h, c, d, r, p) \
  49. xc_gnttab_map_domain_grant_refs(h, c, d, r, p)
  50. typedef xc_interface xenforeignmemory_handle;
  51. #else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40701 */
  52. #include <xenevtchn.h>
  53. #include <xengnttab.h>
  54. #include <xenforeignmemory.h>
  55. #endif
  56. /* Xen before 4.8 */
  57. static int libxengnttab_fallback_grant_copy(xengnttab_handle *xgt,
  58. bool to_domain, uint32_t domid,
  59. XenGrantCopySegment segs[],
  60. unsigned int nr_segs, Error **errp)
  61. {
  62. uint32_t *refs = g_new(uint32_t, nr_segs);
  63. int prot = to_domain ? PROT_WRITE : PROT_READ;
  64. void *map;
  65. unsigned int i;
  66. int rc = 0;
  67. for (i = 0; i < nr_segs; i++) {
  68. XenGrantCopySegment *seg = &segs[i];
  69. refs[i] = to_domain ? seg->dest.foreign.ref :
  70. seg->source.foreign.ref;
  71. }
  72. map = xengnttab_map_domain_grant_refs(xgt, nr_segs, domid, refs, prot);
  73. if (!map) {
  74. if (errp) {
  75. error_setg_errno(errp, errno,
  76. "xengnttab_map_domain_grant_refs failed");
  77. }
  78. rc = -errno;
  79. goto done;
  80. }
  81. for (i = 0; i < nr_segs; i++) {
  82. XenGrantCopySegment *seg = &segs[i];
  83. void *page = map + (i * XEN_PAGE_SIZE);
  84. if (to_domain) {
  85. memcpy(page + seg->dest.foreign.offset, seg->source.virt,
  86. seg->len);
  87. } else {
  88. memcpy(seg->dest.virt, page + seg->source.foreign.offset,
  89. seg->len);
  90. }
  91. }
  92. if (xengnttab_unmap(xgt, map, nr_segs)) {
  93. if (errp) {
  94. error_setg_errno(errp, errno, "xengnttab_unmap failed");
  95. }
  96. rc = -errno;
  97. }
  98. done:
  99. g_free(refs);
  100. return rc;
  101. }
  102. #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40800
  103. static int libxengnttab_backend_grant_copy(xengnttab_handle *xgt,
  104. bool to_domain, uint32_t domid,
  105. XenGrantCopySegment *segs,
  106. uint32_t nr_segs, Error **errp)
  107. {
  108. xengnttab_grant_copy_segment_t *xengnttab_segs;
  109. unsigned int i;
  110. int rc;
  111. xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
  112. for (i = 0; i < nr_segs; i++) {
  113. XenGrantCopySegment *seg = &segs[i];
  114. xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
  115. if (to_domain) {
  116. xengnttab_seg->flags = GNTCOPY_dest_gref;
  117. xengnttab_seg->dest.foreign.domid = domid;
  118. xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
  119. xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
  120. xengnttab_seg->source.virt = seg->source.virt;
  121. } else {
  122. xengnttab_seg->flags = GNTCOPY_source_gref;
  123. xengnttab_seg->source.foreign.domid = domid;
  124. xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
  125. xengnttab_seg->source.foreign.offset =
  126. seg->source.foreign.offset;
  127. xengnttab_seg->dest.virt = seg->dest.virt;
  128. }
  129. xengnttab_seg->len = seg->len;
  130. }
  131. if (xengnttab_grant_copy(xgt, nr_segs, xengnttab_segs)) {
  132. if (errp) {
  133. error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
  134. }
  135. rc = -errno;
  136. goto done;
  137. }
  138. rc = 0;
  139. for (i = 0; i < nr_segs; i++) {
  140. xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
  141. if (xengnttab_seg->status != GNTST_okay) {
  142. if (errp) {
  143. error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
  144. }
  145. rc = -EIO;
  146. break;
  147. }
  148. }
  149. done:
  150. g_free(xengnttab_segs);
  151. return rc;
  152. }
  153. #endif
  154. static xenevtchn_handle *libxenevtchn_backend_open(void)
  155. {
  156. return xenevtchn_open(NULL, 0);
  157. }
  158. struct evtchn_backend_ops libxenevtchn_backend_ops = {
  159. .open = libxenevtchn_backend_open,
  160. .close = xenevtchn_close,
  161. .bind_interdomain = xenevtchn_bind_interdomain,
  162. .unbind = xenevtchn_unbind,
  163. .get_fd = xenevtchn_fd,
  164. .notify = xenevtchn_notify,
  165. .unmask = xenevtchn_unmask,
  166. .pending = xenevtchn_pending,
  167. };
  168. static xengnttab_handle *libxengnttab_backend_open(void)
  169. {
  170. return xengnttab_open(NULL, 0);
  171. }
  172. static int libxengnttab_backend_unmap(xengnttab_handle *xgt,
  173. void *start_address, uint32_t *refs,
  174. uint32_t count)
  175. {
  176. return xengnttab_unmap(xgt, start_address, count);
  177. }
  178. static struct gnttab_backend_ops libxengnttab_backend_ops = {
  179. .features = XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE,
  180. .open = libxengnttab_backend_open,
  181. .close = xengnttab_close,
  182. .grant_copy = libxengnttab_fallback_grant_copy,
  183. .set_max_grants = xengnttab_set_max_grants,
  184. .map_refs = xengnttab_map_domain_grant_refs,
  185. .unmap = libxengnttab_backend_unmap,
  186. };
  187. #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40701
  188. static void *libxenforeignmem_backend_map(uint32_t dom, void *addr, int prot,
  189. size_t pages, xfn_pfn_t *pfns,
  190. int *errs)
  191. {
  192. if (errs) {
  193. return xc_map_foreign_bulk(xen_xc, dom, prot, pfns, errs, pages);
  194. } else {
  195. return xc_map_foreign_pages(xen_xc, dom, prot, pfns, pages);
  196. }
  197. }
  198. static int libxenforeignmem_backend_unmap(void *addr, size_t pages)
  199. {
  200. return munmap(addr, pages * XC_PAGE_SIZE);
  201. }
  202. #else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40701 */
  203. static void *libxenforeignmem_backend_map(uint32_t dom, void *addr, int prot,
  204. size_t pages, xen_pfn_t *pfns,
  205. int *errs)
  206. {
  207. return xenforeignmemory_map2(xen_fmem, dom, addr, prot, 0, pages, pfns,
  208. errs);
  209. }
  210. static int libxenforeignmem_backend_unmap(void *addr, size_t pages)
  211. {
  212. return xenforeignmemory_unmap(xen_fmem, addr, pages);
  213. }
  214. #endif
  215. struct foreignmem_backend_ops libxenforeignmem_backend_ops = {
  216. .map = libxenforeignmem_backend_map,
  217. .unmap = libxenforeignmem_backend_unmap,
  218. };
  219. struct qemu_xs_handle {
  220. struct xs_handle *xsh;
  221. NotifierList notifiers;
  222. };
  223. static void watch_event(void *opaque)
  224. {
  225. struct qemu_xs_handle *h = opaque;
  226. for (;;) {
  227. char **v = xs_check_watch(h->xsh);
  228. if (!v) {
  229. break;
  230. }
  231. notifier_list_notify(&h->notifiers, v);
  232. free(v);
  233. }
  234. }
  235. static struct qemu_xs_handle *libxenstore_open(void)
  236. {
  237. struct xs_handle *xsh = xs_open(0);
  238. struct qemu_xs_handle *h = g_new0(struct qemu_xs_handle, 1);
  239. if (!xsh) {
  240. return NULL;
  241. }
  242. h = g_new0(struct qemu_xs_handle, 1);
  243. h->xsh = xsh;
  244. notifier_list_init(&h->notifiers);
  245. qemu_set_fd_handler(xs_fileno(h->xsh), watch_event, NULL, h);
  246. return h;
  247. }
  248. static void libxenstore_close(struct qemu_xs_handle *h)
  249. {
  250. g_assert(notifier_list_empty(&h->notifiers));
  251. qemu_set_fd_handler(xs_fileno(h->xsh), NULL, NULL, NULL);
  252. xs_close(h->xsh);
  253. g_free(h);
  254. }
  255. static char *libxenstore_get_domain_path(struct qemu_xs_handle *h,
  256. unsigned int domid)
  257. {
  258. return xs_get_domain_path(h->xsh, domid);
  259. }
  260. static char **libxenstore_directory(struct qemu_xs_handle *h,
  261. xs_transaction_t t, const char *path,
  262. unsigned int *num)
  263. {
  264. return xs_directory(h->xsh, t, path, num);
  265. }
  266. static void *libxenstore_read(struct qemu_xs_handle *h, xs_transaction_t t,
  267. const char *path, unsigned int *len)
  268. {
  269. return xs_read(h->xsh, t, path, len);
  270. }
  271. static bool libxenstore_write(struct qemu_xs_handle *h, xs_transaction_t t,
  272. const char *path, const void *data,
  273. unsigned int len)
  274. {
  275. return xs_write(h->xsh, t, path, data, len);
  276. }
  277. static bool libxenstore_create(struct qemu_xs_handle *h, xs_transaction_t t,
  278. unsigned int owner, unsigned int domid,
  279. unsigned int perms, const char *path)
  280. {
  281. struct xs_permissions perms_list[] = {
  282. {
  283. .id = owner,
  284. .perms = XS_PERM_NONE,
  285. },
  286. {
  287. .id = domid,
  288. .perms = perms,
  289. },
  290. };
  291. if (!xs_mkdir(h->xsh, t, path)) {
  292. return false;
  293. }
  294. return xs_set_permissions(h->xsh, t, path, perms_list,
  295. ARRAY_SIZE(perms_list));
  296. }
  297. static bool libxenstore_destroy(struct qemu_xs_handle *h, xs_transaction_t t,
  298. const char *path)
  299. {
  300. return xs_rm(h->xsh, t, path);
  301. }
  302. struct qemu_xs_watch {
  303. char *path;
  304. char *token;
  305. xs_watch_fn fn;
  306. void *opaque;
  307. Notifier notifier;
  308. };
  309. static void watch_notify(Notifier *n, void *data)
  310. {
  311. struct qemu_xs_watch *w = container_of(n, struct qemu_xs_watch, notifier);
  312. const char **v = data;
  313. if (!strcmp(w->token, v[XS_WATCH_TOKEN])) {
  314. w->fn(w->opaque, v[XS_WATCH_PATH]);
  315. }
  316. }
  317. static struct qemu_xs_watch *new_watch(const char *path, xs_watch_fn fn,
  318. void *opaque)
  319. {
  320. struct qemu_xs_watch *w = g_new0(struct qemu_xs_watch, 1);
  321. QemuUUID uuid;
  322. qemu_uuid_generate(&uuid);
  323. w->token = qemu_uuid_unparse_strdup(&uuid);
  324. w->path = g_strdup(path);
  325. w->fn = fn;
  326. w->opaque = opaque;
  327. w->notifier.notify = watch_notify;
  328. return w;
  329. }
  330. static void free_watch(struct qemu_xs_watch *w)
  331. {
  332. g_free(w->token);
  333. g_free(w->path);
  334. g_free(w);
  335. }
  336. static struct qemu_xs_watch *libxenstore_watch(struct qemu_xs_handle *h,
  337. const char *path, xs_watch_fn fn,
  338. void *opaque)
  339. {
  340. struct qemu_xs_watch *w = new_watch(path, fn, opaque);
  341. notifier_list_add(&h->notifiers, &w->notifier);
  342. if (!xs_watch(h->xsh, path, w->token)) {
  343. notifier_remove(&w->notifier);
  344. free_watch(w);
  345. return NULL;
  346. }
  347. return w;
  348. }
  349. static void libxenstore_unwatch(struct qemu_xs_handle *h,
  350. struct qemu_xs_watch *w)
  351. {
  352. xs_unwatch(h->xsh, w->path, w->token);
  353. notifier_remove(&w->notifier);
  354. free_watch(w);
  355. }
  356. static xs_transaction_t libxenstore_transaction_start(struct qemu_xs_handle *h)
  357. {
  358. return xs_transaction_start(h->xsh);
  359. }
  360. static bool libxenstore_transaction_end(struct qemu_xs_handle *h,
  361. xs_transaction_t t, bool abort)
  362. {
  363. return xs_transaction_end(h->xsh, t, abort);
  364. }
  365. struct xenstore_backend_ops libxenstore_backend_ops = {
  366. .open = libxenstore_open,
  367. .close = libxenstore_close,
  368. .get_domain_path = libxenstore_get_domain_path,
  369. .directory = libxenstore_directory,
  370. .read = libxenstore_read,
  371. .write = libxenstore_write,
  372. .create = libxenstore_create,
  373. .destroy = libxenstore_destroy,
  374. .watch = libxenstore_watch,
  375. .unwatch = libxenstore_unwatch,
  376. .transaction_start = libxenstore_transaction_start,
  377. .transaction_end = libxenstore_transaction_end,
  378. };
  379. void setup_xen_backend_ops(void)
  380. {
  381. #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40800
  382. xengnttab_handle *xgt = xengnttab_open(NULL, 0);
  383. if (xgt) {
  384. if (xengnttab_grant_copy(xgt, 0, NULL) == 0) {
  385. libxengnttab_backend_ops.grant_copy = libxengnttab_backend_grant_copy;
  386. }
  387. xengnttab_close(xgt);
  388. }
  389. #endif
  390. xen_evtchn_ops = &libxenevtchn_backend_ops;
  391. xen_gnttab_ops = &libxengnttab_backend_ops;
  392. xen_foreignmem_ops = &libxenforeignmem_backend_ops;
  393. xen_xenstore_ops = &libxenstore_backend_ops;
  394. }