Skip to content

Commit

Permalink
fix build with current libs: use libxl
Browse files Browse the repository at this point in the history
Signed-off-by: Bernhard Kaindl <[email protected]>
  • Loading branch information
bernhardkaindl committed May 12, 2024
1 parent 44ca004 commit 4954192
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 159 deletions.
4 changes: 2 additions & 2 deletions config/hwloc.m4
Original file line number Diff line number Diff line change
Expand Up @@ -918,8 +918,8 @@ EOF])
hwloc_xen_happy=no
if test "x$enable_xen" != "xno"; then
hwloc_xen_happy=yes
AC_CHECK_HEADERS([xenctrl.h], [
AC_CHECK_LIB([xenctrl], [xc_topologyinfo_bounced], [HWLOC_XEN_LIBS="-lxenctrl"], [hwloc_xen_happy=no])
AC_CHECK_HEADERS([libxl.h], [
AC_CHECK_LIB([xenlight], [libxl_get_cpu_topology], [HWLOC_XEN_LIBS="-lxenlight"], [hwloc_xen_happy=no])
], [hwloc_xen_happy=no])
fi
AC_SUBST(HWLOC_XEN_LIBS)
Expand Down
229 changes: 72 additions & 157 deletions src/topology-xen.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,23 @@
#include <inttypes.h>
#include <assert.h>

#include <xenctrl.h>
#include <libxl.h>


/* Xen private data for hwloc_backend */
struct hwloc_xen_priv {
xc_interface *xch; /* Xenctrl handle */
libxl_ctx *ctx;
xentoollog_logger logger; /* Xenctrl logger */
};

/* Topology and numa information from Xen */
struct hwloc_xen_info {
libxl_cputopology *cpu;
libxl_numainfo *node;
uint32_t max_cpu_id;
uint32_t max_node_id;

/* From sysctl_topologyinfo */
uint32_t cpu_count; /* Number of elements in of cpu_to_* arrays */
const uint32_t *cpu_to_core, *cpu_to_socket, *cpu_to_node;

/* From sysctl_numainfo */
uint32_t node_count; /* Number of elements in of node_to_* arrays */
const uint64_t *node_to_memsize, *node_to_memfree;
const uint32_t *node_to_node_distance; /* (node_count * node_count) elements */
int cpu_count;
int node_count;
};

/* Xenctrl Logging function */
Expand All @@ -49,118 +44,41 @@ xenctl_logfn(struct xentoollog_logger *logger __hwloc_attribute_unused,
va_list al __hwloc_attribute_unused)
{
#ifdef HWLOC_DEBUG
/* Dont bother snprintf()ing the buffer if we will throw it away anyway. */
static char logbuf[512];

vsnprintf(logbuf, sizeof logbuf, format, al);
hwloc_debug("%s: %s: %s\n", context, xtl_level_to_string(level), logbuf);
#endif
}

/* Allocate a hwloc_xen_info structure */
static struct hwloc_xen_info *
alloc_xen_info(void)
{
struct hwloc_xen_info *p = malloc(sizeof *p);

if (p)
memset(p, 0, sizeof *p);

return p;
}

/* Free a hwloc_xen_info structure */
static void
free_xen_info(struct hwloc_xen_info *p)
{
if (p) {
free((void *)p->node_to_node_distance);
free((void *)p->node_to_memfree);
free((void *)p->node_to_memsize);
free((void *)p->cpu_to_node);
free((void *)p->cpu_to_socket);
free((void *)p->cpu_to_core);
free(p->cpu);
free(p->node);
free(p);
}
}

/* Perform hypercalls to query Xen for information, and fill in a
* hwloc_xen_info structure. */
static struct hwloc_xen_info *
hwloc_get_xen_info(xc_interface *xch)
hwloc_get_xen_info(libxl_ctx *ctx)
{
struct hwloc_xen_info *data = alloc_xen_info();
xc_physinfo_t physinfo;

struct hwloc_xen_info *data = malloc(sizeof *data);
if (!data)
return NULL;

/* Ask Xen for the physical information. This provides the sizes of arrays
* required to query the topology and numa information. */
if (xc_physinfo(xch, &physinfo))
goto out;

{ /* Ask for the full topology information */
uint32_t *cpu_to_core, *cpu_to_socket, *cpu_to_node;

data->max_cpu_id = physinfo.max_cpu_id;
data->cpu_count = data->max_cpu_id + 1;

cpu_to_core = calloc(data->cpu_count, sizeof *cpu_to_core);
cpu_to_socket = calloc(data->cpu_count, sizeof *cpu_to_socket);
cpu_to_node = calloc(data->cpu_count, sizeof *cpu_to_node);

if (!cpu_to_core || !cpu_to_socket || !cpu_to_node)
goto out;

if (xc_topologyinfo_bounced(xch, &data->max_cpu_id,
cpu_to_core, cpu_to_socket, cpu_to_node))
goto out;

assert((data->max_cpu_id < data->cpu_count) &&
"Xen overflowed our arrays");

data->cpu_to_core = cpu_to_core;
data->cpu_to_socket = cpu_to_socket;
data->cpu_to_node = cpu_to_node;
}

{ /* Ask for the full numa memory information */
uint64_t *node_to_memsize, *node_to_memfree;
uint32_t *node_to_node_distance;

data->max_node_id = physinfo.max_node_id;
data->node_count = data->max_node_id + 1;

node_to_memsize = calloc(data->node_count, sizeof *node_to_memsize);
node_to_memfree = calloc(data->node_count, sizeof *node_to_memfree);
node_to_node_distance = calloc(data->node_count * data->node_count,
sizeof *node_to_node_distance);

if (!node_to_memsize || !node_to_memfree || !node_to_node_distance)
goto out;

if (xc_numainfo_bounced(xch, &data->max_node_id,
node_to_memsize, node_to_memfree,
node_to_node_distance))
goto out;

assert((data->max_node_id < data->node_count) &&
"Xen overflowed our arrays");

data->node_to_memsize = node_to_memsize;
data->node_to_memfree = node_to_memfree;
data->node_to_node_distance = node_to_node_distance;
}

memset(data, 0, sizeof *data);
data->cpu = libxl_get_cpu_topology(ctx, &data->cpu_count);
data->max_cpu_id = data->cpu_count - 1;
data->node = libxl_get_numainfo(ctx, &data->node_count);
data->max_node_id = data->node_count - 1;
return data;

out:
free_xen_info(data);
return NULL;
}

#ifdef HWLOC_HAVE_X86_CPUID
#if 0 && defined(HWLOC_HAVE_X86_CPUID)
/* Ask Xen to execute CPUID on a specific PU on our behalf. */
static int xen_cpuid_fn(void *_priv, unsigned pu, unsigned *eax, unsigned *ebx,
unsigned *ecx, unsigned *edx)
Expand All @@ -185,78 +103,83 @@ hwloc_xen_discover(struct hwloc_backend *backend)
struct hwloc_xen_priv *priv = backend->private_data;
struct hwloc_xen_info *data;
hwloc_bitmap_t each_socket, each_node, each_core;
uint32_t i, j, z;
uint32_t current_node, current_core, current_socket, cpu;

if (hwloc_get_root_obj(topology)->cpuset)
return 0;
/* Set by the x86 backend already if HWLOC_COMPONENTS=xen is not exported */
if (hwloc_get_root_obj(topology)->cpuset) {
/* fprintf(stderr, "export HWLOC_COMPONENTS=xen,x86 to enable the Xen backend before x86\n"); */
/* return 0; */
}

hwloc_debug("Discovering Xen topology\n");

data = hwloc_get_xen_info(priv->xch);
data = hwloc_get_xen_info(priv->ctx);
assert(data && "Failed to gather data from Xen\n");

hwloc_debug("Xen topology information\n");
hwloc_debug(" cpu count %"PRIu32", max cpu id %"PRIu32"\n",
data->cpu_count, data->max_cpu_id);

for ( z = 0; z <= data->max_cpu_id; ++z )
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
hwloc_debug(" cpu[%3"PRIu32"], core %3"PRIu32", sock %3"PRIu32", node %3"PRIu32"\n",
z, data->cpu_to_core[z], data->cpu_to_socket[z],
data->cpu_to_node[z]);
cpu, data->cpu[cpu].core, data->cpu[cpu].socket, data->cpu[cpu].node);

hwloc_debug("Xen NUMA information\n");
hwloc_debug(" numa count %"PRIu32", max numa id %"PRIu32"\n",
data->node_count, data->max_node_id);
for ( z = 0; z <= data->max_node_id; ++z )
hwloc_debug(" node[%3"PRIu32"], size %"PRIu64", free %"PRIu64"\n",
z, data->node_to_memsize[z], data->node_to_memfree[z]);
for ( current_node = 0; current_node <= data->max_node_id; ++current_node )
hwloc_debug(" node[%3"PRIu32"], size %"PRIu64"MB\n",
current_node, data->node[current_node].size >> 20);

hwloc_alloc_root_sets(topology);
hwloc_setup_pu_level(topology, data->max_cpu_id+1);

/* Socket information */
each_socket = hwloc_bitmap_alloc();
for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_socket[z] != ~0U)
hwloc_bitmap_set(each_socket, data->cpu_to_socket[z]);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].socket != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
hwloc_bitmap_set(each_socket, data->cpu[cpu].socket);

hwloc_debug_bitmap("Xen each_sockets is %s\n", each_socket);

each_core = hwloc_bitmap_alloc();
hwloc_bitmap_foreach_begin(i, each_socket)
hwloc_bitmap_foreach_begin(current_socket, each_socket)
{
struct hwloc_obj *sock =
hwloc_alloc_setup_object(HWLOC_OBJ_SOCKET, i);
hwloc_alloc_setup_object(HWLOC_OBJ_SOCKET, current_socket);
sock->cpuset = hwloc_bitmap_alloc();

for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_socket[z] == i)
hwloc_bitmap_set(sock->cpuset, z);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].socket == current_socket)
hwloc_bitmap_set(sock->cpuset, cpu);

hwloc_insert_object_by_cpuset(topology, sock);
hwloc_debug_1arg_bitmap(" Xen cpus on socket %u are %s\n", i, sock->cpuset);

/* If HWLOC_COMPONENTS inits x86 before xen, this warns of wrong magic and segfaults: */
if (!hwloc_get_root_obj(topology)->cpuset)
hwloc_debug_1arg_bitmap(" Xen cpus on socket %u are %s\n", current_socket, sock->cpuset);

/* Core information (Core IDs are enumerated per-socket in Xen ) */
hwloc_bitmap_zero(each_core);
for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_socket[z] == i &&
data->cpu_to_core[z] != ~0U )
hwloc_bitmap_set(each_core, data->cpu_to_core[z]);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].socket == current_socket &&
data->cpu[cpu].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY &&
data->cpu[cpu].node != LIBXL_CPUTOPOLOGY_INVALID_ENTRY )
hwloc_bitmap_set(each_core, data->cpu[cpu].core);
hwloc_debug_bitmap(" Xen each_core is %s\n", each_core);

hwloc_bitmap_foreach_begin(j, each_core)
hwloc_bitmap_foreach_begin(current_core, each_core)
{
struct hwloc_obj *core =
hwloc_alloc_setup_object(HWLOC_OBJ_CORE, j);
hwloc_alloc_setup_object(HWLOC_OBJ_CORE, current_core);
core->cpuset = hwloc_bitmap_alloc();

for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_socket[z] == i &&
data->cpu_to_core[z] == j)
hwloc_bitmap_set(core->cpuset, z);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].socket == current_socket &&
data->cpu[cpu].core == current_core)
hwloc_bitmap_set(core->cpuset, cpu);

hwloc_insert_object_by_cpuset(topology, core);
hwloc_debug_1arg_bitmap(" Xen cpus on core %u are %s\n", j, core->cpuset);
hwloc_debug_1arg_bitmap(" Xen cpus on core %u are %s\n", current_core, core->cpuset);
}
hwloc_bitmap_foreach_end();
}
Expand All @@ -266,45 +189,44 @@ hwloc_xen_discover(struct hwloc_backend *backend)

/* Node information */
each_node = hwloc_bitmap_alloc();
for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_node[z] != ~0U)
hwloc_bitmap_set(each_node, data->cpu_to_node[z]);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].node != LIBXL_NUMAINFO_INVALID_ENTRY)
hwloc_bitmap_set(each_node, data->cpu[cpu].node);

hwloc_debug_bitmap("Xen each_node is %s\n", each_node);

hwloc_bitmap_foreach_begin(i, each_node)
hwloc_bitmap_foreach_begin(current_node, each_node)
{
struct hwloc_obj *node =
hwloc_alloc_setup_object(HWLOC_OBJ_NODE, i);
hwloc_alloc_setup_object(HWLOC_OBJ_NODE, current_node);
node->cpuset = hwloc_bitmap_alloc();

for ( z = 0; z <= data->max_cpu_id; ++z )
if (data->cpu_to_node[z] == i)
hwloc_bitmap_set(node->cpuset, z);
for ( cpu = 0; cpu <= data->max_cpu_id; ++cpu )
if (data->cpu[cpu].node == current_node)
hwloc_bitmap_set(node->cpuset, cpu);

/* Fill in some memory information, as we have it to hand.
* Xen doesn't really do superpages yet. */
if (data->node_to_memsize[i] != ~0U) {
if (data->node[current_node].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
node->memory.page_types_len = 1;
node->memory.page_types = calloc(1, sizeof *node->memory.page_types);

node->memory.page_types[0].size = 4096;
node->memory.page_types[0].count = data->node_to_memsize[i] >> 12;
node->memory.local_memory = data->node_to_memsize[i];
node->memory.page_types[0].count = data->node[current_node].size >> 12;
node->memory.local_memory = data->node[current_node].size;
}

hwloc_insert_object_by_cpuset(topology, node);

hwloc_debug_1arg_bitmap(" Xen cpus on node %u are %s\n", i, node->cpuset);
hwloc_debug_1arg_bitmap(" Xen cpus on node %u are %s\n", current_node, node->cpuset);
}
hwloc_bitmap_foreach_end();
hwloc_bitmap_free(each_node);


hwloc_debug("All done discovering Xen topology\n\n");
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "Xen");

#ifdef HWLOC_HAVE_X86_CPUID
#if 0 && defined(HWLOC_HAVE_X86_CPUID)
hwloc_debug("Using CPUID to find cache information\n\n");
hwloc_x86_cpuid_discovery(
topology, data->max_cpu_id + 1,
Expand All @@ -324,11 +246,9 @@ hwloc_xen_backend_disable(struct hwloc_backend *backend)
struct hwloc_xen_priv *priv = backend->private_data;

if (priv) {

if (priv->xch)
xc_interface_close(priv->xch);
if (priv->ctx)
libxl_ctx_free(priv->ctx);
free(priv);

backend->private_data = NULL;
}
}
Expand All @@ -347,30 +267,25 @@ hwloc_xen_component_instantiate(struct hwloc_disc_component *component,
if (!backend)
goto err;

priv = malloc(sizeof *priv);
backend->private_data = priv = malloc(sizeof *priv);
if (!priv)
goto err;

priv->logger.vmessage = xenctl_logfn;

/* This will fail if we are not running as root in dom0. */
priv->xch = xc_interface_open(&priv->logger, &priv->logger, 0);
if (!priv->xch) {
hwloc_debug("xc_interface_open() failed. Are you running as root in dom0?"
" Disabling xen component.\n");
goto err;
if (libxl_ctx_alloc(&priv->ctx, LIBXL_VERSION, 0, NULL)) {
fprintf(stderr, "xen: libxl_ctx_alloc failed. Need to run as root in dom0.\n");
goto err;
}

backend->private_data = priv;
backend->discover = hwloc_xen_discover;
backend->disable = hwloc_xen_backend_disable;

return backend;

err:
if (priv && priv->xch)
xc_interface_close(priv->xch);
free(priv);
hwloc_xen_backend_disable(backend);
free(backend);
return NULL;
}
Expand Down

0 comments on commit 4954192

Please sign in to comment.