[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 9/9] libxl: Add interface for querying hypervisor about PCI topology
.. and use this new interface to display it along with CPU topology and NUMA information when 'xl info -n' command is issued The output will look like ... cpu_topology : cpu: core socket node 0: 0 0 0 ... device topology : device node 0000:00:00.0 0 0000:00:01.0 0 ... Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> --- Changes in v4: * Rename LIBXL_HAVE_PCITOPO to LIBXL_HAVE_PCITOPOLOGY, drop ifdefs from code * Don't treat no PCI devices as an error in libxl_get_pci_topology() * Drop unnecessary comments * Make num_devs argument in xc_pcitopoinfo an unsigned tools/libxc/include/xenctrl.h | 3 ++ tools/libxc/xc_misc.c | 31 ++++++++++++++++++ tools/libxl/libxl.c | 42 +++++++++++++++++++++++++ tools/libxl/libxl.h | 12 +++++++ tools/libxl/libxl_freebsd.c | 12 +++++++ tools/libxl/libxl_internal.h | 5 +++ tools/libxl/libxl_linux.c | 69 +++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_netbsd.c | 12 +++++++ tools/libxl/libxl_types.idl | 7 ++++ tools/libxl/libxl_utils.c | 8 +++++ tools/libxl/xl_cmdimpl.c | 40 +++++++++++++++++++---- 11 files changed, 234 insertions(+), 7 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 09b0ec2..c08f253 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1229,6 +1229,7 @@ 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 xen_sysctl_pcitopoinfo_t xc_pcitopoinfo_t; typedef uint32_t xc_cpu_to_node_t; typedef uint32_t xc_cpu_to_socket_t; @@ -1242,6 +1243,8 @@ int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus, xc_cputopo_t *cputopo); int xc_numainfo(xc_interface *xch, unsigned *max_nodes, xc_meminfo_t *meminfo, uint8_t *distance); +int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs, + physdev_pci_device_t *devs, uint8_t *nodes); 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 58d3883..f6cb05b 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -237,6 +237,37 @@ out: return ret; } +int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs, + physdev_pci_device_t *devs, + uint8_t *nodes) +{ + int ret; + DECLARE_SYSCTL; + DECLARE_HYPERCALL_BOUNCE(devs, num_devs * sizeof(*devs), + XC_HYPERCALL_BUFFER_BOUNCE_IN); + DECLARE_HYPERCALL_BOUNCE(nodes, num_devs* sizeof(*nodes), + XC_HYPERCALL_BUFFER_BOUNCE_OUT); + + if ((ret = xc_hypercall_bounce_pre(xch, devs))) + goto out; + if ((ret = xc_hypercall_bounce_pre(xch, nodes))) + goto out; + + sysctl.u.pcitopoinfo.first_dev = 0; + sysctl.u.pcitopoinfo.num_devs = num_devs; + set_xen_guest_handle(sysctl.u.pcitopoinfo.devs, devs); + set_xen_guest_handle(sysctl.u.pcitopoinfo.nodes, nodes); + + sysctl.cmd = XEN_SYSCTL_pcitopoinfo; + + ret = do_sysctl(xch, &sysctl); + + out: + xc_hypercall_bounce_post(xch, devs); + xc_hypercall_bounce_post(xch, nodes); + + return ret; +} int xc_sched_id(xc_interface *xch, int *sched_id) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index b37b3bd..0f8b519 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5078,6 +5078,48 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out) return ret; } +libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs) +{ + GC_INIT(ctx); + physdev_pci_device_t *devs; + uint8_t *nodes; + libxl_pcitopology *ret = NULL; + int i; + + *num_devs = libxl__pci_numdevs(gc); + if (*num_devs < 0) { + LOG(ERROR, "Unable to determine number of PCI devices"); + goto out; + } + + devs = libxl__zalloc(gc, sizeof(*devs) * *num_devs); + nodes = libxl__zalloc(gc, sizeof(*nodes) * *num_devs); + + if (libxl__pci_topology_init(gc, devs, *num_devs)) { + LOGE(ERROR, "Cannot initialize PCI hypercall structure"); + goto out; + } + + if (xc_pcitopoinfo(ctx->xch, *num_devs, devs, nodes) != 0) { + LOGE(ERROR, "PCI topology info hypercall failed"); + goto out; + } + + ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * *num_devs); + + for (i = 0; i < *num_devs; i++) { + ret[i].seg = devs[i].seg; + ret[i].bus = devs[i].bus; + ret[i].devfn = devs[i].devfn; + ret[i].node = (nodes[i] == XEN_INVALID_NODE_ID) ? + LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i]; + } + + out: + GC_FREE; + return ret; +} + libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr) { GC_INIT(ctx); diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index f784df5..a4c1bf5 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -714,6 +714,14 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src); #define LIBXL_HAVE_PSR_CMT 1 #endif +/* + * LIBXL_HAVE_PCITOPOLOGY + * + * If this is defined, then interface to query hypervisor about PCI device + * topology is available. + */ +#define LIBXL_HAVE_PCITOPOLOGY 1 + typedef char **libxl_string_list; void libxl_string_list_dispose(libxl_string_list *sl); int libxl_string_list_length(const libxl_string_list *sl); @@ -1092,6 +1100,10 @@ void libxl_vminfo_list_free(libxl_vminfo *list, int nb_vm); libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out); void libxl_cputopology_list_free(libxl_cputopology *, int nb_cpu); +#define LIBXL_PCITOPOLOGY_INVALID_ENTRY (~(uint32_t)0) +libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs); +void libxl_pcitopology_list_free(libxl_pcitopology *, int num_devs); + #define LIBXL_NUMAINFO_INVALID_ENTRY (~(uint32_t)0) libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr); void libxl_numainfo_list_free(libxl_numainfo *, int nr); diff --git a/tools/libxl/libxl_freebsd.c b/tools/libxl/libxl_freebsd.c index e8b88b3..47c3391 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__gc *gc) +{ + return ERROR_NI; +} + +int libxl__pci_topology_init(libxl__gc *gc, + physdev_pci_device_t *devs, + int num_devs) +{ + return ERROR_NI; +} diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 934465a..42942b2 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1170,6 +1170,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__gc *gc); +_hidden int libxl__pci_topology_init(libxl__gc *gc, + physdev_pci_device_t *devs, + int num_devs); + /* 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 b51930c..be76c6f 100644 --- a/tools/libxl/libxl_linux.c +++ b/tools/libxl/libxl_linux.c @@ -279,3 +279,72 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc) { return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; } + +int libxl__pci_numdevs(libxl__gc *gc) +{ + DIR *dir; + struct dirent *entry; + int num_devs = 0; + + dir = opendir("/sys/bus/pci/devices"); + if (!dir) { + LOGEV(ERROR, errno, "Cannot open /sys/bus/pci/devices"); + return ERROR_FAIL; + } + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + num_devs++; + } + closedir(dir); + + return num_devs; +} + +int libxl__pci_topology_init(libxl__gc *gc, + physdev_pci_device_t *devs, + int num_devs) +{ + + DIR *dir; + struct dirent *entry; + int i, err = 0; + + dir = opendir("/sys/bus/pci/devices"); + if (!dir) { + LOGEV(ERROR, errno, "Cannot open /sys/bus/pci/devices"); + return ERROR_FAIL; + } + + i = 0; + while ((entry = readdir(dir))) { + unsigned int dom, bus, dev, func; + + if (entry->d_name[0] == '.') + continue; + + if (i == num_devs) { + LOGE(ERROR, "Too many devices\n"); + err = ERROR_FAIL; + goto out; + } + + if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4) { + LOGEV(ERROR, errno, "Error processing /sys/bus/pci/devices"); + err = ERROR_FAIL; + goto out; + } + + devs[i].seg = dom; + devs[i].bus = bus; + devs[i].devfn = ((dev & 0x1f) << 3) | (func & 7); + + i++; + } + + out: + closedir(dir); + + return err; +} diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c index 898e160..a2a962e 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__gc *gc) +{ + return ERROR_NI; +} + +int libxl__pci_topology_init(libxl__gc *gc, + physdev_pci_device_t *devs, + int num_devs) +{ + return ERROR_NI; +} diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 02be466..2accda3 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -645,6 +645,13 @@ libxl_cputopology = Struct("cputopology", [ ("node", uint32), ], dir=DIR_OUT) +libxl_pcitopology = Struct("pcitopology", [ + ("seg", uint16), + ("bus", uint8), + ("devfn", uint8), + ("node", uint32), + ], dir=DIR_OUT) + libxl_sched_credit_params = Struct("sched_credit_params", [ ("tslice_ms", integer), ("ratelimit_us", integer), diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c index 7095b58..c31407f 100644 --- a/tools/libxl/libxl_utils.c +++ b/tools/libxl/libxl_utils.c @@ -877,6 +877,14 @@ void libxl_cputopology_list_free(libxl_cputopology *list, int nr) free(list); } +void libxl_pcitopology_list_free(libxl_pcitopology *list, int nr) +{ + int i; + for (i = 0; i < nr; i++) + libxl_pcitopology_dispose(&list[i]); + free(list); +} + void libxl_numainfo_list_free(libxl_numainfo *list, int nr) { int i; diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index e41f633..b9fd8cf 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -5214,12 +5214,15 @@ static void output_numainfo(void) static void output_topologyinfo(void) { - libxl_cputopology *info; + libxl_cputopology *cpuinfo; int i, nr; + libxl_pcitopology *pciinfo; + int valid_devs; - info = libxl_get_cpu_topology(ctx, &nr); - if (info == NULL) { - fprintf(stderr, "libxl_get_topologyinfo failed.\n"); + + cpuinfo = libxl_get_cpu_topology(ctx, &nr); + if (cpuinfo == NULL) { + fprintf(stderr, "libxl_get_cpu_topology failed.\n"); return; } @@ -5227,12 +5230,35 @@ static void output_topologyinfo(void) printf("cpu: core socket node\n"); for (i = 0; i < nr; i++) { - if (info[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY) + if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY) printf("%3d: %4d %4d %4d\n", i, - info[i].core, info[i].socket, info[i].node); + cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node); + } + + libxl_cputopology_list_free(cpuinfo, nr); + + pciinfo = libxl_get_pci_topology(ctx, &nr); + if (cpuinfo == NULL) { + fprintf(stderr, "libxl_get_pci_topology failed.\n"); + return; } - libxl_cputopology_list_free(info, nr); + printf("device topology :\n"); + printf("device node\n"); + for (i = 0; i < nr; i++) { + if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) { + printf("%04x:%02x:%02x.%01x %d\n", pciinfo[i].seg, + pciinfo[i].bus, + ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7), + pciinfo[i].node); + valid_devs++; + } + } + + if (valid_devs == 0) + printf("No device topology data available\n"); + + libxl_pcitopology_list_free(pciinfo, nr); return; } -- 1.7.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |