[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.