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