[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 4/4] 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 Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> --- tools/libxc/include/xenctrl.h | 2 + tools/libxc/xc_misc.c | 18 ++++++++++ tools/libxl/libxl.c | 58 +++++++++++++++++++++++++++++++++ tools/libxl/libxl.h | 4 ++ tools/libxl/libxl_freebsd.c | 12 +++++++ tools/libxl/libxl_internal.h | 5 +++ tools/libxl/libxl_linux.c | 71 +++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_netbsd.c | 12 +++++++ tools/libxl/libxl_types.idl | 7 ++++ tools/libxl/libxl_utils.c | 8 +++++ tools/libxl/xl_cmdimpl.c | 39 ++++++++++++++++++---- 11 files changed, 229 insertions(+), 7 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 0cb6743..3c5824a 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1227,6 +1227,7 @@ int xc_send_debug_keys(xc_interface *xch, char *keys); typedef xen_sysctl_physinfo_t xc_physinfo_t; typedef xen_sysctl_cputopoinfo_t xc_cputopoinfo_t; +typedef xen_sysctl_pcitopoinfo_t xc_pcitopoinfo_t; typedef xen_sysctl_numainfo_t xc_numainfo_t; typedef uint32_t xc_cpu_to_node_t; @@ -1238,6 +1239,7 @@ typedef uint32_t xc_node_to_node_dist_t; int xc_physinfo(xc_interface *xch, xc_physinfo_t *info); int xc_cputopoinfo(xc_interface *xch, xc_cputopoinfo_t *info); +int xc_pcitopoinfo(xc_interface *xch, xc_pcitopoinfo_t *info); int xc_numainfo(xc_interface *xch, xc_numainfo_t *info); int xc_sched_id(xc_interface *xch, diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index be68291..e33a312 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -195,6 +195,24 @@ int xc_cputopoinfo(xc_interface *xch, return 0; } +int xc_pcitopoinfo(xc_interface *xch, + xc_pcitopoinfo_t *put_info) +{ + int ret; + DECLARE_SYSCTL; + + sysctl.cmd = XEN_SYSCTL_pcitopoinfo; + + memcpy(&sysctl.u.pcitopoinfo, put_info, sizeof(*put_info)); + + if ( (ret = do_sysctl(xch, &sysctl)) != 0 ) + return ret; + + memcpy(put_info, &sysctl.u.pcitopoinfo, sizeof(*put_info)); + + return 0; +} + int xc_numainfo(xc_interface *xch, xc_numainfo_t *put_info) { diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index cd87614..888f068 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -5121,6 +5121,64 @@ 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); + xc_pcitopoinfo_t tinfo; + DECLARE_HYPERCALL_BUFFER(xen_sysctl_pcitopo_t, pcitopo); + libxl_pcitopology *ret = NULL; + int i, rc; + + tinfo.num_devs = libxl__pci_numdevs(gc); + if (tinfo.num_devs <= 0) { + LIBXL__LOG(ctx, XTL_ERROR, "Unable to determine number of PCI devices"); + goto out; + } + + pcitopo = xc_hypercall_buffer_alloc(ctx->xch, pcitopo, + sizeof(*pcitopo) * tinfo.num_devs); + if (pcitopo == NULL) { + LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, ENOMEM, + "Unable to allocate hypercall arguments"); + goto out; + } + + rc = libxl__pci_topology_init(gc, pcitopo, tinfo.num_devs); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "Cannot initialize PCI" + " hypercall structure"); + goto fail; + } + + tinfo.first_dev = 0; + + set_xen_guest_handle(tinfo.pcitopo, pcitopo); + + if (xc_pcitopoinfo(ctx->xch, &tinfo) != 0) { + LIBXL__LOG_ERRNO(ctx, XTL_ERROR, "PCI topology info hypercall failed"); + goto fail; + } + + ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * tinfo.num_devs); + + for (i = 0; i < tinfo.num_devs; i++) { + ret[i].seg = pcitopo[i].pcidev.seg; + ret[i].bus = pcitopo[i].pcidev.bus; + ret[i].devfn = pcitopo[i].pcidev.devfn; + ret[i].node = (pcitopo[i].node == INVALID_TOPOLOGY_ID) ? + LIBXL_PCITOPOLOGY_INVALID_ENTRY : pcitopo[i].node; + } + + *num_devs = tinfo.num_devs; + + fail: + xc_hypercall_buffer_free(ctx->xch, pcitopo); + + 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 0a123f1..eb83f0a 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1070,6 +1070,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_dev); +void libxl_pcitopology_list_free(libxl_pcitopology *, int num_dev); + #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..3cb11cd 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, + xen_sysctl_pcitopo_t *pcitopo, + int numdev) +{ + return ERROR_NI; +} diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 9695f18..453e652 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, + xen_sysctl_pcitopo_t *pcitopo, + 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..07428c0 100644 --- a/tools/libxl/libxl_linux.c +++ b/tools/libxl/libxl_linux.c @@ -279,3 +279,74 @@ 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__gc *gc) +{ + DIR *dir; + struct dirent *entry; + int numdev = 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; + numdev++; + } + closedir(dir); + + return numdev; +} + +int libxl__pci_topology_init(libxl__gc *gc, + xen_sysctl_pcitopo_t *pcitopo, + int numdev) +{ + + DIR *dir; + struct dirent *entry; + int i; + + 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 == numdev) { + LOGE(ERROR, "Too many devices\n"); + closedir(dir); + return ERROR_FAIL; + } + + if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4) { + LOGEV(ERROR, errno, "Error processing /sys/bus/pci/devices"); + closedir(dir); + return ERROR_FAIL; + } + + pcitopo[i].pcidev.seg = dom; + pcitopo[i].pcidev.bus = bus; + pcitopo[i].pcidev.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..743d439 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, + xen_sysctl_pcitopo_t *pcitopo, + int numdev) +{ + return ERROR_NI; +} 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 3737c7e..f2a3320 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -5195,12 +5195,14 @@ static void output_numainfo(void) static void output_topologyinfo(void) { - libxl_cputopology *info; + libxl_cputopology *cpuinfo; + libxl_pcitopology *pciinfo; int i, nr; + 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; } @@ -5208,12 +5210,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 |