[PATCH v10 9/10] libs/guest: use new hypercall if available
Frediano Ziglio <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
Use new hypercall if available, otherwise fall back to map+copy+unmap sequence. I took some statistics while migrating some machines instrumenting the code to use new and old code and doing it 5 times in a row for each and the raw operation takes at least 4 (from) or 5 (to) times less. Specifically for a test done with a machine with Intel Xeon Sapphire Rapids CPUs and migrating a Windows 10 machine with 12 GB of RAM the ratios were: - 4.9 times faster copying from guest to dom0; - 5.3 times faster copying to guest from dom0. The test was repeated multiple times resulting consistent in all rans. Signed-off-by: Frediano Ziglio <[email protected]> --- Changes since v4: - use int8_t instead of char for signed type. Changes since v6: - add some statistics. Changes since v9: - fixed a pointer initialization. --- tools/libs/guest/xg_sr_common.c | 47 ++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/tools/libs/guest/xg_sr_common.c b/tools/libs/guest/xg_sr_common.c index 90da21c35f..ce5026c707 100644 --- a/tools/libs/guest/xg_sr_common.c +++ b/tools/libs/guest/xg_sr_common.c @@ -156,11 +156,6 @@ static void __attribute__((unused)) build_assertions(void) BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params) != 8); } -enum { - foreigncopy_from, - foreigncopy_to -}; - static int xg_foreignmemory_copy(xc_interface *xch, domid_t domid, int dir, size_t nr_pages, void *buffer, const xen_pfn_t foreign_pfns[nr_pages]) @@ -174,8 +169,42 @@ static int xg_foreignmemory_copy(xc_interface *xch, domid_t domid, return -1; } + /* + * If foreign copy is supported, -1 not initialized, 0 not supported, + * 1 supported. + */ + static int8_t foreign_copy_supported = -1; + + if ( foreign_copy_supported ) + { + int rc; + privcmd_foreigncopy_t copy = { + .dom = domid, + .dir = dir, + .num = nr_pages, + .buffer = buffer, + }; + DECLARE_HYPERCALL_BOUNCE_IN(foreign_pfns, nr_pages * sizeof(xen_pfn_t)); + + if ( xc_hypercall_bounce_pre(xch, foreign_pfns) ) + return -1; + + copy.pfns = (xen_pfn_t *)HYPERCALL_BUFFER_AS_ARG(foreign_pfns); + + rc = ioctl(xencall_fd(xch->xcall), IOCTL_PRIVCMD_FOREIGNCOPY, ©); + if ( foreign_copy_supported < 0 ) + foreign_copy_supported = + (!rc || (errno != ENOTTY && errno != ENOSYS)); + + xc_hypercall_bounce_post(xch, foreign_pfns); + + if ( foreign_copy_supported ) + return rc; + } + + /* Fallback, emulate. */ int err[nr_pages]; - const int prot = (dir == foreigncopy_from) ? PROT_READ : PROT_READ|PROT_WRITE; + const int prot = (dir == XENMEM_foreigncopy_from) ? PROT_READ : PROT_READ|PROT_WRITE; void *p = xenforeignmemory_map(xch->fmem, domid, prot, nr_pages, foreign_pfns, err); if ( !p ) @@ -189,7 +218,7 @@ static int xg_foreignmemory_copy(xc_interface *xch, domid_t domid, return -1; } - if ( dir == foreigncopy_from ) + if ( dir == XENMEM_foreigncopy_from ) memcpy(buffer, p, nr_pages * XC_PAGE_SIZE); else memcpy(p, buffer, nr_pages * XC_PAGE_SIZE); @@ -201,7 +230,7 @@ int xg_foreignmemory_copy_from(xc_interface *xch, domid_t dom, size_t nr_pages, void *dest, const xen_pfn_t source[nr_pages]) { - return xg_foreignmemory_copy(xch, dom, foreigncopy_from, + return xg_foreignmemory_copy(xch, dom, XENMEM_foreigncopy_from, nr_pages, dest, source); } @@ -209,7 +238,7 @@ int xg_foreignmemory_copy_to(xc_interface *xch, domid_t dom, size_t nr_pages, const xen_pfn_t dest[nr_pages], const void *source) { - return xg_foreignmemory_copy(xch, dom, foreigncopy_to, + return xg_foreignmemory_copy(xch, dom, XENMEM_foreigncopy_to, nr_pages, (void *) source, dest); } -- 2.43.0