mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer management to libxc
xc_cputopoinfo() 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 reporting macros. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
b3c8f22904
commit
250f0b43af
5 files changed
+61
-75
No files matched your search
@@ -1238,7 +1238,7 @@ int xc_readconsolering(xc_interface *xch,
|
||||
int xc_send_debug_keys(xc_interface *xch, char *keys);
|
||||
|
||||
typedef xen_sysctl_physinfo_t xc_physinfo_t;
|
||||
typedef xen_sysctl_cputopoinfo_t xc_cputopoinfo_t;
|
||||
typedef xen_sysctl_cputopo_t xc_cputopo_t;
|
||||
typedef xen_sysctl_numainfo_t xc_numainfo_t;
|
||||
|
||||
typedef uint32_t xc_cpu_to_node_t;
|
||||
@@ -1249,7 +1249,8 @@ typedef uint64_t xc_node_to_memfree_t;
|
||||
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, xc_cputopoinfo_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_sched_id(xc_interface *xch,
|
||||
|
||||
+16
-7
@@ -203,22 +203,31 @@ int xc_physinfo(xc_interface *xch,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xc_cputopoinfo(xc_interface *xch,
|
||||
xc_cputopoinfo_t *put_info)
|
||||
int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
|
||||
xc_cputopo_t *cputopo)
|
||||
{
|
||||
int ret;
|
||||
DECLARE_SYSCTL;
|
||||
DECLARE_HYPERCALL_BOUNCE(cputopo, *max_cpus * sizeof(*cputopo),
|
||||
XC_HYPERCALL_BUFFER_BOUNCE_OUT);
|
||||
|
||||
if ( (ret = xc_hypercall_bounce_pre(xch, cputopo)) )
|
||||
goto out;
|
||||
|
||||
sysctl.u.cputopoinfo.num_cpus = *max_cpus;
|
||||
set_xen_guest_handle(sysctl.u.cputopoinfo.cputopo, cputopo);
|
||||
|
||||
sysctl.cmd = XEN_SYSCTL_cputopoinfo;
|
||||
|
||||
memcpy(&sysctl.u.cputopoinfo, put_info, sizeof(*put_info));
|
||||
|
||||
if ( (ret = do_sysctl(xch, &sysctl)) != 0 )
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
memcpy(put_info, &sysctl.u.cputopoinfo, sizeof(*put_info));
|
||||
*max_cpus = sysctl.u.cputopoinfo.num_cpus;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
xc_hypercall_bounce_post(xch, cputopo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xc_numainfo(xc_interface *xch,
|
||||
|
||||
+12
-25
@@ -5102,37 +5102,28 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
|
||||
libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
|
||||
{
|
||||
GC_INIT(ctx);
|
||||
xc_cputopoinfo_t tinfo;
|
||||
DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
|
||||
xc_cputopo_t *cputopo;
|
||||
libxl_cputopology *ret = NULL;
|
||||
int i;
|
||||
unsigned num_cpus;
|
||||
|
||||
/* Setting buffer to NULL makes the hypercall return number of CPUs */
|
||||
set_xen_guest_handle(tinfo.cputopo, HYPERCALL_BUFFER_NULL);
|
||||
if (xc_cputopoinfo(ctx->xch, &tinfo) != 0)
|
||||
/* Setting buffer to NULL makes the call return number of CPUs */
|
||||
if (xc_cputopoinfo(ctx->xch, &num_cpus, NULL))
|
||||
{
|
||||
LIBXL__LOG(ctx, XTL_ERROR, "Unable to determine number of CPUS");
|
||||
ret = NULL;
|
||||
LOGE(ERROR, "Unable to determine number of CPUS");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cputopo = xc_hypercall_buffer_alloc(ctx->xch, cputopo,
|
||||
sizeof(*cputopo) * tinfo.num_cpus);
|
||||
if (cputopo == NULL) {
|
||||
LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, ENOMEM,
|
||||
"Unable to allocate hypercall arguments");
|
||||
goto fail;
|
||||
}
|
||||
set_xen_guest_handle(tinfo.cputopo, cputopo);
|
||||
cputopo = libxl__zalloc(gc, sizeof(*cputopo) * num_cpus);
|
||||
|
||||
if (xc_cputopoinfo(ctx->xch, &tinfo) != 0) {
|
||||
LIBXL__LOG_ERRNO(ctx, XTL_ERROR, "CPU topology info hypercall failed");
|
||||
goto fail;
|
||||
if (xc_cputopoinfo(ctx->xch, &num_cpus, cputopo)) {
|
||||
LOGE(ERROR, "CPU topology info hypercall failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * tinfo.num_cpus);
|
||||
ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * num_cpus);
|
||||
|
||||
for (i = 0; i < tinfo.num_cpus; i++) {
|
||||
for (i = 0; i < num_cpus; i++) {
|
||||
#define V(map, i, invalid) ( cputopo[i].map == invalid) ? \
|
||||
LIBXL_CPUTOPOLOGY_INVALID_ENTRY : cputopo[i].map
|
||||
ret[i].core = V(core, i, XEN_INVALID_CORE_ID);
|
||||
@@ -5141,11 +5132,7 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
|
||||
#undef V
|
||||
}
|
||||
|
||||
fail:
|
||||
xc_hypercall_buffer_free(ctx->xch, cputopo);
|
||||
|
||||
if (ret)
|
||||
*nb_cpu_out = tinfo.num_cpus;
|
||||
*nb_cpu_out = num_cpus;
|
||||
|
||||
out:
|
||||
GC_FREE;
|
||||
|
||||
+22
-29
@@ -355,20 +355,17 @@ static void signal_int_handler(int signo)
|
||||
int i, j, k;
|
||||
struct timeval tv;
|
||||
int cx_cap = 0, px_cap = 0;
|
||||
DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
|
||||
xc_cputopoinfo_t info = { 0 };
|
||||
xc_cputopo_t *cputopo;
|
||||
unsigned max_cpus;
|
||||
|
||||
set_xen_guest_handle(info.cputopo, HYPERCALL_BUFFER_NULL);
|
||||
if ( xc_cputopoinfo(xc_handle, &info) != 0 )
|
||||
if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
|
||||
{
|
||||
fprintf(stderr, "failed to discover number of CPUs: %s\n",
|
||||
strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
cputopo = xc_hypercall_buffer_alloc(xc_handle, cputopo,
|
||||
sizeof(*cputopo) * info.num_cpus);
|
||||
|
||||
cputopo = calloc(max_cpus, sizeof(*cputopo));
|
||||
if ( cputopo == NULL )
|
||||
{
|
||||
fprintf(stderr, "failed to allocate hypercall buffers\n");
|
||||
@@ -453,28 +450,26 @@ static void signal_int_handler(int signo)
|
||||
printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
|
||||
}
|
||||
|
||||
set_xen_guest_handle(info.cputopo, cputopo);
|
||||
|
||||
if ( cx_cap && !xc_cputopoinfo(xc_handle, &info) )
|
||||
if ( cx_cap && !xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
|
||||
{
|
||||
uint32_t socket_ids[MAX_NR_CPU];
|
||||
uint32_t core_ids[MAX_NR_CPU];
|
||||
uint32_t socket_nr = 0;
|
||||
uint32_t core_nr = 0;
|
||||
|
||||
if ( info.num_cpus > MAX_NR_CPU )
|
||||
info.num_cpus = MAX_NR_CPU;
|
||||
if ( max_cpus > MAX_NR_CPU )
|
||||
max_cpus = MAX_NR_CPU;
|
||||
/* check validity */
|
||||
for ( i = 0; i < info.num_cpus; i++ )
|
||||
for ( i = 0; i < max_cpus; i++ )
|
||||
{
|
||||
if ( cputopo[i].core == XEN_INVALID_CORE_ID ||
|
||||
cputopo[i].socket == XEN_INVALID_SOCKET_ID )
|
||||
break;
|
||||
}
|
||||
if ( i >= info.num_cpus )
|
||||
if ( i >= max_cpus )
|
||||
{
|
||||
/* find socket nr & core nr per socket */
|
||||
for ( i = 0; i < info.num_cpus; i++ )
|
||||
for ( i = 0; i < max_cpus; i++ )
|
||||
{
|
||||
for ( j = 0; j < socket_nr; j++ )
|
||||
if ( cputopo[i].socket == socket_ids[j] )
|
||||
@@ -501,7 +496,7 @@ static void signal_int_handler(int signo)
|
||||
unsigned int n;
|
||||
uint64_t res;
|
||||
|
||||
for ( j = 0; j < info.num_cpus; j++ )
|
||||
for ( j = 0; j < max_cpus; j++ )
|
||||
{
|
||||
if ( cputopo[j].socket == socket_ids[i] )
|
||||
break;
|
||||
@@ -520,7 +515,7 @@ static void signal_int_handler(int signo)
|
||||
}
|
||||
for ( k = 0; k < core_nr; k++ )
|
||||
{
|
||||
for ( j = 0; j < info.num_cpus; j++ )
|
||||
for ( j = 0; j < max_cpus; j++ )
|
||||
{
|
||||
if ( cputopo[j].socket == socket_ids[i] &&
|
||||
cputopo[j].core == core_ids[k] )
|
||||
@@ -558,7 +553,7 @@ static void signal_int_handler(int signo)
|
||||
free(sum);
|
||||
free(avgfreq);
|
||||
out:
|
||||
xc_hypercall_buffer_free(xc_handle, cputopo);
|
||||
free(cputopo);
|
||||
xc_interface_close(xc_handle);
|
||||
exit(0);
|
||||
}
|
||||
@@ -965,12 +960,11 @@ void scaling_governor_func(int argc, char *argv[])
|
||||
|
||||
void cpu_topology_func(int argc, char *argv[])
|
||||
{
|
||||
DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
|
||||
xc_cputopoinfo_t info = { 0 };
|
||||
int i, rc = ENOMEM;
|
||||
xc_cputopo_t *cputopo;
|
||||
unsigned max_cpus;
|
||||
int i, rc;
|
||||
|
||||
set_xen_guest_handle(info.cputopo, HYPERCALL_BUFFER_NULL);
|
||||
if ( xc_cputopoinfo(xc_handle, &info) )
|
||||
if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
|
||||
{
|
||||
rc = errno;
|
||||
fprintf(stderr, "failed to discover number of CPUs (%d - %s)\n",
|
||||
@@ -978,16 +972,15 @@ void cpu_topology_func(int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
cputopo = xc_hypercall_buffer_alloc(xc_handle, cputopo,
|
||||
sizeof(*cputopo) * info.num_cpus);
|
||||
cputopo = calloc(max_cpus, sizeof(*cputopo));
|
||||
if ( cputopo == NULL )
|
||||
{
|
||||
rc = ENOMEM;
|
||||
fprintf(stderr, "failed to allocate hypercall buffers\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_xen_guest_handle(info.cputopo, cputopo);
|
||||
if ( xc_cputopoinfo(xc_handle, &info) )
|
||||
if ( xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
|
||||
{
|
||||
rc = errno;
|
||||
fprintf(stderr, "Cannot get Xen CPU topology (%d - %s)\n",
|
||||
@@ -996,7 +989,7 @@ void cpu_topology_func(int argc, char *argv[])
|
||||
}
|
||||
|
||||
printf("CPU\tcore\tsocket\tnode\n");
|
||||
for ( i = 0; i < info.num_cpus; i++ )
|
||||
for ( i = 0; i < max_cpus; i++ )
|
||||
{
|
||||
if ( cputopo[i].core == XEN_INVALID_CORE_ID )
|
||||
continue;
|
||||
@@ -1005,7 +998,7 @@ void cpu_topology_func(int argc, char *argv[])
|
||||
}
|
||||
rc = 0;
|
||||
out:
|
||||
xc_hypercall_buffer_free(xc_handle, cputopo);
|
||||
free(cputopo);
|
||||
if ( rc )
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
@@ -1220,30 +1220,26 @@ static PyObject *pyxc_getcpuinfo(XcObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
static PyObject *pyxc_topologyinfo(XcObject *self)
|
||||
{
|
||||
xc_cputopoinfo_t tinfo = { 0 };
|
||||
unsigned i;
|
||||
xc_cputopo_t *cputopo = NULL;
|
||||
unsigned i, num_cpus;
|
||||
PyObject *ret_obj = NULL;
|
||||
PyObject *cpu_to_core_obj, *cpu_to_socket_obj, *cpu_to_node_obj;
|
||||
DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
|
||||
|
||||
set_xen_guest_handle(tinfo.cputopo, HYPERCALL_BUFFER_NULL);
|
||||
if ( xc_cputopoinfo(self->xc_handle, &tinfo) != 0 )
|
||||
if ( xc_cputopoinfo(self->xc_handle, &num_cpus, NULL) != 0 )
|
||||
goto out;
|
||||
|
||||
cputopo = xc_hypercall_buffer_alloc(self->xc_handle, cputopo,
|
||||
sizeof(*cputopo) * tinfo.num_cpus);
|
||||
cputopo = calloc(num_cpus, sizeof(*cputopo));
|
||||
if ( cputopo == NULL )
|
||||
goto out;
|
||||
|
||||
set_xen_guest_handle(tinfo.cputopo, cputopo);
|
||||
if ( xc_cputopoinfo(self->xc_handle, &tinfo) != 0 )
|
||||
if ( xc_cputopoinfo(self->xc_handle, &num_cpus, cputopo) != 0 )
|
||||
goto out;
|
||||
|
||||
/* Construct cpu-to-* lists. */
|
||||
cpu_to_core_obj = PyList_New(0);
|
||||
cpu_to_socket_obj = PyList_New(0);
|
||||
cpu_to_node_obj = PyList_New(0);
|
||||
for ( i = 0; i < tinfo.num_cpus; i++ )
|
||||
for ( i = 0; i < num_cpus; i++ )
|
||||
{
|
||||
if ( cputopo[i].core == XEN_INVALID_CORE_ID )
|
||||
{
|
||||
@@ -1279,7 +1275,7 @@ static PyObject *pyxc_topologyinfo(XcObject *self)
|
||||
}
|
||||
}
|
||||
|
||||
ret_obj = Py_BuildValue("{s:i}", "max_cpu_index", tinfo.num_cpus + 1);
|
||||
ret_obj = Py_BuildValue("{s:i}", "max_cpu_index", num_cpus + 1);
|
||||
|
||||
PyDict_SetItemString(ret_obj, "cpu_to_core", cpu_to_core_obj);
|
||||
Py_DECREF(cpu_to_core_obj);
|
||||
@@ -1291,7 +1287,7 @@ static PyObject *pyxc_topologyinfo(XcObject *self)
|
||||
Py_DECREF(cpu_to_node_obj);
|
||||
|
||||
out:
|
||||
xc_hypercall_buffer_free(self->xc_handle, cputopo);
|
||||
free(cputopo);
|
||||
return ret_obj ? ret_obj : pyxc_error_to_exception(self->xc_handle);
|
||||
}
|
||||
|
||||
|
||||