xc_numainfo() is not expected to be used on a hot path and therefore hypercall buffer management can be pushed into libxc. This will simplify life for callers.
Also update error logging macros. Signed-off-by: Boris Ostrovsky <boris.ostrov...@oracle.com> --- Changes in v6: * Dropped separate NULL buffer tests in xc_numainfo() * Moved test for buffers validity (either both or neither are NULL) to be the the first thing to do in xc_numainfo() tools/libxc/include/xenctrl.h | 4 ++- tools/libxc/xc_misc.c | 36 +++++++++++++++++++++----- tools/libxl/libxl.c | 51 ++++++++++++------------------------ tools/python/xen/lowlevel/xc/xc.c | 38 ++++++++++----------------- 4 files changed, 63 insertions(+), 66 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index f298702..4cf8daf 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1228,6 +1228,7 @@ int xc_send_debug_keys(xc_interface *xch, char *keys); typedef xen_sysctl_physinfo_t xc_physinfo_t; typedef xen_sysctl_cputopo_t xc_cputopo_t; typedef xen_sysctl_numainfo_t xc_numainfo_t; +typedef xen_sysctl_meminfo_t xc_meminfo_t; typedef uint32_t xc_cpu_to_node_t; typedef uint32_t xc_cpu_to_socket_t; @@ -1239,7 +1240,8 @@ typedef uint32_t xc_node_to_node_dist_t; int xc_physinfo(xc_interface *xch, xc_physinfo_t *info); int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus, xc_cputopo_t *cputopo); -int xc_numainfo(xc_interface *xch, xc_numainfo_t *info); +int xc_numainfo(xc_interface *xch, unsigned *max_nodes, + xc_meminfo_t *meminfo, uint32_t *distance); int xc_sched_id(xc_interface *xch, int *sched_id); diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 630a86c..97cbe63 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -204,22 +204,44 @@ out: return ret; } -int xc_numainfo(xc_interface *xch, - xc_numainfo_t *put_info) +int xc_numainfo(xc_interface *xch, unsigned *max_nodes, + xc_meminfo_t *meminfo, uint32_t *distance) { int ret; DECLARE_SYSCTL; + DECLARE_HYPERCALL_BOUNCE(meminfo, *max_nodes * sizeof(*meminfo), + XC_HYPERCALL_BUFFER_BOUNCE_OUT); + DECLARE_HYPERCALL_BOUNCE(distance, + *max_nodes * *max_nodes * sizeof(*distance), + XC_HYPERCALL_BUFFER_BOUNCE_OUT); + + if ( !!meminfo ^ !!distance ) + { + errno = EINVAL; + return -1; + } + + if ( (ret = xc_hypercall_bounce_pre(xch, meminfo)) ) + goto out; + if ((ret = xc_hypercall_bounce_pre(xch, distance)) ) + goto out; + + sysctl.u.numainfo.num_nodes = *max_nodes; + set_xen_guest_handle(sysctl.u.numainfo.meminfo, meminfo); + set_xen_guest_handle(sysctl.u.numainfo.distance, distance); sysctl.cmd = XEN_SYSCTL_numainfo; - memcpy(&sysctl.u.numainfo, put_info, sizeof(*put_info)); + if ( (ret = do_sysctl(xch, &sysctl)) != 0 ) + goto out; - if ((ret = do_sysctl(xch, &sysctl)) != 0) - return ret; + *max_nodes = sysctl.u.numainfo.num_nodes; - memcpy(put_info, &sysctl.u.numainfo, sizeof(*put_info)); +out: + xc_hypercall_bounce_post(xch, meminfo); + xc_hypercall_bounce_post(xch, distance); - return 0; + return ret; } diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 697c86d..45cd318 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5140,61 +5140,44 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out) libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr) { GC_INIT(ctx); - xc_numainfo_t ninfo; - DECLARE_HYPERCALL_BUFFER(xen_sysctl_meminfo_t, meminfo); - DECLARE_HYPERCALL_BUFFER(uint32_t, distance); + xc_meminfo_t *meminfo; + uint32_t *distance; libxl_numainfo *ret = NULL; int i, j; + unsigned num_nodes; - set_xen_guest_handle(ninfo.meminfo, HYPERCALL_BUFFER_NULL); - set_xen_guest_handle(ninfo.distance, HYPERCALL_BUFFER_NULL); - if (xc_numainfo(ctx->xch, &ninfo) != 0) { - LIBXL__LOG(ctx, XTL_ERROR, "Unable to determine number of NODES"); - ret = NULL; + if (xc_numainfo(ctx->xch, &num_nodes, NULL, NULL)) { + LOGEV(ERROR, errno, "Unable to determine number of nodes"); goto out; } - meminfo = xc_hypercall_buffer_alloc(ctx->xch, meminfo, - sizeof(*meminfo) * ninfo.num_nodes); - distance = xc_hypercall_buffer_alloc(ctx->xch, distance, - sizeof(*distance) * - ninfo.num_nodes * ninfo.num_nodes); - if ((meminfo == NULL) || (distance == NULL)) { - LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, ENOMEM, - "Unable to allocate hypercall arguments"); - goto fail; - } + meminfo = libxl__zalloc(gc, sizeof(*meminfo) * num_nodes); + distance = libxl__zalloc(gc, sizeof(*distance) * num_nodes * num_nodes); - set_xen_guest_handle(ninfo.meminfo, meminfo); - set_xen_guest_handle(ninfo.distance, distance); - if (xc_numainfo(ctx->xch, &ninfo) != 0) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting numainfo"); - goto fail; + if (xc_numainfo(ctx->xch, &num_nodes, meminfo, distance)) { + LOGEV(ERROR, errno, "getting numainfo"); + goto out; } - *nr = ninfo.num_nodes; + *nr = num_nodes; - ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * ninfo.num_nodes); - for (i = 0; i < ninfo.num_nodes; i++) - ret[i].dists = libxl__calloc(NOGC, ninfo.num_nodes, sizeof(*distance)); + ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * num_nodes); + for (i = 0; i < num_nodes; i++) + ret[i].dists = libxl__calloc(NOGC, num_nodes, sizeof(*distance)); - for (i = 0; i < ninfo.num_nodes; i++) { + for (i = 0; i < num_nodes; i++) { #define V(val, invalid) (val == invalid) ? \ LIBXL_NUMAINFO_INVALID_ENTRY : val ret[i].size = V(meminfo[i].memsize, XEN_INVALID_MEM_SZ); ret[i].free = V(meminfo[i].memfree, XEN_INVALID_MEM_SZ); - ret[i].num_dists = ninfo.num_nodes; + ret[i].num_dists = num_nodes; for (j = 0; j < ret[i].num_dists; j++) { - unsigned idx = i * ninfo.num_nodes + j; + unsigned idx = i * num_nodes + j; ret[i].dists[j] = V(distance[idx], XEN_INVALID_NODE_DIST); } #undef V } - fail: - xc_hypercall_buffer_free(ctx->xch, meminfo); - xc_hypercall_buffer_free(ctx->xch, distance); - out: GC_FREE; return ret; diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 21ba57d..fbd93db 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1293,33 +1293,23 @@ out: static PyObject *pyxc_numainfo(XcObject *self) { - xc_numainfo_t ninfo = { 0 }; - unsigned i, j; + unsigned i, j, num_nodes; uint64_t free_heap; PyObject *ret_obj = NULL, *node_to_node_dist_list_obj; PyObject *node_to_memsize_obj, *node_to_memfree_obj; PyObject *node_to_dma32_mem_obj, *node_to_node_dist_obj; - DECLARE_HYPERCALL_BUFFER(xen_sysctl_meminfo_t, meminfo); - DECLARE_HYPERCALL_BUFFER(uint32_t, distance); + xc_meminfo_t *meminfo = NULL; + uint32_t *distance = NULL; - set_xen_guest_handle(ninfo.meminfo, HYPERCALL_BUFFER_NULL); - set_xen_guest_handle(ninfo.distance, HYPERCALL_BUFFER_NULL); - if ( xc_numainfo(self->xc_handle, &ninfo) != 0 ) + if ( xc_numainfo(self->xc_handle, &num_nodes, NULL, NULL) != 0 ) goto out; - meminfo = xc_hypercall_buffer_alloc(self->xc_handle, meminfo, - sizeof(*meminfo) * ninfo.num_nodes); - if ( meminfo == NULL ) - goto out; - distance = xc_hypercall_buffer_alloc(self->xc_handle, distance, - sizeof(*distance) * - ninfo.num_nodes * ninfo.num_nodes); - if ( distance == NULL ) + meminfo = calloc(num_nodes, sizeof(*meminfo)); + distance = calloc(num_nodes * num_nodes, sizeof(*distance)); + if ( (meminfo == NULL) || (distance == NULL) ) goto out; - set_xen_guest_handle(ninfo.meminfo, meminfo); - set_xen_guest_handle(ninfo.distance, distance); - if ( xc_numainfo(self->xc_handle, &ninfo) != 0 ) + if ( xc_numainfo(self->xc_handle, &num_nodes, meminfo, distance) != 0 ) goto out; /* Construct node-to-* lists. */ @@ -1327,7 +1317,7 @@ static PyObject *pyxc_numainfo(XcObject *self) node_to_memfree_obj = PyList_New(0); node_to_dma32_mem_obj = PyList_New(0); node_to_node_dist_list_obj = PyList_New(0); - for ( i = 0; i < ninfo.num_nodes; i++ ) + for ( i = 0; i < num_nodes; i++ ) { PyObject *pyint; unsigned invalid_node; @@ -1351,9 +1341,9 @@ static PyObject *pyxc_numainfo(XcObject *self) /* Node to Node Distance */ node_to_node_dist_obj = PyList_New(0); invalid_node = (meminfo[i].memsize == XEN_INVALID_MEM_SZ); - for ( j = 0; j < ninfo.num_nodes; j++ ) + for ( j = 0; j < num_nodes; j++ ) { - uint32_t dist = distance[i * ninfo.num_nodes + j]; + uint32_t dist = distance[i * num_nodes + j]; if ( invalid_node || (dist == XEN_INVALID_NODE_DIST) ) { PyList_Append(node_to_node_dist_obj, Py_None); @@ -1369,7 +1359,7 @@ static PyObject *pyxc_numainfo(XcObject *self) Py_DECREF(node_to_node_dist_obj); } - ret_obj = Py_BuildValue("{s:i}", "max_node_index", ninfo.num_nodes + 1); + ret_obj = Py_BuildValue("{s:i}", "max_node_index", num_nodes + 1); PyDict_SetItemString(ret_obj, "node_memsize", node_to_memsize_obj); Py_DECREF(node_to_memsize_obj); @@ -1385,8 +1375,8 @@ static PyObject *pyxc_numainfo(XcObject *self) Py_DECREF(node_to_node_dist_list_obj); out: - xc_hypercall_buffer_free(self->xc_handle, meminfo); - xc_hypercall_buffer_free(self->xc_handle, distance); + free(meminfo); + free(distance); return ret_obj ? ret_obj : pyxc_error_to_exception(self->xc_handle); } -- 1.7.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel