| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QEMU Xen backend support: Operations for true Xen | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Authors: David Woodhouse <dwmw2@infradead.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This work is licensed under the terms of the GNU GPL, version 2 or later. | 
					
						
							|  |  |  |  * See the COPYING file in the top-level directory. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-02 11:05:16 +00:00
										 |  |  | #include "qemu/uuid.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 00:39:13 +00:00
										 |  |  | #include "hw/xen/xen_native.h"
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | #include "hw/xen/xen_backend_ops.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * If we have new enough libxenctrl then we do not want/need these compat | 
					
						
							|  |  |  |  * interfaces, despite what the user supplied cflags might say. They | 
					
						
							|  |  |  |  * must be undefined before including xenctrl.h | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #undef XC_WANT_COMPAT_EVTCHN_API
 | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | #undef XC_WANT_COMPAT_GNTTAB_API
 | 
					
						
							| 
									
										
										
										
											2023-01-02 01:13:46 +00:00
										 |  |  | #undef XC_WANT_COMPAT_MAP_FOREIGN_API
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <xenctrl.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-04-12 19:51:00 +01:00
										 |  |  |  * We don't support Xen prior to 4.7.1. | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <xenevtchn.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | #include <xengnttab.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-02 01:13:46 +00:00
										 |  |  | #include <xenforeignmemory.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | /* Xen before 4.8 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int libxengnttab_fallback_grant_copy(xengnttab_handle *xgt, | 
					
						
							|  |  |  |                                             bool to_domain, uint32_t domid, | 
					
						
							|  |  |  |                                             XenGrantCopySegment segs[], | 
					
						
							|  |  |  |                                             unsigned int nr_segs, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t *refs = g_new(uint32_t, nr_segs); | 
					
						
							|  |  |  |     int prot = to_domain ? PROT_WRITE : PROT_READ; | 
					
						
							|  |  |  |     void *map; | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							|  |  |  |     int rc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nr_segs; i++) { | 
					
						
							|  |  |  |         XenGrantCopySegment *seg = &segs[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         refs[i] = to_domain ? seg->dest.foreign.ref : | 
					
						
							|  |  |  |             seg->source.foreign.ref; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     map = xengnttab_map_domain_grant_refs(xgt, nr_segs, domid, refs, prot); | 
					
						
							|  |  |  |     if (!map) { | 
					
						
							|  |  |  |         if (errp) { | 
					
						
							|  |  |  |             error_setg_errno(errp, errno, | 
					
						
							|  |  |  |                              "xengnttab_map_domain_grant_refs failed"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         rc = -errno; | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nr_segs; i++) { | 
					
						
							|  |  |  |         XenGrantCopySegment *seg = &segs[i]; | 
					
						
							|  |  |  |         void *page = map + (i * XEN_PAGE_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (to_domain) { | 
					
						
							|  |  |  |             memcpy(page + seg->dest.foreign.offset, seg->source.virt, | 
					
						
							|  |  |  |                    seg->len); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             memcpy(seg->dest.virt, page + seg->source.foreign.offset, | 
					
						
							|  |  |  |                    seg->len); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (xengnttab_unmap(xgt, map, nr_segs)) { | 
					
						
							|  |  |  |         if (errp) { | 
					
						
							|  |  |  |             error_setg_errno(errp, errno, "xengnttab_unmap failed"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         rc = -errno; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     g_free(refs); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40800
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int libxengnttab_backend_grant_copy(xengnttab_handle *xgt, | 
					
						
							|  |  |  |                                            bool to_domain, uint32_t domid, | 
					
						
							|  |  |  |                                            XenGrantCopySegment *segs, | 
					
						
							|  |  |  |                                            uint32_t nr_segs, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     xengnttab_grant_copy_segment_t *xengnttab_segs; | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							|  |  |  |     int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nr_segs; i++) { | 
					
						
							|  |  |  |         XenGrantCopySegment *seg = &segs[i]; | 
					
						
							|  |  |  |         xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (to_domain) { | 
					
						
							|  |  |  |             xengnttab_seg->flags = GNTCOPY_dest_gref; | 
					
						
							|  |  |  |             xengnttab_seg->dest.foreign.domid = domid; | 
					
						
							|  |  |  |             xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref; | 
					
						
							|  |  |  |             xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset; | 
					
						
							|  |  |  |             xengnttab_seg->source.virt = seg->source.virt; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             xengnttab_seg->flags = GNTCOPY_source_gref; | 
					
						
							|  |  |  |             xengnttab_seg->source.foreign.domid = domid; | 
					
						
							|  |  |  |             xengnttab_seg->source.foreign.ref = seg->source.foreign.ref; | 
					
						
							|  |  |  |             xengnttab_seg->source.foreign.offset = | 
					
						
							|  |  |  |                 seg->source.foreign.offset; | 
					
						
							|  |  |  |             xengnttab_seg->dest.virt = seg->dest.virt; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         xengnttab_seg->len = seg->len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (xengnttab_grant_copy(xgt, nr_segs, xengnttab_segs)) { | 
					
						
							|  |  |  |         if (errp) { | 
					
						
							|  |  |  |             error_setg_errno(errp, errno, "xengnttab_grant_copy failed"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         rc = -errno; | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rc = 0; | 
					
						
							|  |  |  |     for (i = 0; i < nr_segs; i++) { | 
					
						
							|  |  |  |         xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (xengnttab_seg->status != GNTST_okay) { | 
					
						
							|  |  |  |             if (errp) { | 
					
						
							|  |  |  |                 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             rc = -EIO; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     g_free(xengnttab_segs); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | static xenevtchn_handle *libxenevtchn_backend_open(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xenevtchn_open(NULL, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct evtchn_backend_ops libxenevtchn_backend_ops = { | 
					
						
							|  |  |  |     .open = libxenevtchn_backend_open, | 
					
						
							|  |  |  |     .close = xenevtchn_close, | 
					
						
							|  |  |  |     .bind_interdomain = xenevtchn_bind_interdomain, | 
					
						
							|  |  |  |     .unbind = xenevtchn_unbind, | 
					
						
							|  |  |  |     .get_fd = xenevtchn_fd, | 
					
						
							|  |  |  |     .notify = xenevtchn_notify, | 
					
						
							|  |  |  |     .unmask = xenevtchn_unmask, | 
					
						
							|  |  |  |     .pending = xenevtchn_pending, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | static xengnttab_handle *libxengnttab_backend_open(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xengnttab_open(NULL, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-10 00:03:49 +00:00
										 |  |  | static int libxengnttab_backend_unmap(xengnttab_handle *xgt, | 
					
						
							|  |  |  |                                       void *start_address, uint32_t *refs, | 
					
						
							|  |  |  |                                       uint32_t count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xengnttab_unmap(xgt, start_address, count); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct gnttab_backend_ops libxengnttab_backend_ops = { | 
					
						
							|  |  |  |     .features = XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE, | 
					
						
							|  |  |  |     .open = libxengnttab_backend_open, | 
					
						
							|  |  |  |     .close = xengnttab_close, | 
					
						
							|  |  |  |     .grant_copy = libxengnttab_fallback_grant_copy, | 
					
						
							|  |  |  |     .set_max_grants = xengnttab_set_max_grants, | 
					
						
							|  |  |  |     .map_refs = xengnttab_map_domain_grant_refs, | 
					
						
							| 
									
										
										
										
											2023-01-10 00:03:49 +00:00
										 |  |  |     .unmap = libxengnttab_backend_unmap, | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 01:13:46 +00:00
										 |  |  | static void *libxenforeignmem_backend_map(uint32_t dom, void *addr, int prot, | 
					
						
							|  |  |  |                                           size_t pages, xen_pfn_t *pfns, | 
					
						
							|  |  |  |                                           int *errs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xenforeignmemory_map2(xen_fmem, dom, addr, prot, 0, pages, pfns, | 
					
						
							|  |  |  |                                  errs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int libxenforeignmem_backend_unmap(void *addr, size_t pages) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xenforeignmemory_unmap(xen_fmem, addr, pages); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct foreignmem_backend_ops libxenforeignmem_backend_ops = { | 
					
						
							|  |  |  |     .map = libxenforeignmem_backend_map, | 
					
						
							|  |  |  |     .unmap = libxenforeignmem_backend_unmap, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 11:05:16 +00:00
										 |  |  | struct qemu_xs_handle { | 
					
						
							|  |  |  |     struct xs_handle *xsh; | 
					
						
							|  |  |  |     NotifierList notifiers; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void watch_event(void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct qemu_xs_handle *h = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         char **v = xs_check_watch(h->xsh); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!v) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         notifier_list_notify(&h->notifiers, v); | 
					
						
							|  |  |  |         free(v); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct qemu_xs_handle *libxenstore_open(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct xs_handle *xsh = xs_open(0); | 
					
						
							| 
									
										
										
										
											2023-04-12 19:50:59 +01:00
										 |  |  |     struct qemu_xs_handle *h; | 
					
						
							| 
									
										
										
										
											2023-01-02 11:05:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!xsh) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     h = g_new0(struct qemu_xs_handle, 1); | 
					
						
							|  |  |  |     h->xsh = xsh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     notifier_list_init(&h->notifiers); | 
					
						
							|  |  |  |     qemu_set_fd_handler(xs_fileno(h->xsh), watch_event, NULL, h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void libxenstore_close(struct qemu_xs_handle *h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     g_assert(notifier_list_empty(&h->notifiers)); | 
					
						
							|  |  |  |     qemu_set_fd_handler(xs_fileno(h->xsh), NULL, NULL, NULL); | 
					
						
							|  |  |  |     xs_close(h->xsh); | 
					
						
							|  |  |  |     g_free(h); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *libxenstore_get_domain_path(struct qemu_xs_handle *h, | 
					
						
							|  |  |  |                                          unsigned int domid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_get_domain_path(h->xsh, domid); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char **libxenstore_directory(struct qemu_xs_handle *h, | 
					
						
							|  |  |  |                                     xs_transaction_t t, const char *path, | 
					
						
							|  |  |  |                                     unsigned int *num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_directory(h->xsh, t, path, num); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *libxenstore_read(struct qemu_xs_handle *h, xs_transaction_t t, | 
					
						
							|  |  |  |                               const char *path, unsigned int *len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_read(h->xsh, t, path, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool libxenstore_write(struct qemu_xs_handle *h, xs_transaction_t t, | 
					
						
							|  |  |  |                               const char *path, const void *data, | 
					
						
							|  |  |  |                               unsigned int len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_write(h->xsh, t, path, data, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool libxenstore_create(struct qemu_xs_handle *h, xs_transaction_t t, | 
					
						
							|  |  |  |                                unsigned int owner, unsigned int domid, | 
					
						
							|  |  |  |                                unsigned int perms, const char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct xs_permissions perms_list[] = { | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             .id    = owner, | 
					
						
							|  |  |  |             .perms = XS_PERM_NONE, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             .id    = domid, | 
					
						
							|  |  |  |             .perms = perms, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!xs_mkdir(h->xsh, t, path)) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return xs_set_permissions(h->xsh, t, path, perms_list, | 
					
						
							|  |  |  |                               ARRAY_SIZE(perms_list)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool libxenstore_destroy(struct qemu_xs_handle *h, xs_transaction_t t, | 
					
						
							|  |  |  |                                 const char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_rm(h->xsh, t, path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct qemu_xs_watch { | 
					
						
							|  |  |  |     char *path; | 
					
						
							|  |  |  |     char *token; | 
					
						
							|  |  |  |     xs_watch_fn fn; | 
					
						
							|  |  |  |     void *opaque; | 
					
						
							|  |  |  |     Notifier notifier; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void watch_notify(Notifier *n, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct qemu_xs_watch *w = container_of(n, struct qemu_xs_watch, notifier); | 
					
						
							|  |  |  |     const char **v = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!strcmp(w->token, v[XS_WATCH_TOKEN])) { | 
					
						
							|  |  |  |         w->fn(w->opaque, v[XS_WATCH_PATH]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct qemu_xs_watch *new_watch(const char *path, xs_watch_fn fn, | 
					
						
							|  |  |  |                                        void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct qemu_xs_watch *w = g_new0(struct qemu_xs_watch, 1); | 
					
						
							|  |  |  |     QemuUUID uuid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qemu_uuid_generate(&uuid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     w->token = qemu_uuid_unparse_strdup(&uuid); | 
					
						
							|  |  |  |     w->path = g_strdup(path); | 
					
						
							|  |  |  |     w->fn = fn; | 
					
						
							|  |  |  |     w->opaque = opaque; | 
					
						
							|  |  |  |     w->notifier.notify = watch_notify; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return w; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_watch(struct qemu_xs_watch *w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     g_free(w->token); | 
					
						
							|  |  |  |     g_free(w->path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_free(w); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct qemu_xs_watch *libxenstore_watch(struct qemu_xs_handle *h, | 
					
						
							|  |  |  |                                                const char *path, xs_watch_fn fn, | 
					
						
							|  |  |  |                                                void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct qemu_xs_watch *w = new_watch(path, fn, opaque); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     notifier_list_add(&h->notifiers, &w->notifier); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!xs_watch(h->xsh, path, w->token)) { | 
					
						
							|  |  |  |         notifier_remove(&w->notifier); | 
					
						
							|  |  |  |         free_watch(w); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return w; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void libxenstore_unwatch(struct qemu_xs_handle *h, | 
					
						
							|  |  |  |                                 struct qemu_xs_watch *w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     xs_unwatch(h->xsh, w->path, w->token); | 
					
						
							|  |  |  |     notifier_remove(&w->notifier); | 
					
						
							|  |  |  |     free_watch(w); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static xs_transaction_t libxenstore_transaction_start(struct qemu_xs_handle *h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_transaction_start(h->xsh); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool libxenstore_transaction_end(struct qemu_xs_handle *h, | 
					
						
							|  |  |  |                                         xs_transaction_t t, bool abort) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return xs_transaction_end(h->xsh, t, abort); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct xenstore_backend_ops libxenstore_backend_ops = { | 
					
						
							|  |  |  |     .open = libxenstore_open, | 
					
						
							|  |  |  |     .close = libxenstore_close, | 
					
						
							|  |  |  |     .get_domain_path = libxenstore_get_domain_path, | 
					
						
							|  |  |  |     .directory = libxenstore_directory, | 
					
						
							|  |  |  |     .read = libxenstore_read, | 
					
						
							|  |  |  |     .write = libxenstore_write, | 
					
						
							|  |  |  |     .create = libxenstore_create, | 
					
						
							|  |  |  |     .destroy = libxenstore_destroy, | 
					
						
							|  |  |  |     .watch = libxenstore_watch, | 
					
						
							|  |  |  |     .unwatch = libxenstore_unwatch, | 
					
						
							|  |  |  |     .transaction_start = libxenstore_transaction_start, | 
					
						
							|  |  |  |     .transaction_end = libxenstore_transaction_end, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | void setup_xen_backend_ops(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  | #if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40800
 | 
					
						
							|  |  |  |     xengnttab_handle *xgt = xengnttab_open(NULL, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (xgt) { | 
					
						
							|  |  |  |         if (xengnttab_grant_copy(xgt, 0, NULL) == 0) { | 
					
						
							|  |  |  |             libxengnttab_backend_ops.grant_copy = libxengnttab_backend_grant_copy; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         xengnttab_close(xgt); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  |     xen_evtchn_ops = &libxenevtchn_backend_ops; | 
					
						
							| 
									
										
										
										
											2023-01-01 21:31:37 +00:00
										 |  |  |     xen_gnttab_ops = &libxengnttab_backend_ops; | 
					
						
							| 
									
										
										
										
											2023-01-02 01:13:46 +00:00
										 |  |  |     xen_foreignmem_ops = &libxenforeignmem_backend_ops; | 
					
						
							| 
									
										
										
										
											2023-01-02 11:05:16 +00:00
										 |  |  |     xen_xenstore_ops = &libxenstore_backend_ops; | 
					
						
							| 
									
										
										
										
											2023-01-01 17:54:41 +00:00
										 |  |  | } |