|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 3/4] sysctl/libxl: Provide information about IO topology
Add support to XEN_SYSCTL_topologyinfo to return IO topology data.
Modify libxl_get_topology() to request this data, provide OS-dependent
helper functions that determine which devices we are inquiring about
(Linux only).
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
---
tools/libxl/libxl.c | 28 ++++++++++++++++-
tools/libxl/libxl_freebsd.c | 12 +++++++
tools/libxl/libxl_internal.h | 5 +++
tools/libxl/libxl_linux.c | 74 ++++++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_netbsd.c | 12 +++++++
tools/libxl/xl_cmdimpl.c | 31 ++++++++++++++-----
xen/common/sysctl.c | 30 ++++++++++++++++++
7 files changed, 183 insertions(+), 9 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 58cdc3b..ee103ac 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5086,6 +5086,7 @@ libxl_topology *libxl_get_topology(libxl_ctx *ctx)
GC_INIT(ctx);
xc_topologyinfo_t tinfo;
DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
+ DECLARE_HYPERCALL_BUFFER(xen_sysctl_iotopo_t, iotopo);
libxl_topology *ret = NULL;
int i;
int max_cpus;
@@ -5108,7 +5109,20 @@ libxl_topology *libxl_get_topology(libxl_ctx *ctx)
set_xen_guest_handle(tinfo.cputopo, cputopo);
tinfo.max_cpu_index = max_cpus - 1;
- set_xen_guest_handle(tinfo.iotopo, HYPERCALL_BUFFER_NULL);
+ tinfo.max_devs = libxl_pci_numdevs(ctx);
+ if (tinfo.max_devs > 0) {
+ iotopo = xc_hypercall_buffer_alloc(ctx->xch, iotopo,
+ sizeof(*iotopo) * tinfo.max_devs);
+ if (iotopo != NULL) {
+ if (libxl_pci_topology_init(ctx, iotopo, tinfo.max_devs))
+ tinfo.max_devs = 0;
+ } else
+ tinfo.max_devs = 0;
+ }
+ if (tinfo.max_devs > 0)
+ set_xen_guest_handle(tinfo.iotopo, iotopo);
+ else
+ set_xen_guest_handle(tinfo.iotopo, HYPERCALL_BUFFER_NULL);
if (xc_topologyinfo(ctx->xch, &tinfo) != 0) {
LIBXL__LOG_ERRNO(ctx, XTL_ERROR, "Topology info hypercall failed");
@@ -5128,8 +5142,20 @@ libxl_topology *libxl_get_topology(libxl_ctx *ctx)
#undef V
}
+ ret->dev_num = tinfo.max_devs;
+ ret->dev = libxl__zalloc(NOGC, sizeof(libxl_iotopology) * ret->dev_num);
+
+ for (i = 0; i < tinfo.max_devs; i++) {
+ ret->dev[i].seg = iotopo[i].seg;
+ ret->dev[i].bus = iotopo[i].bus;
+ ret->dev[i].devfn = iotopo[i].devfn;
+ ret->dev[i].node = (iotopo[i].node == INVALID_TOPOLOGY_ID) ?
+ LIBXL_TOPOLOGY_INVALID_ENTRY : iotopo[i].node;
+ }
+
fail:
xc_hypercall_buffer_free(ctx->xch, cputopo);
+ xc_hypercall_buffer_free(ctx->xch, iotopo);
out:
GC_FREE;
diff --git a/tools/libxl/libxl_freebsd.c b/tools/libxl/libxl_freebsd.c
index e8b88b3..8695a78 100644
--- a/tools/libxl/libxl_freebsd.c
+++ b/tools/libxl/libxl_freebsd.c
@@ -131,3 +131,15 @@ libxl_device_model_version
libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
}
+
+int libxl_pci_numdevs(libxl_ctx *ctx)
+{
+ return ERROR_NI;
+}
+
+int libxl_pci_topology_init(libxl_ctx *ctx,
+ xen_sysctl_iotopo_t *iotopo,
+ int numdev)
+{
+ return ERROR_NI;
+}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 4361421..c3a4194 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1168,6 +1168,11 @@ _hidden int libxl__try_phy_backend(mode_t st_mode);
_hidden char *libxl__devid_to_localdev(libxl__gc *gc, int devid);
+_hidden int libxl_pci_numdevs(libxl_ctx *ctx);
+_hidden int libxl_pci_topology_init(libxl_ctx *ctx,
+ xen_sysctl_iotopo_t *iotopo,
+ int numdev);
+
/* from libxl_pci */
_hidden int libxl__device_pci_add(libxl__gc *gc, uint32_t domid,
libxl_device_pci *pcidev, int starting);
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index ea5d8c1..884c042 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -279,3 +279,77 @@ libxl_device_model_version
libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
}
+
+/* These two routines are "inspired" by pciutils */
+int libxl_pci_numdevs(libxl_ctx *ctx)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int numdev = 0;
+
+ dir = opendir("/sys/bus/pci/devices");
+ if (!dir) {
+ LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, errno,
+ "Cannot open /sys/bus/pci/devices");
+ return ERROR_FAIL;
+ }
+
+ while ((entry = readdir(dir))) {
+ /* ".", ".." or a special non-device perhaps */
+ if (entry->d_name[0] == '.')
+ continue;
+ numdev++;
+ }
+ closedir(dir);
+
+ return numdev;
+}
+
+int libxl_pci_topology_init(libxl_ctx *ctx,
+ xen_sysctl_iotopo_t *iotopo,
+ int numdev)
+{
+
+ DIR *dir;
+ struct dirent *entry;
+ int i;
+
+ dir = opendir("/sys/bus/pci/devices");
+ if (!dir) {
+ LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, errno,
+ "Cannot open /sys/bus/pci/devices");
+ return ERROR_FAIL;
+ }
+
+ i = 0;
+ while ((entry = readdir(dir))) {
+ unsigned int dom, bus, dev, func;
+
+ /* ".", ".." or a special non-device perhaps */
+ if (entry->d_name[0] == '.')
+ continue;
+
+ if (i == numdev) {
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Too many devices\n");
+ closedir(dir);
+ return ERROR_FAIL;
+ }
+
+ if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4)
{
+ LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, errno,
+ "Cannot open /sys/bus/pci/devices");
+ closedir(dir);
+ return ERROR_FAIL;
+ }
+
+ iotopo[i].seg = dom;
+ iotopo[i].bus = bus;
+ iotopo[i].devfn = ((dev & 0x1f) << 3) | (func & 7);
+
+ i++;
+ }
+
+ closedir(dir);
+
+ return 0;
+}
diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
index 898e160..0946b64 100644
--- a/tools/libxl/libxl_netbsd.c
+++ b/tools/libxl/libxl_netbsd.c
@@ -95,3 +95,15 @@ libxl_device_model_version
libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
}
+
+int libxl_pci_numdevs(libxl_ctx *ctx)
+{
+ return ERROR_NI;
+}
+
+int libxl_pci_topology_init(libxl_ctx *ctx,
+ xen_sysctl_iotopo_t *iotopo,
+ int numdev)
+{
+ return ERROR_NI;
+}
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 9afef3f..fd9beb3 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5186,25 +5186,40 @@ static void output_numainfo(void)
static void output_topologyinfo(void)
{
- libxl_cputopology *info;
- int i, nr;
+ libxl_topology *info;
+ int i, valid_devs = 0;
- info = libxl_get_cpu_topology(ctx, &nr);
+ info = libxl_get_topology(ctx);
if (info == NULL) {
- fprintf(stderr, "libxl_get_topologyinfo failed.\n");
+ fprintf(stderr, "libxl_get_topology failed.\n");
return;
}
printf("cpu_topology :\n");
printf("cpu: core socket node\n");
- for (i = 0; i < nr; i++) {
- if (info[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
+ for (i = 0; i < info->cpu_num; i++) {
+ if (info->cpu[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
printf("%3d: %4d %4d %4d\n", i,
- info[i].core, info[i].socket, info[i].node);
+ info->cpu[i].core, info->cpu[i].socket, info->cpu[i].node);
}
- libxl_cputopology_list_free(info, nr);
+ printf("device topology :\n");
+ printf("device node\n");
+ for (i = 0; i < info->dev_num; i++) {
+ libxl_iotopology *dev = &info->dev[i];
+
+ if (dev->node != LIBXL_TOPOLOGY_INVALID_ENTRY) {
+ printf("%04x:%02x:%02x.%01x %d\n", dev->seg, dev->bus,
+ ((dev->devfn >> 3) & 0x1f), (dev->devfn & 7), dev->node);
+ valid_devs++;
+ }
+ }
+
+ if (valid_devs == 0)
+ printf(" No device topology data available\n");
+
+ libxl_topology_free(info);
return;
}
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index d4dc8ed..a82e0ed 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -328,6 +328,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t)
u_sysctl)
last_online_cpu = cpumask_last(&cpu_online_map);
max_cpu_index = min_t(uint32_t, ti->max_cpu_index, last_online_cpu);
+ /* CPU topology buffers should always be provided */
if ( guest_handle_is_null(ti->cputopo) )
{
ret = -EINVAL;
@@ -362,6 +363,35 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t)
u_sysctl)
u.topologyinfo.max_cpu_index) )
ret = -EFAULT;
}
+
+ if ( !ret && !guest_handle_is_null(ti->iotopo) )
+ {
+ for ( i = 0; i < ti->max_devs; i++ )
+ {
+ xen_sysctl_iotopo_t iotopo;
+ struct pci_dev *pdev;
+
+ if ( copy_from_guest_offset(&iotopo, ti->iotopo, i, 1) )
+ {
+ ret = -EFAULT;
+ break;
+ }
+
+ spin_lock(&pcidevs_lock);
+ pdev = pci_get_pdev(iotopo.seg, iotopo.bus, iotopo.devfn);
+ if ( !pdev || (pdev->node == NUMA_NO_NODE) )
+ iotopo.node = INVALID_TOPOLOGY_ID;
+ else
+ iotopo.node = pdev->node;
+ spin_unlock(&pcidevs_lock);
+
+ if ( copy_to_guest_offset(ti->iotopo, i, &iotopo, 1) )
+ {
+ ret = -EFAULT;
+ break;
+ }
+ }
+ }
}
break;
--
1.8.4.2
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |