[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 7/7] 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> --- tools/libxc/include/xenctrl.h | 3 ++ tools/libxc/xc_misc.c | 32 +++++++++++++++++ tools/libxl/libxl.c | 49 +++++++++++++++++++++++++++ tools/libxl/libxl.h | 14 ++++++++ tools/libxl/libxl_freebsd.c | 14 ++++++++ tools/libxl/libxl_internal.h | 5 +++ tools/libxl/libxl_linux.c | 74 +++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_netbsd.c | 14 ++++++++ tools/libxl/libxl_types.idl | 7 ++++ tools/libxl/libxl_utils.c | 8 ++++ tools/libxl/xl_cmdimpl.c | 44 ++++++++++++++++++++---- 11 files changed, 257 insertions(+), 7 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 4466cd7..9ba40eb 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; @@ -1241,6 +1242,8 @@ int xc_physinfo(xc_interface *xch, xc_physinfo_t *info); int xc_cputopoinfo(xc_interface *xch, int *max_cpus, xc_cputopo_t *cputopo); int xc_numainfo(xc_interface *xch, int *max_nodes, xc_meminfo_t *meminfo, uint8_t *distance); +int xc_pcitopoinfo(xc_interface *xch, int 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 2dd5e13..a8266d7 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -204,6 +204,38 @@ out: return ret; } +int xc_pcitopoinfo(xc_interface *xch, int 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_numainfo(xc_interface *xch, int *max_nodes, xc_meminfo_t *meminfo, uint8_t *distance) { diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 9c1c949..c3b6c8a 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5107,6 +5107,55 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out) return ret; } +#ifdef LIBXL_HAVE_PCITOPO +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, rc; + + *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 (devs == NULL || nodes == NULL) { + LOGEV(ERROR, ENOMEM, "Unable to allocate hypercall arguments"); + goto out; + } + + rc = libxl__pci_topology_init(gc, devs, *num_devs); + if (rc) { + LOGEV(ERROR, rc, "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] == INVALID_NODE_ID) ? + LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i]; + } + + out: + GC_FREE; + return ret; +} +#endif + 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 0a123f1..12d9fb9 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -692,6 +692,14 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src); #define LIBXL_HAVE_PSR_CMT 1 #endif +/* + * LIBXL_HAVE_PCITOPO + * + * If this is defined, we have interfaces to query hypervisor about PCI device + * topology + */ +#define LIBXL_HAVE_PCITOPO 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); @@ -1070,6 +1078,12 @@ 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); +#ifdef LIBXL_HAVE_PCITOPO +#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); +#endif + #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..68d7b71 100644 --- a/tools/libxl/libxl_freebsd.c +++ b/tools/libxl/libxl_freebsd.c @@ -131,3 +131,17 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc) { return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; } + +#ifdef LIBXL_HAVE_PCITOPO +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; +} +#endif diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 9695f18..5a3a2c5 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__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 ea5d8c1..f558dba 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; } + +#ifdef LIBXL_HAVE_PCITOPO +/* These two routines are "inspired" by pciutils */ +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))) { + /* ".", ".." or a special non-device perhaps */ + 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; + + /* ".", ".." or a special non-device perhaps */ + 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; +} +#endif diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c index 898e160..25c1701 100644 --- a/tools/libxl/libxl_netbsd.c +++ b/tools/libxl/libxl_netbsd.c @@ -95,3 +95,17 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc) { return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; } + +#ifdef LIBXL_HAVE_PCITOPO +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; +} +#endif diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index f7fc695..e49b5f8 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -642,6 +642,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 ed0d478..c0e3f52 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -5196,12 +5196,17 @@ static void output_numainfo(void) static void output_topologyinfo(void) { - libxl_cputopology *info; + libxl_cputopology *cpuinfo; int i, nr; +#ifdef LIBXL_HAVE_PCITOPO + libxl_pcitopology *pciinfo; + int valid_devs; +#endif - 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; } @@ -5209,12 +5214,37 @@ 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); + +#ifdef LIBXL_HAVE_PCITOPO + 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); +#endif 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 |