From nobody Tue Feb 10 17:53:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673907673493444.41169287084836; Mon, 16 Jan 2023 14:21:13 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pHXpg-0007W7-P5; Mon, 16 Jan 2023 17:20:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pHXpL-0007Ox-Dh for qemu-devel@nongnu.org; Mon, 16 Jan 2023 17:19:39 -0500 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pHXpE-00070f-SB for qemu-devel@nongnu.org; Mon, 16 Jan 2023 17:19:39 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pHXpL-0098Us-6A; Mon, 16 Jan 2023 22:19:40 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.96 #2 (Red Hat Linux)) id 1pHXp7-004iXP-1U; Mon, 16 Jan 2023 22:19:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=0VqBxEPZUZ0bRM003xs3i5RTQY4oLA+f9mwDx3NhsxI=; b=da0GeSc9OsV0AamXtOlrQFKLMA XToA6IOy9Hf899tGWw/pwoiilMfeEC2xBVTfWD6nEJ/j4XoNYPB4yguSdXG4gfW3pAYaJET6YqL9R tDI+R6OAbAhgmFuGF1BFF+oYbx5JXmnoCFyP08nNJR5Sl6rcCqwD2L/Em4/kXZEURDpzh/XKDX147 3YSGoS81YJ69jIIvYaMfyk6NXA833cpj95JSwwrTQZak21gwKu45SfWydACJ4yRFSN187WoLKBReX 4gqc+xy3XCCzJybrV3PoulS5rx2w5ha80O+UWTueKVx1mmqdmuNjDg1kHc++k1ZSejgL7/WW8126l AjcLyVdg==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , Marcel Apfelbaum , armbru@redhat.com Subject: [RFC PATCH v7bis 03/19] hw/xen: Add gnttab operations to allow redirection to internal emulation Date: Mon, 16 Jan 2023 22:19:03 +0000 Message-Id: <20230116221919.1124201-4-dwmw2@infradead.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230116221919.1124201-1-dwmw2@infradead.org> References: <20230116215805.1123514-1-dwmw2@infradead.org> <20230116221919.1124201-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1236::1; envelope-from=BATV+fb0b8ce1ba8490165fd5+7085+infradead.org+dwmw2@casper.srs.infradead.org; helo=casper.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673907674798100001 Content-Type: text/plain; charset="utf-8" From: David Woodhouse In emulation, mapping more than one grant ref to be virtually contiguous would be fairly difficult. The best way to do it might be to make the ram_block mappings actually backed by a file (shmem or a deleted file, perhaps) so that we can have multiple *shared* mappings of it. But that would be fairly intrusive. Making the backend drivers cope with page *lists* instead of expecting the mapping to be contiguous is also non-trivial, since some structures would actually *cross* page boundaries (e.g. the 32-bit blkif responses which are 12 bytes). So for now, we'll support only single-page mappings in emulation. Signed-off-by: David Woodhouse Signed-off-by: Paul Durrant --- hw/xen/xen-bus.c | 112 ++------------------ hw/xen/xen-legacy-backend.c | 125 ++-------------------- hw/xen/xen-operations.c | 157 ++++++++++++++++++++++++++++ hw/xen/xen_pvdev.c | 2 +- include/hw/xen/xen-bus.h | 3 +- include/hw/xen/xen-legacy-backend.h | 13 +-- include/hw/xen/xen_backend_ops.h | 93 ++++++++++++++++ include/hw/xen/xen_common.h | 39 ------- softmmu/globals.c | 1 + 9 files changed, 273 insertions(+), 272 deletions(-) diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index d0b1ae93da..b247e86f28 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -947,7 +947,7 @@ static void xen_device_frontend_destroy(XenDevice *xend= ev) void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs, Error **errp) { - if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) { + if (qemu_xen_gnttab_set_max_grants(xendev->xgth, nr_refs)) { error_setg_errno(errp, errno, "xengnttab_set_max_grants failed"); } } @@ -956,9 +956,8 @@ void *xen_device_map_grant_refs(XenDevice *xendev, uint= 32_t *refs, unsigned int nr_refs, int prot, Error **errp) { - void *map =3D xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs, - xendev->frontend_id, refs, - prot); + void *map =3D qemu_xen_gnttab_map_refs(xendev->xgth, nr_refs, + xendev->frontend_id, refs, prot); =20 if (!map) { error_setg_errno(errp, errno, @@ -971,109 +970,17 @@ void *xen_device_map_grant_refs(XenDevice *xendev, u= int32_t *refs, void xen_device_unmap_grant_refs(XenDevice *xendev, void *map, unsigned int nr_refs, Error **errp) { - if (xengnttab_unmap(xendev->xgth, map, nr_refs)) { + if (qemu_xen_gnttab_unmap(xendev->xgth, map, nr_refs)) { error_setg_errno(errp, errno, "xengnttab_unmap failed"); } } =20 -static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain, - XenDeviceGrantCopySegment segs[], - unsigned int nr_segs, Error **errp) -{ - uint32_t *refs =3D g_new(uint32_t, nr_segs); - int prot =3D to_domain ? PROT_WRITE : PROT_READ; - void *map; - unsigned int i; - - for (i =3D 0; i < nr_segs; i++) { - XenDeviceGrantCopySegment *seg =3D &segs[i]; - - refs[i] =3D to_domain ? seg->dest.foreign.ref : - seg->source.foreign.ref; - } - - map =3D xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs, - xendev->frontend_id, refs, - prot); - if (!map) { - error_setg_errno(errp, errno, - "xengnttab_map_domain_grant_refs failed"); - goto done; - } - - for (i =3D 0; i < nr_segs; i++) { - XenDeviceGrantCopySegment *seg =3D &segs[i]; - void *page =3D map + (i * XC_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(xendev->xgth, map, nr_segs)) { - error_setg_errno(errp, errno, "xengnttab_unmap failed"); - } - -done: - g_free(refs); -} - void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, XenDeviceGrantCopySegment segs[], unsigned int nr_segs, Error **errp) { - xengnttab_grant_copy_segment_t *xengnttab_segs; - unsigned int i; - - if (!xendev->feature_grant_copy) { - compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp); - return; - } - - xengnttab_segs =3D g_new0(xengnttab_grant_copy_segment_t, nr_segs); - - for (i =3D 0; i < nr_segs; i++) { - XenDeviceGrantCopySegment *seg =3D &segs[i]; - xengnttab_grant_copy_segment_t *xengnttab_seg =3D &xengnttab_segs[= i]; - - if (to_domain) { - xengnttab_seg->flags =3D GNTCOPY_dest_gref; - xengnttab_seg->dest.foreign.domid =3D xendev->frontend_id; - xengnttab_seg->dest.foreign.ref =3D seg->dest.foreign.ref; - xengnttab_seg->dest.foreign.offset =3D seg->dest.foreign.offse= t; - xengnttab_seg->source.virt =3D seg->source.virt; - } else { - xengnttab_seg->flags =3D GNTCOPY_source_gref; - xengnttab_seg->source.foreign.domid =3D xendev->frontend_id; - xengnttab_seg->source.foreign.ref =3D seg->source.foreign.ref; - xengnttab_seg->source.foreign.offset =3D - seg->source.foreign.offset; - xengnttab_seg->dest.virt =3D seg->dest.virt; - } - - xengnttab_seg->len =3D seg->len; - } - - if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) { - error_setg_errno(errp, errno, "xengnttab_grant_copy failed"); - goto done; - } - - for (i =3D 0; i < nr_segs; i++) { - xengnttab_grant_copy_segment_t *xengnttab_seg =3D &xengnttab_segs[= i]; - - if (xengnttab_seg->status !=3D GNTST_okay) { - error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i); - break; - } - } - -done: - g_free(xengnttab_segs); + qemu_xen_gnttab_grant_copy(xendev->xgth, to_domain, xendev->frontend_i= d, + (XenGrantCopySegment *)segs, nr_segs, errp); } =20 struct XenEventChannel { @@ -1235,7 +1142,7 @@ static void xen_device_unrealize(DeviceState *dev) xen_device_backend_destroy(xendev); =20 if (xendev->xgth) { - xengnttab_close(xendev->xgth); + qemu_xen_gnttab_close(xendev->xgth); xendev->xgth =3D NULL; } =20 @@ -1298,15 +1205,12 @@ static void xen_device_realize(DeviceState *dev, Er= ror **errp) =20 xendev->watch_list =3D watch_list_create(xendev->xsh); =20 - xendev->xgth =3D xengnttab_open(NULL, 0); + xendev->xgth =3D qemu_xen_gnttab_open(); if (!xendev->xgth) { error_setg_errno(errp, errno, "failed xengnttab_open"); goto unrealize; } =20 - xendev->feature_grant_copy =3D - (xengnttab_grant_copy(xendev->xgth, 0, NULL) =3D=3D 0); - xen_device_backend_create(xendev, errp); if (*errp) { goto unrealize; diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c index 23e8a6fbd8..88d2ae3f0a 100644 --- a/hw/xen/xen-legacy-backend.c +++ b/hw/xen/xen-legacy-backend.c @@ -43,7 +43,6 @@ struct xs_handle *xenstore; const char *xen_protocol; =20 /* private */ -static bool xen_feature_grant_copy; static int debug; =20 int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node, @@ -113,7 +112,7 @@ void xen_be_set_max_grant_refs(struct XenLegacyDevice *= xendev, { assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); =20 - if (xengnttab_set_max_grants(xendev->gnttabdev, nr_refs)) { + if (qemu_xen_gnttab_set_max_grants(xendev->gnttabdev, nr_refs)) { xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n", strerror(errno)); } @@ -126,8 +125,8 @@ void *xen_be_map_grant_refs(struct XenLegacyDevice *xen= dev, uint32_t *refs, =20 assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); =20 - ptr =3D xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_refs, - xen_domid, refs, prot); + ptr =3D qemu_xen_gnttab_map_refs(xendev->gnttabdev, nr_refs, xen_domid= , refs, + prot); if (!ptr) { xen_pv_printf(xendev, 0, "xengnttab_map_domain_grant_refs failed: %s\n", @@ -142,119 +141,27 @@ void xen_be_unmap_grant_refs(struct XenLegacyDevice = *xendev, void *ptr, { assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); =20 - if (xengnttab_unmap(xendev->gnttabdev, ptr, nr_refs)) { + if (qemu_xen_gnttab_unmap(xendev->gnttabdev, ptr, nr_refs)) { xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n", strerror(errno)); } } =20 -static int compat_copy_grant_refs(struct XenLegacyDevice *xendev, - bool to_domain, - XenGrantCopySegment segs[], - unsigned int nr_segs) -{ - uint32_t *refs =3D g_new(uint32_t, nr_segs); - int prot =3D to_domain ? PROT_WRITE : PROT_READ; - void *pages; - unsigned int i; - - for (i =3D 0; i < nr_segs; i++) { - XenGrantCopySegment *seg =3D &segs[i]; - - refs[i] =3D to_domain ? - seg->dest.foreign.ref : seg->source.foreign.ref; - } - - pages =3D xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_segs, - xen_domid, refs, prot); - if (!pages) { - xen_pv_printf(xendev, 0, - "xengnttab_map_domain_grant_refs failed: %s\n", - strerror(errno)); - g_free(refs); - return -1; - } - - for (i =3D 0; i < nr_segs; i++) { - XenGrantCopySegment *seg =3D &segs[i]; - void *page =3D pages + (i * XC_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(xendev->gnttabdev, pages, nr_segs)) { - xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n", - strerror(errno)); - } - - g_free(refs); - return 0; -} - int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev, bool to_domain, XenGrantCopySegment segs[], unsigned int nr_segs) { - xengnttab_grant_copy_segment_t *xengnttab_segs; - unsigned int i; int rc; =20 assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); =20 - if (!xen_feature_grant_copy) { - return compat_copy_grant_refs(xendev, to_domain, segs, nr_segs); - } - - xengnttab_segs =3D g_new0(xengnttab_grant_copy_segment_t, nr_segs); - - for (i =3D 0; i < nr_segs; i++) { - XenGrantCopySegment *seg =3D &segs[i]; - xengnttab_grant_copy_segment_t *xengnttab_seg =3D &xengnttab_segs[= i]; - - if (to_domain) { - xengnttab_seg->flags =3D GNTCOPY_dest_gref; - xengnttab_seg->dest.foreign.domid =3D xen_domid; - xengnttab_seg->dest.foreign.ref =3D seg->dest.foreign.ref; - xengnttab_seg->dest.foreign.offset =3D seg->dest.foreign.offse= t; - xengnttab_seg->source.virt =3D seg->source.virt; - } else { - xengnttab_seg->flags =3D GNTCOPY_source_gref; - xengnttab_seg->source.foreign.domid =3D xen_domid; - xengnttab_seg->source.foreign.ref =3D seg->source.foreign.ref; - xengnttab_seg->source.foreign.offset =3D - seg->source.foreign.offset; - xengnttab_seg->dest.virt =3D seg->dest.virt; - } - - xengnttab_seg->len =3D seg->len; - } - - rc =3D xengnttab_grant_copy(xendev->gnttabdev, nr_segs, xengnttab_segs= ); - + rc =3D qemu_xen_gnttab_grant_copy(xendev->gnttabdev, to_domain, xen_do= mid, + segs, nr_segs, NULL); if (rc) { - xen_pv_printf(xendev, 0, "xengnttab_copy failed: %s\n", - strerror(errno)); - } - - for (i =3D 0; i < nr_segs; i++) { - xengnttab_grant_copy_segment_t *xengnttab_seg =3D - &xengnttab_segs[i]; - - if (xengnttab_seg->status !=3D GNTST_okay) { - xen_pv_printf(xendev, 0, "segment[%u] status: %d\n", i, - xengnttab_seg->status); - rc =3D -1; - } + xen_pv_printf(xendev, 0, "xengnttab_grant_copy failed: %s\n", + strerror(-rc)); } - - g_free(xengnttab_segs); return rc; } =20 @@ -466,7 +373,7 @@ static int xen_be_try_initialise(struct XenLegacyDevice= *xendev) } =20 if (xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV) { - xendev->gnttabdev =3D xengnttab_open(NULL, 0); + xendev->gnttabdev =3D qemu_xen_gnttab_open(); if (xendev->gnttabdev =3D=3D NULL) { xen_pv_printf(NULL, 0, "can't open gnttab device\n"); return -1; @@ -524,7 +431,7 @@ static void xen_be_disconnect(struct XenLegacyDevice *x= endev, xendev->ops->disconnect(xendev); } if (xendev->gnttabdev) { - xengnttab_close(xendev->gnttabdev); + qemu_xen_gnttab_close(xendev->gnttabdev); xendev->gnttabdev =3D NULL; } if (xendev->be_state !=3D state) { @@ -678,8 +585,6 @@ void xenstore_update_fe(char *watch, struct XenLegacyDe= vice *xendev) =20 int xen_be_init(void) { - xengnttab_handle *gnttabdev; - xenstore =3D xs_daemon_open(); if (!xenstore) { xen_pv_printf(NULL, 0, "can't connect to xenstored\n"); @@ -688,19 +593,11 @@ int xen_be_init(void) =20 qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL); =20 - if (xen_xc =3D=3D NULL || xen_fmem =3D=3D NULL) { + if (xen_evtchn_ops =3D=3D NULL || xen_gnttab_ops =3D=3D NULL) { /* Check if xen_init() have been called */ goto err; } =20 - gnttabdev =3D xengnttab_open(NULL, 0); - if (gnttabdev !=3D NULL) { - if (xengnttab_grant_copy(gnttabdev, 0, NULL) =3D=3D 0) { - xen_feature_grant_copy =3D true; - } - xengnttab_close(gnttabdev); - } - xen_sysdev =3D qdev_new(TYPE_XENSYSDEV); sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal); xen_sysbus =3D qbus_new(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus"); diff --git a/hw/xen/xen-operations.c b/hw/xen/xen-operations.c index 1a959d89e8..eb5fb0a59f 100644 --- a/hw/xen/xen-operations.c +++ b/hw/xen/xen-operations.c @@ -21,6 +21,7 @@ * must be undefined before including xenctrl.h */ #undef XC_WANT_COMPAT_EVTCHN_API +#undef XC_WANT_COMPAT_GNTTAB_API =20 #include =20 @@ -43,12 +44,141 @@ typedef evtchn_port_or_error_t xenevtchn_port_or_error= _t; #define xenevtchn_unmask(h, p) xc_evtchn_unmask(h, p) #define xenevtchn_unbind(h, p) xc_evtchn_unbind(h, p) =20 +typedef xc_gnttab xengnttab_handle; + +#define xengnttab_open(l, f) xc_gnttab_open(l, f) +#define xengnttab_close(h) xc_gnttab_close(h) +#define xengnttab_set_max_grants(h, n) xc_gnttab_set_max_grants(h, n) +#define xengnttab_map_grant_ref(h, d, r, p) xc_gnttab_map_grant_ref(h, d, = r, p) +#define xengnttab_unmap(h, a, n) xc_gnttab_munmap(h, a, n) +#define xengnttab_map_grant_refs(h, c, d, r, p) \ + xc_gnttab_map_grant_refs(h, c, d, r, p) +#define xengnttab_map_domain_grant_refs(h, c, d, r, p) \ + xc_gnttab_map_domain_grant_refs(h, c, d, r, p) + #else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >=3D 40701 */ =20 #include +#include =20 #endif =20 +/* 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 =3D g_new(uint32_t, nr_segs); + int prot =3D to_domain ? PROT_WRITE : PROT_READ; + void *map; + unsigned int i; + int rc =3D 0; + + for (i =3D 0; i < nr_segs; i++) { + XenGrantCopySegment *seg =3D &segs[i]; + + refs[i] =3D to_domain ? seg->dest.foreign.ref : + seg->source.foreign.ref; + } + map =3D xengnttab_map_domain_grant_refs(xgt, nr_segs, domid, refs, pro= t); + if (!map) { + if (errp) { + error_setg_errno(errp, errno, + "xengnttab_map_domain_grant_refs failed"); + } + rc =3D -errno; + goto done; + } + + for (i =3D 0; i < nr_segs; i++) { + XenGrantCopySegment *seg =3D &segs[i]; + void *page =3D 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 =3D -errno; + } + +done: + g_free(refs); + return rc; +} + +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >=3D 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 =3D g_new0(xengnttab_grant_copy_segment_t, nr_segs); + + for (i =3D 0; i < nr_segs; i++) { + XenGrantCopySegment *seg =3D &segs[i]; + xengnttab_grant_copy_segment_t *xengnttab_seg =3D &xengnttab_segs[= i]; + + if (to_domain) { + xengnttab_seg->flags =3D GNTCOPY_dest_gref; + xengnttab_seg->dest.foreign.domid =3D domid; + xengnttab_seg->dest.foreign.ref =3D seg->dest.foreign.ref; + xengnttab_seg->dest.foreign.offset =3D seg->dest.foreign.offse= t; + xengnttab_seg->source.virt =3D seg->source.virt; + } else { + xengnttab_seg->flags =3D GNTCOPY_source_gref; + xengnttab_seg->source.foreign.domid =3D domid; + xengnttab_seg->source.foreign.ref =3D seg->source.foreign.ref; + xengnttab_seg->source.foreign.offset =3D + seg->source.foreign.offset; + xengnttab_seg->dest.virt =3D seg->dest.virt; + } + + xengnttab_seg->len =3D seg->len; + } + + if (xengnttab_grant_copy(xgt, nr_segs, xengnttab_segs)) { + if (errp) { + error_setg_errno(errp, errno, "xengnttab_grant_copy failed"); + } + rc =3D -errno; + goto done; + } + + rc =3D 0; + for (i =3D 0; i < nr_segs; i++) { + xengnttab_grant_copy_segment_t *xengnttab_seg =3D &xengnttab_segs[= i]; + + if (xengnttab_seg->status !=3D GNTST_okay) { + if (errp) { + error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i); + } + rc =3D -EIO; + break; + } + } + +done: + g_free(xengnttab_segs); + return rc; +} +#endif + static xenevtchn_handle *libxenevtchn_backend_open(void) { return xenevtchn_open(NULL, 0); @@ -65,7 +195,34 @@ struct evtchn_backend_ops libxenevtchn_backend_ops =3D { .pending =3D xenevtchn_pending, }; =20 +static xengnttab_handle *libxengnttab_backend_open(void) +{ + return xengnttab_open(NULL, 0); +} + + +static struct gnttab_backend_ops libxengnttab_backend_ops =3D { + .features =3D XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE, + .open =3D libxengnttab_backend_open, + .close =3D xengnttab_close, + .grant_copy =3D libxengnttab_fallback_grant_copy, + .set_max_grants =3D xengnttab_set_max_grants, + .map_refs =3D xengnttab_map_domain_grant_refs, + .unmap =3D xengnttab_unmap, +}; + void setup_xen_backend_ops(void) { +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >=3D 40800 + xengnttab_handle *xgt =3D xengnttab_open(NULL, 0); + + if (xgt) { + if (xengnttab_grant_copy(xgt, 0, NULL) =3D=3D 0) { + xen_gnttab_ops->grant_copy =3D libxengnttab_backend_grant_copy; + } + xengnttab_close(xgt); + } +#endif xen_evtchn_ops =3D &libxenevtchn_backend_ops; + xen_gnttab_ops =3D &libxengnttab_backend_ops; } diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c index 86a2c8e567..d8582cc74c 100644 --- a/hw/xen/xen_pvdev.c +++ b/hw/xen/xen_pvdev.c @@ -309,7 +309,7 @@ void xen_pv_del_xendev(struct XenLegacyDevice *xendev) qemu_xen_evtchn_close(xendev->evtchndev); } if (xendev->gnttabdev !=3D NULL) { - xengnttab_close(xendev->gnttabdev); + qemu_xen_gnttab_close(xendev->gnttabdev); } =20 QTAILQ_REMOVE(&xendevs, xendev, next); diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index e21b83796e..72d71d1eb7 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -9,7 +9,7 @@ #define HW_XEN_BUS_H =20 #include "hw/xen/xen_backend_ops.h" -#include "hw/xen/xen_common.h" +#include "hw/xen/interface/io/xenbus.h" #include "hw/sysbus.h" #include "qemu/notify.h" #include "qom/object.h" @@ -33,7 +33,6 @@ struct XenDevice { bool backend_online; XenWatch *backend_online_watch; xengnttab_handle *xgth; - bool feature_grant_copy; bool inactive; QLIST_HEAD(, XenEventChannel) event_channels; QLIST_ENTRY(XenDevice) list; diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legac= y-backend.h index 0ef9b772ac..01c12952b7 100644 --- a/include/hw/xen/xen-legacy-backend.h +++ b/include/hw/xen/xen-legacy-backend.h @@ -1,8 +1,8 @@ #ifndef HW_XEN_LEGACY_BACKEND_H #define HW_XEN_LEGACY_BACKEND_H =20 -#include "hw/xen/xen_common.h" #include "hw/xen/xen_backend_ops.h" +#include "hw/xen/interface/io/xenbus.h" #include "hw/xen/xen_pvdev.h" #include "net/net.h" #include "qom/object.h" @@ -55,17 +55,6 @@ void *xen_be_map_grant_refs(struct XenLegacyDevice *xend= ev, uint32_t *refs, void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr, unsigned int nr_refs); =20 -typedef struct XenGrantCopySegment { - union { - void *virt; - struct { - uint32_t ref; - off_t offset; - } foreign; - } source, dest; - size_t len; -} XenGrantCopySegment; - int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev, bool to_domain, XenGrantCopySegment segs[], unsigned int nr_segs); diff --git a/include/hw/xen/xen_backend_ops.h b/include/hw/xen/xen_backend_= ops.h index 9605456e81..acb7838e63 100644 --- a/include/hw/xen/xen_backend_ops.h +++ b/include/hw/xen/xen_backend_ops.h @@ -29,6 +29,12 @@ typedef struct xenevtchn_handle xenevtchn_handle; typedef int xenevtchn_port_or_error_t; typedef uint32_t evtchn_port_t; +typedef uint16_t domid_t; +typedef uint32_t grant_ref_t; + +#define XEN_PAGE_SHIFT 12 +#define XEN_PAGE_SIZE (1UL << XEN_PAGE_SHIFT) +#define XEN_PAGE_MASK (~(XEN_PAGE_SIZE-1)) =20 struct evtchn_backend_ops { xenevtchn_handle *(*open)(void); @@ -113,6 +119,93 @@ static inline int qemu_xen_evtchn_pending(xenevtchn_ha= ndle *xc) return xen_evtchn_ops->pending(xc); } =20 +typedef struct xengntdev_handle xengnttab_handle; + +typedef struct XenGrantCopySegment { + union { + void *virt; + struct { + uint32_t ref; + off_t offset; + } foreign; + } source, dest; + size_t len; +} XenGrantCopySegment; + +#define XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE (1U << 0) + +struct gnttab_backend_ops { + uint32_t features; + xengnttab_handle *(*open)(void); + int (*close)(xengnttab_handle *xgt); + int (*grant_copy)(xengnttab_handle *xgt, bool to_domain, uint32_t domi= d, + XenGrantCopySegment *segs, uint32_t nr_segs, + Error **errp); + int (*set_max_grants)(xengnttab_handle *xgt, uint32_t nr_grants); + void *(*map_refs)(xengnttab_handle *xgt, uint32_t count, uint32_t domi= d, + uint32_t *refs, int prot); + int (*unmap)(xengnttab_handle *xgt, void *start_address, uint32_t coun= t); +}; + +extern struct gnttab_backend_ops *xen_gnttab_ops; + +static inline xengnttab_handle *qemu_xen_gnttab_open(void) +{ + if (!xen_gnttab_ops) { + return NULL; + } + return xen_gnttab_ops->open(); +} + +static inline int qemu_xen_gnttab_close(xengnttab_handle *xgt) +{ + if (!xen_gnttab_ops) { + return -ENOSYS; + } + return xen_gnttab_ops->close(xgt); +} + +static inline int qemu_xen_gnttab_grant_copy(xengnttab_handle *xgt, + bool to_domain, uint32_t domi= d, + XenGrantCopySegment *segs, + uint32_t nr_segs, Error **err= p) +{ + if (!xen_gnttab_ops) { + return -ENOSYS; + } + + return xen_gnttab_ops->grant_copy(xgt, to_domain, domid, segs, nr_segs, + errp); +} + +static inline int qemu_xen_gnttab_set_max_grants(xengnttab_handle *xgt, ui= nt32_t nr_grants) +{ + if (!xen_gnttab_ops) { + return -ENOSYS; + } + return xen_gnttab_ops->set_max_grants(xgt, nr_grants); +} + +static inline void *qemu_xen_gnttab_map_refs(xengnttab_handle *xgt, uint32= _t count, + uint32_t domid, uint32_t *ref= s, + int prot) +{ + if (!xen_gnttab_ops) { + return NULL; + } + return xen_gnttab_ops->map_refs(xgt, count, domid, refs, prot); +} + +static inline int qemu_xen_gnttab_unmap(xengnttab_handle *xgt, + void *start_address, + uint32_t count) +{ + if (!xen_gnttab_ops) { + return -ENOSYS; + } + return xen_gnttab_ops->unmap(xgt, start_address, count); +} + void setup_xen_backend_ops(void); =20 #endif /* QEMU_XEN_BACKEND_OPS_H */ diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 34abd0a772..d4d10d3ff1 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -28,17 +28,6 @@ extern xc_interface *xen_xc; #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40701 =20 typedef xc_interface xenforeignmemory_handle; -typedef xc_gnttab xengnttab_handle; - -#define xengnttab_open(l, f) xc_gnttab_open(l, f) -#define xengnttab_close(h) xc_gnttab_close(h) -#define xengnttab_set_max_grants(h, n) xc_gnttab_set_max_grants(h, n) -#define xengnttab_map_grant_ref(h, d, r, p) xc_gnttab_map_grant_ref(h, d, = r, p) -#define xengnttab_unmap(h, a, n) xc_gnttab_munmap(h, a, n) -#define xengnttab_map_grant_refs(h, c, d, r, p) \ - xc_gnttab_map_grant_refs(h, c, d, r, p) -#define xengnttab_map_domain_grant_refs(h, c, d, r, p) \ - xc_gnttab_map_domain_grant_refs(h, c, d, r, p) =20 #define xenforeignmemory_open(l, f) xen_xc #define xenforeignmemory_close(h) @@ -58,7 +47,6 @@ static inline void *xenforeignmemory_map(xc_interface *h,= uint32_t dom, =20 #else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >=3D 40701 */ =20 -#include #include =20 #endif @@ -648,31 +636,4 @@ static inline int xen_set_ioreq_server_state(domid_t d= om, =20 #endif =20 -/* Xen before 4.8 */ - -#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40800 - -struct xengnttab_grant_copy_segment { - union xengnttab_copy_ptr { - void *virt; - struct { - uint32_t ref; - uint16_t offset; - uint16_t domid; - } foreign; - } source, dest; - uint16_t len; - uint16_t flags; - int16_t status; -}; - -typedef struct xengnttab_grant_copy_segment xengnttab_grant_copy_segment_t; - -static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t cou= nt, - xengnttab_grant_copy_segment_t *seg= s) -{ - return -ENOSYS; -} -#endif - #endif /* QEMU_HW_XEN_COMMON_H */ diff --git a/softmmu/globals.c b/softmmu/globals.c index eb62739be1..23bb27f0f6 100644 --- a/softmmu/globals.c +++ b/softmmu/globals.c @@ -66,3 +66,4 @@ uint32_t xen_domid; enum xen_mode xen_mode =3D XEN_DISABLED; bool xen_domid_restrict; struct evtchn_backend_ops *xen_evtchn_ops; +struct gnttab_backend_ops *xen_gnttab_ops; --=20 2.39.0