[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v7 5/5] 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 v7: * Replaced LOG with LOGE in libxl_get_pci_topology() * Replaced LOGE with LOG and set errno in libxl__pci_topology_init() * Test correct pointer for non-NULL in output_topologyinfo() (pciinfo, not cpuinfo) tools/libxc/include/xenctrl.h | 3 ++ tools/libxc/xc_misc.c | 44 +++++++++++++++++++++++++ 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 | 70 +++++++++++++++++++++++++++++++++++++++++ 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, 248 insertions(+), 7 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 520a284..2e7787a 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1231,6 +1231,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; @@ -1244,6 +1245,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, uint32_t *distance); +int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs, + physdev_pci_device_t *devs, uint32_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 94b70b4..3a3e366 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -238,6 +238,50 @@ out: return ret; } +int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs, + physdev_pci_device_t *devs, + uint32_t *nodes) +{ + int ret = 0; + 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_BOTH); + + 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; + + while ( sysctl.u.pcitopoinfo.first_dev < num_devs ) + { + if ( (ret = do_sysctl(xch, &sysctl)) != 0 ) + { + /* + * node[] is set to XEN_INVALID_NODE_ID for invalid devices, + * we can just skip those entries. + */ + if ( errno == ENODEV ) + errno = ret = 0; + else + break; + } + } + + 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 1abcbf1..86aff8e 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5139,6 +5139,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; + uint32_t *nodes; + libxl_pcitopology *ret = NULL; + int i; + + *num_devs = libxl__pci_numdevs(gc); + if (*num_devs < 0) { + LOGE(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 6bc75c5..f0db4d5 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -736,6 +736,14 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src); #define LIBXL_HAVE_PSR_MBM 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); @@ -1126,6 +1134,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 9c22309..bd7b508 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1193,6 +1193,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..6882d3a 100644 --- a/tools/libxl/libxl_linux.c +++ b/tools/libxl/libxl_linux.c @@ -279,3 +279,73 @@ 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) { + LOG(ERROR, "Too many devices"); + err = ERROR_FAIL; + errno = -ENOSPC; + 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 0866433..cd6f230 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -655,6 +655,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 9053b27..9108b56 100644 --- a/tools/libxl/libxl_utils.c +++ b/tools/libxl/libxl_utils.c @@ -882,6 +882,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 394b55d..5eaa083 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -5405,12 +5405,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; } @@ -5418,12 +5421,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 (pciinfo == 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 |