xref: /openbmc/qemu/hw/xen/xen-operations.c (revision 4f65e89f8cf0e079b4ec3ddfede314bbb4e35c76)
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