[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH 4/8] libxl: calculate and set vcpu topology



Before creating vCPUs, assign an unique APIC_ID to each vCPU according the
number of vcpu, the number of core/thread in one socket/core and guest's numa
configuration. Refer to SDM "PROGRAMMING CONSIDERATIONS FOR HARDWARE
MULTI-THREADING CAPABLE PROCESSORS" for more information about how software
should extract topology from APIC_ID. The unique APIC_ID consists of three sub
fields: PACKAGE_ID, CORE_ID and SMT_ID.  PACKAGE_ID is the virtual numa ID (if
no numa information, PACKAGE_ID is always 0). CORE_ID and SMT_ID increase from
0.

Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx>
---
 tools/libxc/include/xenctrl.h |  7 +++++
 tools/libxc/xc_domain.c       | 36 ++++++++++++++++++++++
 tools/libxl/libxl_arch.h      |  4 +++
 tools/libxl/libxl_arm.c       |  6 ++++
 tools/libxl/libxl_dom.c       |  4 +++
 tools/libxl/libxl_types.idl   |  1 +
 tools/libxl/libxl_x86.c       | 70 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 128 insertions(+)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 09e1363..e897e5d 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1341,6 +1341,13 @@ int xc_domain_set_memory_map(xc_interface *xch,
 int xc_get_machine_memory_map(xc_interface *xch,
                               struct e820entry entries[],
                               uint32_t max_entries);
+
+int xc_set_cpu_topology(xc_interface *xch,
+                        uint32_t domid,
+                        uint32_t *tid,
+                        uint32_t size,
+                        uint8_t thread_per_core,
+                        uint8_t core_per_socket);
 #endif
 
 int xc_reserved_device_memory_map(xc_interface *xch,
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 3ccd27f..f8bb1eb 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -2435,6 +2435,42 @@ int xc_domain_soft_reset(xc_interface *xch,
     domctl.domain = domid;
     return do_domctl(xch, &domctl);
 }
+
+int xc_set_cpu_topology(xc_interface *xch,
+                        uint32_t domid,
+                        uint32_t *tid,
+                        uint32_t size,
+                        uint8_t thread_per_core,
+                        uint8_t core_per_socket)
+{
+    int rc;
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(tid, sizeof(*tid) * size,
+                             XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+
+    domctl.cmd = XEN_DOMCTL_set_cpu_topology;
+    domctl.domain = domid;
+
+    if ( xc_hypercall_bounce_pre(xch, tid) )
+    {
+        rc = -1;
+        errno = ENOMEM;
+        goto failed;
+    }
+
+    set_xen_guest_handle(domctl.u.cpu_topology.tid, tid);
+    domctl.u.cpu_topology.size = size;
+    domctl.u.cpu_topology.core_per_socket = core_per_socket;
+    domctl.u.cpu_topology.thread_per_core = thread_per_core;
+    memset(domctl.u.cpu_topology.pad, 0, sizeof(domctl.u.cpu_topology.pad));
+
+    rc = do_domctl(xch, &domctl);
+
+ failed:
+    xc_hypercall_bounce_post(xch, tid);
+
+    return rc;
+}
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index 784ec7f..61d9492 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -78,6 +78,10 @@ int libxl__arch_extra_memory(libxl__gc *gc,
                              const libxl_domain_build_info *info,
                              uint64_t *out);
 
+_hidden
+int libxl__arch_cpu_topology_init(libxl__gc *gc, uint32_t domid,
+                                  libxl_domain_config *d_config);
+
 #if defined(__i386__) || defined(__x86_64__)
 
 #define LAPIC_BASE_ADDRESS  0xfee00000
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index de1840b..70c328e 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -1154,6 +1154,12 @@ void libxl__arch_domain_build_info_acpi_setdefault(
     libxl_defbool_setdefault(&b_info->acpi, false);
 }
 
+int libxl__arch_cpu_topology_init(libxl__gc *gc, uint32_t domid,
+                                  libxl_domain_config *d_config)
+{
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index ef834e6..13e27d3 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -353,6 +353,10 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
     int rc;
     uint64_t size;
 
+    if (libxl__arch_cpu_topology_init(gc, domid, d_config)) {
+        return ERROR_FAIL;
+    }
+
     if (xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus) != 0) {
         LOG(ERROR, "Couldn't set max vcpu count");
         return ERROR_FAIL;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 8c80e67..6e0d96a 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -461,6 +461,7 @@ libxl_cpu_topology = Struct("cpu_topology", [
     ("cores",           uint8),
     ("threads",         uint8),
     ("real_threads",    uint8),
+    ("tid",             Array(uint32, "tid_size")),
     ])
 
 libxl_domain_build_info = Struct("domain_build_info",[
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index 5f91fe4..f28af46 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -596,6 +596,76 @@ void libxl__arch_domain_build_info_acpi_setdefault(
     libxl_defbool_setdefault(&b_info->acpi, true);
 }
 
+static inline int fls(unsigned int x)
+{
+    int r;
+
+    asm ( "bsr %1,%0\n\t"
+          "jnz 1f\n\t"
+          "mov $-1,%0\n"
+          "1:" : "=r" (r) : "rm" (x));
+    return r + 1;
+}
+
+int libxl__arch_cpu_topology_init(libxl__gc *gc, uint32_t domid,
+                                  libxl_domain_config *d_config)
+{
+    int i, rc = 0;
+    uint8_t core_shift, socket_shift, real_threads;
+    unsigned int *tid;
+    libxl_domain_build_info *const info = &d_config->b_info;
+
+    if (!info->u.hvm.cpu_topology.cores)
+        info->u.hvm.cpu_topology.cores = 128;
+    if (!info->u.hvm.cpu_topology.threads)
+        info->u.hvm.cpu_topology.threads = 2;
+    if (!info->u.hvm.cpu_topology.real_threads)
+        info->u.hvm.cpu_topology.real_threads = 1;
+
+    if (info->u.hvm.cpu_topology.threads <
+         info->u.hvm.cpu_topology.real_threads)
+    {
+        LOGE(ERROR, "threads cannot be smaller than real threads");
+        return ERROR_FAIL;
+    }
+
+    real_threads = info->u.hvm.cpu_topology.real_threads;
+    tid = libxl__calloc(gc, info->max_vcpus, sizeof(unsigned int));
+    core_shift = fls(info->u.hvm.cpu_topology.threads - 1);
+    socket_shift = core_shift + fls(info->u.hvm.cpu_topology.cores - 1);
+    if (info->num_vnuma_nodes == 0) {
+        for (i = 0; i < info->max_vcpus; i++) {
+            tid[i] = ((i / real_threads) << core_shift) + i % real_threads;
+        }
+    } else {
+        int socket_id;
+
+        for (socket_id = 0; socket_id < info->num_vnuma_nodes; socket_id++) {
+            int j = 0;
+
+            libxl_for_each_set_bit(i, info->vnuma_nodes[socket_id].vcpus) {
+                tid[i] = (socket_id << socket_shift) +
+                         ((j / real_threads) << core_shift) +
+                         (j % real_threads);
+                j++;
+            }
+        }
+    }
+
+    info->u.hvm.cpu_topology.tid = tid;
+    info->u.hvm.cpu_topology.tid_size = info->max_vcpus;
+
+    rc = xc_set_cpu_topology(libxl__gc_owner(gc)->xch, domid, tid,
+                             info->max_vcpus, info->u.hvm.cpu_topology.threads,
+                             info->u.hvm.cpu_topology.cores);
+    if (rc < 0) {
+        LOGE(ERROR, "xc_set_cpu_topology failed");
+        rc = ERROR_FAIL;
+    }
+
+    return rc;
+
+}
 /*
  * Local variables:
  * mode: C
-- 
1.8.3.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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