Yu, Ke
2009-Mar-13 09:00 UTC
[Xen-devel] [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@intel.com>
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;
};
};
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Akio Takebe
2009-Mar-13 09:46 UTC
Re: [Xen-devel] [PATCH] Add CPU topology info (thread/core/socket) in xenpm
Hi, Yu Good patch! We wanted this feature.> Add CPU topology info (thread/core/socket) in xenpmCan this patch show thread?> +#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 ; > +}The function looks like only show core/socket. Best Regards, Akio Takebe _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Akio Takebe
2009-Mar-13 10:46 UTC
Re: [Xen-devel] [PATCH] Add CPU topology info (thread/core/socket) in xenpm
Hi, Akio Takebe wrote:> Hi, Yu > > Good patch! We wanted this feature. > >> Add CPU topology info (thread/core/socket) in xenpm > Can this patch show thread? > >> +#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 ; >> +} > The function looks like only show core/socket. >Is the CPU%d means thread? Best Regards, Akio Takebe _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Yu Ke
2009-Mar-13 12:45 UTC
Re: [Xen-devel] [PATCH] Add CPU topology info (thread/core/socket) in xenpm
2009/3/13 Akio Takebe <takebe_akio@jp.fujitsu.com>:> Hi, > > Akio Takebe wrote: >> Hi, Yu >> >> Good patch! We wanted this feature. >> >>> Add CPU topology info (thread/core/socket) in xenpm >> Can this patch show thread? >> >>> +#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 ; >>> +} >> The function looks like only show core/socket. >> > Is the CPU%d means thread? > > Best Regards, > > Akio TakebeYes, you are right :) thread is the smallest unit, so here just use CPU for thread. A thread related example is, in a 2 sockets system, where 4 cores per socket and 2 threads per core, here is a possible output # 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 CPU8 0 0 CPU9 0 1 CPU10 1 0 CPU11 1 1 CPU12 2 0 CPU13 2 1 CPU14 3 0 CPU15 3 1 Indicating the following topology socket 0: core 0: CPU0 CPU8 core 1: CPU2 CPU10 core 2: CPU4 CPU12 core 3: CPU6 CPU14 socket 1: core 0: CPU1 CPU9 core 1: CPU3 CPU11 core 2: CPU5 CPU13 core 3: CPU7 CPU15 Probably later I can add one option to make xenpm output the above more human-readable format. Best Regards Ke Intel Open Source Technology Center _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel