Message ID | f56ceeaf-745b-9064-e6c1-83bdb0d04360@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | allow xc_domain_maximum_gpfn() to observe full GFN value | expand |
On 22/06/2021 16:19, Jan Beulich wrote: > Some sub-functions, XENMEM_maximum_gpfn and XENMEM_maximum_ram_page in > particular, can return values requiring more than 31 bits to represent. > Hence we cannot issue the hypercall directly when the return value of > ioctl() is used to propagate this value (note that this is not the case > for the BSDs, and MiniOS already wraps all hypercalls in a multicall). It took me 3 readings to realise you weren't saying that BSDs used multicall (which they don't). Instead, I'd suggest rewording it. "Some sub-functions, XENMEM_maximum_gpfn and XENMEM_maximum_ram_page in particular, can return values requiring more than 31 bits to represent. The BSDs deliberately avoid using the ioctl() return value, and MiniOS already uses a multicall. They aren't affected. Linux and Solaris however do use the ioctl() return value, which must be avoided in this case to avoid truncation." Or something similar. With a suitable improvement along these lines, Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/tools/libs/ctrl/xc_private.c +++ b/tools/libs/ctrl/xc_private.c @@ -337,8 +337,47 @@ long do_memory_op(xc_interface *xch, int goto out1; } - ret = xencall2(xch->xcall, __HYPERVISOR_memory_op, - cmd, HYPERCALL_BUFFER_AS_ARG(arg)); +#if defined(__linux__) || defined(__sun__) + /* + * Some sub-ops return values which don't fit in "int". On platforms + * without a specific hypercall return value field in the privcmd + * interface structure, issue the request as a single-element multicall, + * to be able to capture the full return value. + */ + if ( sizeof(long) > sizeof(int) ) + { + multicall_entry_t multicall = { + .op = __HYPERVISOR_memory_op, + .args[0] = cmd, + .args[1] = HYPERCALL_BUFFER_AS_ARG(arg), + }, *call = &multicall; + DECLARE_HYPERCALL_BOUNCE(call, sizeof(*call), + XC_HYPERCALL_BUFFER_BOUNCE_BOTH); + + if ( xc_hypercall_bounce_pre(xch, call) ) + { + PERROR("Could not bounce buffer for memory_op hypercall"); + goto out1; + } + + ret = do_multicall_op(xch, HYPERCALL_BUFFER(call), 1); + + xc_hypercall_bounce_post(xch, call); + + if ( !ret ) + { + ret = multicall.result; + if ( multicall.result > ~0xfffUL ) + { + errno = -ret; + ret = -1; + } + } + } + else +#endif + ret = xencall2L(xch->xcall, __HYPERVISOR_memory_op, + cmd, HYPERCALL_BUFFER_AS_ARG(arg)); xc_hypercall_bounce_post(xch, arg); out1: