[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 |