WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Add CPU topology info (thread/core/socket) in xenpm

To: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] Add CPU topology info (thread/core/socket) in xenpm
From: "Yu, Ke" <ke.yu@xxxxxxxxx>
Date: Fri, 13 Mar 2009 17:00:52 +0800
Accept-language: en-US
Acceptlanguage: en-US
Cc: "Liu, Jinsong" <jinsong.liu@xxxxxxxxx>, "Tian, Kevin" <kevin.tian@xxxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>, "Wei, Gang" <gang.wei@xxxxxxxxx>
Delivery-date: Fri, 13 Mar 2009 02:02:31 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AcmjujZM19JRy/84QoSF81tx9HSEBA==
Thread-topic: [PATCH] Add CPU topology info (thread/core/socket) in xenpm
Add CPU topology info (thread/core/socket) in xenpm

CPU topology info is necessary for power management analysis. For example, to 
analysis the effect of Px state coordination, Cx package/core coordination,  
the thread/core/socket topology information is needed.

This patch add new command "get-cpu-topology" in xenpm to print the CPU 
topology info:

e.g. in a 2 sockets, 4 cores per socket machine, the output is as follow:
# xenpm get-cpu-topology
CPU     core    socket
CPU0     0       0
CPU1     0       1
CPU2     1       0
CPU3     1       1
CPU4     2       0
CPU5     2       1
CPU6     3       0
CPU7     3       1

indicating socket 0 has CPU 0,2,4,6, and socket 1 has CPU 1,3,5,7

Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>

diff -r 4fd39881f9f1 tools/libxc/xc_pm.c
--- a/tools/libxc/xc_pm.c
+++ b/tools/libxc/xc_pm.c
@@ -306,3 +306,24 @@ int xc_set_cpufreq_para(int xc_handle, i
 
     return xc_sysctl(xc_handle, &sysctl);
 }
+
+int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info)
+{
+    int rc;
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_cputopo;
+    sysctl.u.pm_op.cpuid = 0;
+    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_core,
+                         info->cpu_to_core );
+    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_socket,
+                         info->cpu_to_socket );
+    sysctl.u.pm_op.get_topo.max_cpus = info->max_cpus;
+
+    rc = do_sysctl(xc_handle, &sysctl);
+    info->nr_cpus = sysctl.u.pm_op.get_topo.nr_cpus;
+
+    return rc;
+}
+
diff -r 4fd39881f9f1 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1242,4 +1242,21 @@ int xc_set_cpufreq_gov(int xc_handle, in
 int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
 int xc_set_cpufreq_para(int xc_handle, int cpuid,
                         int ctrl_type, int ctrl_value);
+
+struct xc_get_cputopo {
+     /* IN: maximum addressable entry in
+      * the caller-provided cpu_to_core/socket.
+      */
+    uint32_t max_cpus;
+    uint32_t *cpu_to_core;
+    uint32_t *cpu_to_socket;
+
+    /* OUT: number of cpus returned
+     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
+     */
+    uint32_t nr_cpus;
+};
+
+int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info);
+
 #endif /* XENCTRL_H */
diff -r 4fd39881f9f1 tools/misc/xenpm.c
--- a/tools/misc/xenpm.c
+++ b/tools/misc/xenpm.c
@@ -58,6 +58,7 @@ void show_help(void)
             "                                     it is used in ondemand 
governor.\n"
             " set-up-threshold      [cpuid] <num> set up threshold on CPU 
<cpuid> or all\n"
             "                                     it is used in ondemand 
governor.\n"
+            " get-cpu-topology                    get thread/core/socket 
topology info\n"
             " start                               start collect Cx/Px 
statistics,\n"
             "                                     output after CTRL-C or 
SIGINT.\n"
             );
@@ -750,6 +751,40 @@ out:
     fprintf(stderr, "failed to set governor name\n");
 }
 
+#define MAX_NR_CPU 512
+
+void cpu_topology_func(int argc, char *argv[])
+{
+    uint32_t cpu_to_core[MAX_NR_CPU];
+    uint32_t cpu_to_socket[MAX_NR_CPU];
+    struct xc_get_cputopo info;
+    int i, ret;
+
+    info.cpu_to_core = cpu_to_core;
+    info.cpu_to_socket = cpu_to_socket;
+    info.max_cpus = MAX_NR_CPU;
+    ret = xc_get_cputopo(xc_fd, &info);
+    if (!ret)
+    {
+        printf("CPU\tcore\tsocket\n");
+        for (i=0; i<info.nr_cpus; i++)
+        {
+            if ( info.cpu_to_core[i] != INVALID_TOPOLOGY_ID &&
+                    info.cpu_to_socket[i] != INVALID_TOPOLOGY_ID )
+            {
+            printf("CPU%d\t %d\t %d\n", i, info.cpu_to_core[i],
+                    info.cpu_to_socket[i]);
+            }
+        }
+    }
+    else
+    {
+        printf("Can not get Xen CPU topology!\n");
+    }
+
+    return ;
+}
+
 struct {
     const char *name;
     void (*function)(int argc, char *argv[]);
@@ -765,6 +800,7 @@ struct {
     { "set-scaling-speed", scaling_speed_func },
     { "set-sampling-rate", scaling_sampling_rate_func },
     { "set-up-threshold", scaling_up_threshold_func },
+    { "get-cpu-topology", cpu_topology_func},
 };
 
 int main(int argc, char *argv[])
diff -r 4fd39881f9f1 xen/common/sysctl.c
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -224,12 +224,11 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
         if ( ret && (ret != -EAGAIN) )
             break;
 
-        if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA )
-            if ( copy_to_guest(u_sysctl, op, 1) )
-            {
-                ret = -EFAULT;
-                break;
-            }
+        if ( copy_to_guest(u_sysctl, op, 1) )
+        {
+            ret = -EFAULT;
+            break;
+        }
     }
     break;
 
diff -r 4fd39881f9f1 xen/drivers/acpi/pmstat.c
--- a/xen/drivers/acpi/pmstat.c
+++ b/xen/drivers/acpi/pmstat.c
@@ -416,6 +416,52 @@ static int set_cpufreq_para(struct xen_s
     return ret;
 }
 
+static int get_cputopo (struct xen_sysctl_pm_op *op)
+{
+    uint32_t i, nr_cpus;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_core_arr;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket_arr;
+    int arr_size, ret=0;
+
+    cpu_to_core_arr = op->get_topo.cpu_to_core;
+    cpu_to_socket_arr = op->get_topo.cpu_to_socket;
+    arr_size= min_t(uint32_t, op->get_topo.max_cpus, NR_CPUS);
+
+    if ( guest_handle_is_null( cpu_to_core_arr ) ||
+            guest_handle_is_null(  cpu_to_socket_arr) )
+    {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    nr_cpus = 0;
+    for ( i = 0; i < arr_size; i++ )
+    {
+        uint32_t core, socket;
+        if ( cpu_online(i) )
+        {
+            core = cpu_to_core(i);
+            socket = cpu_to_socket(i);
+            nr_cpus = i;
+        }
+        else
+        {
+            core = socket = INVALID_TOPOLOGY_ID;
+        }
+
+        if ( copy_to_guest_offset(cpu_to_core_arr, i, &core, 1) ||
+                copy_to_guest_offset(cpu_to_socket_arr, i, &socket, 1))
+        {
+            ret = -EFAULT;
+            goto out;
+        }
+    }
+
+    op->get_topo.nr_cpus = nr_cpus + 1;
+out:
+    return ret;
+}
+
 int do_pm_op(struct xen_sysctl_pm_op *op)
 {
     int ret = 0;
@@ -433,8 +479,6 @@ int do_pm_op(struct xen_sysctl_pm_op *op
         if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) )
             return -EINVAL;
         break;
-    default:
-        return -ENODEV;
     }
 
     switch ( op->cmd )
@@ -457,6 +501,12 @@ int do_pm_op(struct xen_sysctl_pm_op *op
         break;
     }
 
+    case XEN_SYSCTL_pm_op_get_cputopo:
+    {
+        ret = get_cputopo(op);
+        break;
+    }
+
     default:
         printk("not defined sub-hypercall @ do_pm_op\n");
         ret = -ENOSYS;
diff -r 4fd39881f9f1 xen/include/asm-ia64/linux-xen/asm/processor.h
--- a/xen/include/asm-ia64/linux-xen/asm/processor.h
+++ b/xen/include/asm-ia64/linux-xen/asm/processor.h
@@ -197,6 +197,14 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, cpu
  */
 #define local_cpu_data         (&__ia64_per_cpu_var(cpu_info))
 #define cpu_data(cpu)          (&per_cpu(cpu_info, cpu))
+
+#ifdef CONFIG_SMP
+#define cpu_to_core(cpu)    (cpu_data(cpu)->core_id)
+#define cpu_to_socket(cpu)  (cpu_data(cpu)->socket_id)
+#else
+#define cpu_to_core(cpu)    0
+#define cpu_to_socket(cpu)  0
+#endif
 
 extern void identify_cpu (struct cpuinfo_ia64 *);
 extern void print_cpu_info (struct cpuinfo_ia64 *);
diff -r 4fd39881f9f1 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -203,6 +203,9 @@ extern void detect_ht(struct cpuinfo_x86
 #else
 static always_inline void detect_ht(struct cpuinfo_x86 *c) {}
 #endif
+
+#define cpu_to_core(_cpu)   (cpu_core_id[_cpu])
+#define cpu_to_socket(_cpu) (phys_proc_id[_cpu])
 
 /*
  * Generic CPUID function
diff -r 4fd39881f9f1 xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -339,6 +339,24 @@ struct xen_set_cpufreq_para {
 
     uint32_t ctrl_type;
     uint32_t ctrl_value;
+}
+;
+/* Get physical CPU topology information. */
+
+
+#define INVALID_TOPOLOGY_ID  (~0U)
+struct xen_get_cputopo {
+     /* IN: maximum addressable entry in
+      * the caller-provided cpu_to_core/socket.
+      */
+    uint32_t max_cpus;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
+
+    /* OUT: number of cpus returned
+     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
+     */
+    uint32_t nr_cpus;
 };
 
 struct xen_sysctl_pm_op {
@@ -350,12 +368,16 @@ struct xen_sysctl_pm_op {
     #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
     #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
 
+    /* get CPU topology */
+    #define XEN_SYSCTL_pm_op_get_cputopo  0x20
+
     uint32_t cmd;
     uint32_t cpuid;
     union {
         struct xen_get_cpufreq_para get_para;
         struct xen_set_cpufreq_gov  set_gov;
         struct xen_set_cpufreq_para set_para;
+        struct xen_get_cputopo      get_topo;
     };
 };

Attachment: cpu-topology.patch
Description: cpu-topology.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel