>From d2edab820ee1bf4c354836e33c427602963986ba Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 9 Jun 2017 12:00:24 -0400 Subject: [PATCH 2/7] libxc: libxc: Use XENDOMCTL_get_memlist properly With the hypervisor having this working well we take advantage of that. The process has changed as we need to figure out what the upper limit of PFNs the hypervisor is willing to provide. Fortunatly for us, if we provide max_pfns with a zero value and buffer to be NULL, we get in max_pfns the acceptable max number. With this information we can make the hypercall - however the amount we get may be smaller than max, hence we adjust the number and also let the caller know. Furtheremore the 'version' is provided as a way for the caller to restart from scratch if that version is different from its previous call. Also we modify the tools to compile, but not neccessarily work well (see "xen-mceinj: Loop around xc_get_pfn_list". Signed-off-by: Konrad Rzeszutek Wilk --- tools/libxc/xc_private.c | 50 +++++++++++++++++++++++++-------- tools/libxc/xenctrl.h | 2 +- tools/ocaml/libs/xc/xenctrl_stubs.c | 3 +- tools/tests/mce-test/tools/xen-mceinj.c | 3 +- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 52f53d7..3ecee6a 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -581,33 +581,59 @@ int xc_machphys_mfn_list(xc_interface *xch, int xc_get_pfn_list(xc_interface *xch, uint32_t domid, - uint64_t *pfn_buf, - unsigned long max_pfns) + uint64_t *buf, + unsigned long index, + unsigned long max_pfns, + unsigned long *version) { DECLARE_DOMCTL; - DECLARE_HYPERCALL_BOUNCE(pfn_buf, max_pfns * sizeof(*pfn_buf), XC_HYPERCALL_BUFFER_BOUNCE_OUT); + DECLARE_HYPERCALL_BUFFER(uint64_t, pfn_buf); int ret; + unsigned long nr_pfns; -#ifdef VALGRIND - memset(pfn_buf, 0, max_pfns * sizeof(*pfn_buf)); -#endif + domctl.cmd = XEN_DOMCTL_getmemlist; + domctl.domain = (domid_t)domid; + domctl.u.getmemlist.max_pfns = 0; + domctl.u.getmemlist.index = 0; + + /* It is NULL */ + set_xen_guest_handle(domctl.u.getmemlist.buffer, pfn_buf); + + ret = do_domctl(xch, &domctl); + if ( ret && errno != E2BIG ) + return ret; - if ( xc_hypercall_bounce_pre(xch, pfn_buf) ) + if ( !domctl.u.getmemlist.max_pfns ) { - PERROR("xc_get_pfn_list: pfn_buf bounce failed"); + errno = ENXIO; return -1; } + if ( max_pfns > domctl.u.getmemlist.max_pfns ) + max_pfns = domctl.u.getmemlist.max_pfns; - domctl.cmd = XEN_DOMCTL_getmemlist; - domctl.domain = (domid_t)domid; + domctl.u.getmemlist.index = index; domctl.u.getmemlist.max_pfns = max_pfns; + + pfn_buf = xc_hypercall_buffer_alloc(xch, pfn_buf, max_pfns * sizeof(uint64_t)); + if ( !pfn_buf ) { + errno = ENOMEM; + return -1; + } + set_xen_guest_handle(domctl.u.getmemlist.buffer, pfn_buf); ret = do_domctl(xch, &domctl); - xc_hypercall_bounce_post(xch, pfn_buf); + nr_pfns = domctl.u.getmemlist.num_pfns; + + if ( !ret ) { + memcpy(buf, pfn_buf, nr_pfns * sizeof(*buf)); + *version = domctl.u.getmemlist.version; + } + + xc_hypercall_buffer_free(xch, pfn_buf); - return (ret < 0) ? -1 : domctl.u.getmemlist.num_pfns; + return (ret < 0) ? -1 : nr_pfns; } long xc_get_tot_pages(xc_interface *xch, uint32_t domid) diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 5f015b2..5802d69 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -1443,7 +1443,7 @@ unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom, * without a backing MFN. */ int xc_get_pfn_list(xc_interface *xch, uint32_t domid, uint64_t *pfn_buf, - unsigned long max_pfns); + unsigned long start_pfn, unsigned long max_pfns, unsigned long *version); int xc_copy_to_domain_page(xc_interface *xch, uint32_t domid, unsigned long dst_pfn, const char *src_page); diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index 5ed0008..b1f1dff 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -1055,6 +1055,7 @@ CAMLprim value stub_xc_domain_get_pfn_list(value xch, value domid, CAMLparam3(xch, domid, nr_pfns); CAMLlocal2(array, v); unsigned long c_nr_pfns; + unsigned long version; long ret, i; uint64_t *c_array; @@ -1065,7 +1066,7 @@ CAMLprim value stub_xc_domain_get_pfn_list(value xch, value domid, caml_raise_out_of_memory(); ret = xc_get_pfn_list(_H(xch), _D(domid), - c_array, c_nr_pfns); + c_array, 0, c_nr_pfns, &version); if (ret < 0) { free(c_array); failwith_xc(_H(xch)); diff --git a/tools/tests/mce-test/tools/xen-mceinj.c b/tools/tests/mce-test/tools/xen-mceinj.c index 21a488b..22b4401 100644 --- a/tools/tests/mce-test/tools/xen-mceinj.c +++ b/tools/tests/mce-test/tools/xen-mceinj.c @@ -263,6 +263,7 @@ static uint64_t guest_mfn(xc_interface *xc_handle, unsigned long max_mfn = 0; /* max mfn of the whole machine */ unsigned long m2p_mfn0; unsigned int guest_width; + unsigned long version; long max_gpfn,i; uint64_t mfn = MCE_INVALID_MFN; @@ -289,7 +290,7 @@ static uint64_t guest_mfn(xc_interface *xc_handle, err(xc_handle, "Failed to alloc pfn buf\n"); memset(pfn_buf, 0, sizeof(uint64_t) * max_gpfn); - ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, max_gpfn); + ret = xc_get_pfn_list(xc_handle, domain, pfn_buf, 0, max_gpfn, &version); if ( ret < 0 ) { free(pfn_buf); err(xc_handle, "Failed to get pfn list %x\n", ret); -- 2.9.4