ia64/xen-unstable

changeset 19360:0e1449d6f231

xenpm: Add CPU topology info (thread/core/socket)

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:

Signed-off-by: Yu Ke <ke.yu@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Mar 13 10:09:25 2009 +0000 (2009-03-13)
parents 4fd39881f9f1
children 24af58657d8e
files tools/libxc/xc_pm.c tools/libxc/xenctrl.h tools/misc/xenpm.c xen/common/sysctl.c xen/drivers/acpi/pmstat.c xen/include/asm-ia64/linux-xen/asm/processor.h xen/include/asm-x86/processor.h xen/include/public/sysctl.h
line diff
     1.1 --- a/tools/libxc/xc_pm.c	Fri Mar 13 07:45:11 2009 +0000
     1.2 +++ b/tools/libxc/xc_pm.c	Fri Mar 13 10:09:25 2009 +0000
     1.3 @@ -306,3 +306,24 @@ int xc_set_cpufreq_para(int xc_handle, i
     1.4  
     1.5      return xc_sysctl(xc_handle, &sysctl);
     1.6  }
     1.7 +
     1.8 +int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info)
     1.9 +{
    1.10 +    int rc;
    1.11 +    DECLARE_SYSCTL;
    1.12 +
    1.13 +    sysctl.cmd = XEN_SYSCTL_pm_op;
    1.14 +    sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_cputopo;
    1.15 +    sysctl.u.pm_op.cpuid = 0;
    1.16 +    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_core,
    1.17 +                         info->cpu_to_core );
    1.18 +    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_socket,
    1.19 +                         info->cpu_to_socket );
    1.20 +    sysctl.u.pm_op.get_topo.max_cpus = info->max_cpus;
    1.21 +
    1.22 +    rc = do_sysctl(xc_handle, &sysctl);
    1.23 +    info->nr_cpus = sysctl.u.pm_op.get_topo.nr_cpus;
    1.24 +
    1.25 +    return rc;
    1.26 +}
    1.27 +
     2.1 --- a/tools/libxc/xenctrl.h	Fri Mar 13 07:45:11 2009 +0000
     2.2 +++ b/tools/libxc/xenctrl.h	Fri Mar 13 10:09:25 2009 +0000
     2.3 @@ -1242,4 +1242,21 @@ int xc_get_cpufreq_para(int xc_handle, i
     2.4  int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
     2.5  int xc_set_cpufreq_para(int xc_handle, int cpuid,
     2.6                          int ctrl_type, int ctrl_value);
     2.7 +
     2.8 +struct xc_get_cputopo {
     2.9 +     /* IN: maximum addressable entry in
    2.10 +      * the caller-provided cpu_to_core/socket.
    2.11 +      */
    2.12 +    uint32_t max_cpus;
    2.13 +    uint32_t *cpu_to_core;
    2.14 +    uint32_t *cpu_to_socket;
    2.15 +
    2.16 +    /* OUT: number of cpus returned
    2.17 +     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
    2.18 +     */
    2.19 +    uint32_t nr_cpus;
    2.20 +};
    2.21 +
    2.22 +int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info);
    2.23 +
    2.24  #endif /* XENCTRL_H */
     3.1 --- a/tools/misc/xenpm.c	Fri Mar 13 07:45:11 2009 +0000
     3.2 +++ b/tools/misc/xenpm.c	Fri Mar 13 10:09:25 2009 +0000
     3.3 @@ -58,6 +58,7 @@ void show_help(void)
     3.4              "                                     it is used in ondemand governor.\n"
     3.5              " set-up-threshold      [cpuid] <num> set up threshold on CPU <cpuid> or all\n"
     3.6              "                                     it is used in ondemand governor.\n"
     3.7 +            " get-cpu-topology                    get thread/core/socket topology info\n"
     3.8              " start                               start collect Cx/Px statistics,\n"
     3.9              "                                     output after CTRL-C or SIGINT.\n"
    3.10              );
    3.11 @@ -750,6 +751,40 @@ out:
    3.12      fprintf(stderr, "failed to set governor name\n");
    3.13  }
    3.14  
    3.15 +#define MAX_NR_CPU 512
    3.16 +
    3.17 +void cpu_topology_func(int argc, char *argv[])
    3.18 +{
    3.19 +    uint32_t cpu_to_core[MAX_NR_CPU];
    3.20 +    uint32_t cpu_to_socket[MAX_NR_CPU];
    3.21 +    struct xc_get_cputopo info;
    3.22 +    int i, ret;
    3.23 +
    3.24 +    info.cpu_to_core = cpu_to_core;
    3.25 +    info.cpu_to_socket = cpu_to_socket;
    3.26 +    info.max_cpus = MAX_NR_CPU;
    3.27 +    ret = xc_get_cputopo(xc_fd, &info);
    3.28 +    if (!ret)
    3.29 +    {
    3.30 +        printf("CPU\tcore\tsocket\n");
    3.31 +        for (i=0; i<info.nr_cpus; i++)
    3.32 +        {
    3.33 +            if ( info.cpu_to_core[i] != INVALID_TOPOLOGY_ID &&
    3.34 +                    info.cpu_to_socket[i] != INVALID_TOPOLOGY_ID )
    3.35 +            {
    3.36 +            printf("CPU%d\t %d\t %d\n", i, info.cpu_to_core[i],
    3.37 +                    info.cpu_to_socket[i]);
    3.38 +            }
    3.39 +        }
    3.40 +    }
    3.41 +    else
    3.42 +    {
    3.43 +        printf("Can not get Xen CPU topology!\n");
    3.44 +    }
    3.45 +
    3.46 +    return ;
    3.47 +}
    3.48 +
    3.49  struct {
    3.50      const char *name;
    3.51      void (*function)(int argc, char *argv[]);
    3.52 @@ -765,6 +800,7 @@ struct {
    3.53      { "set-scaling-speed", scaling_speed_func },
    3.54      { "set-sampling-rate", scaling_sampling_rate_func },
    3.55      { "set-up-threshold", scaling_up_threshold_func },
    3.56 +    { "get-cpu-topology", cpu_topology_func},
    3.57  };
    3.58  
    3.59  int main(int argc, char *argv[])
     4.1 --- a/xen/common/sysctl.c	Fri Mar 13 07:45:11 2009 +0000
     4.2 +++ b/xen/common/sysctl.c	Fri Mar 13 10:09:25 2009 +0000
     4.3 @@ -224,12 +224,11 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
     4.4          if ( ret && (ret != -EAGAIN) )
     4.5              break;
     4.6  
     4.7 -        if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA )
     4.8 -            if ( copy_to_guest(u_sysctl, op, 1) )
     4.9 -            {
    4.10 -                ret = -EFAULT;
    4.11 -                break;
    4.12 -            }
    4.13 +        if ( copy_to_guest(u_sysctl, op, 1) )
    4.14 +        {
    4.15 +            ret = -EFAULT;
    4.16 +            break;
    4.17 +        }
    4.18      }
    4.19      break;
    4.20  
     5.1 --- a/xen/drivers/acpi/pmstat.c	Fri Mar 13 07:45:11 2009 +0000
     5.2 +++ b/xen/drivers/acpi/pmstat.c	Fri Mar 13 10:09:25 2009 +0000
     5.3 @@ -416,6 +416,52 @@ static int set_cpufreq_para(struct xen_s
     5.4      return ret;
     5.5  }
     5.6  
     5.7 +static int get_cputopo (struct xen_sysctl_pm_op *op)
     5.8 +{
     5.9 +    uint32_t i, nr_cpus;
    5.10 +    XEN_GUEST_HANDLE_64(uint32) cpu_to_core_arr;
    5.11 +    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket_arr;
    5.12 +    int arr_size, ret=0;
    5.13 +
    5.14 +    cpu_to_core_arr = op->get_topo.cpu_to_core;
    5.15 +    cpu_to_socket_arr = op->get_topo.cpu_to_socket;
    5.16 +    arr_size= min_t(uint32_t, op->get_topo.max_cpus, NR_CPUS);
    5.17 +
    5.18 +    if ( guest_handle_is_null( cpu_to_core_arr ) ||
    5.19 +            guest_handle_is_null(  cpu_to_socket_arr) )
    5.20 +    {
    5.21 +        ret = -EINVAL;
    5.22 +        goto out;
    5.23 +    }
    5.24 +
    5.25 +    nr_cpus = 0;
    5.26 +    for ( i = 0; i < arr_size; i++ )
    5.27 +    {
    5.28 +        uint32_t core, socket;
    5.29 +        if ( cpu_online(i) )
    5.30 +        {
    5.31 +            core = cpu_to_core(i);
    5.32 +            socket = cpu_to_socket(i);
    5.33 +            nr_cpus = i;
    5.34 +        }
    5.35 +        else
    5.36 +        {
    5.37 +            core = socket = INVALID_TOPOLOGY_ID;
    5.38 +        }
    5.39 +
    5.40 +        if ( copy_to_guest_offset(cpu_to_core_arr, i, &core, 1) ||
    5.41 +                copy_to_guest_offset(cpu_to_socket_arr, i, &socket, 1))
    5.42 +        {
    5.43 +            ret = -EFAULT;
    5.44 +            goto out;
    5.45 +        }
    5.46 +    }
    5.47 +
    5.48 +    op->get_topo.nr_cpus = nr_cpus + 1;
    5.49 +out:
    5.50 +    return ret;
    5.51 +}
    5.52 +
    5.53  int do_pm_op(struct xen_sysctl_pm_op *op)
    5.54  {
    5.55      int ret = 0;
    5.56 @@ -433,8 +479,6 @@ int do_pm_op(struct xen_sysctl_pm_op *op
    5.57          if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) )
    5.58              return -EINVAL;
    5.59          break;
    5.60 -    default:
    5.61 -        return -ENODEV;
    5.62      }
    5.63  
    5.64      switch ( op->cmd )
    5.65 @@ -457,6 +501,12 @@ int do_pm_op(struct xen_sysctl_pm_op *op
    5.66          break;
    5.67      }
    5.68  
    5.69 +    case XEN_SYSCTL_pm_op_get_cputopo:
    5.70 +    {
    5.71 +        ret = get_cputopo(op);
    5.72 +        break;
    5.73 +    }
    5.74 +
    5.75      default:
    5.76          printk("not defined sub-hypercall @ do_pm_op\n");
    5.77          ret = -ENOSYS;
     6.1 --- a/xen/include/asm-ia64/linux-xen/asm/processor.h	Fri Mar 13 07:45:11 2009 +0000
     6.2 +++ b/xen/include/asm-ia64/linux-xen/asm/processor.h	Fri Mar 13 10:09:25 2009 +0000
     6.3 @@ -198,6 +198,14 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, cpu
     6.4  #define local_cpu_data		(&__ia64_per_cpu_var(cpu_info))
     6.5  #define cpu_data(cpu)		(&per_cpu(cpu_info, cpu))
     6.6  
     6.7 +#ifdef CONFIG_SMP
     6.8 +#define cpu_to_core(cpu)    (cpu_data(cpu)->core_id)
     6.9 +#define cpu_to_socket(cpu)  (cpu_data(cpu)->socket_id)
    6.10 +#else
    6.11 +#define cpu_to_core(cpu)    0
    6.12 +#define cpu_to_socket(cpu)  0
    6.13 +#endif
    6.14 +
    6.15  extern void identify_cpu (struct cpuinfo_ia64 *);
    6.16  extern void print_cpu_info (struct cpuinfo_ia64 *);
    6.17  
     7.1 --- a/xen/include/asm-x86/processor.h	Fri Mar 13 07:45:11 2009 +0000
     7.2 +++ b/xen/include/asm-x86/processor.h	Fri Mar 13 10:09:25 2009 +0000
     7.3 @@ -204,6 +204,9 @@ extern void detect_ht(struct cpuinfo_x86
     7.4  static always_inline void detect_ht(struct cpuinfo_x86 *c) {}
     7.5  #endif
     7.6  
     7.7 +#define cpu_to_core(_cpu)   (cpu_core_id[_cpu])
     7.8 +#define cpu_to_socket(_cpu) (phys_proc_id[_cpu])
     7.9 +
    7.10  /*
    7.11   * Generic CPUID function
    7.12   * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
     8.1 --- a/xen/include/public/sysctl.h	Fri Mar 13 07:45:11 2009 +0000
     8.2 +++ b/xen/include/public/sysctl.h	Fri Mar 13 10:09:25 2009 +0000
     8.3 @@ -339,6 +339,24 @@ struct xen_set_cpufreq_para {
     8.4  
     8.5      uint32_t ctrl_type;
     8.6      uint32_t ctrl_value;
     8.7 +}
     8.8 +;
     8.9 +/* Get physical CPU topology information. */
    8.10 +
    8.11 +
    8.12 +#define INVALID_TOPOLOGY_ID  (~0U)
    8.13 +struct xen_get_cputopo {
    8.14 +     /* IN: maximum addressable entry in
    8.15 +      * the caller-provided cpu_to_core/socket.
    8.16 +      */
    8.17 +    uint32_t max_cpus;
    8.18 +    XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
    8.19 +    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
    8.20 +
    8.21 +    /* OUT: number of cpus returned
    8.22 +     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
    8.23 +     */
    8.24 +    uint32_t nr_cpus;
    8.25  };
    8.26  
    8.27  struct xen_sysctl_pm_op {
    8.28 @@ -350,12 +368,16 @@ struct xen_sysctl_pm_op {
    8.29      #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
    8.30      #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
    8.31  
    8.32 +    /* get CPU topology */
    8.33 +    #define XEN_SYSCTL_pm_op_get_cputopo  0x20
    8.34 +
    8.35      uint32_t cmd;
    8.36      uint32_t cpuid;
    8.37      union {
    8.38          struct xen_get_cpufreq_para get_para;
    8.39          struct xen_set_cpufreq_gov  set_gov;
    8.40          struct xen_set_cpufreq_para set_para;
    8.41 +        struct xen_get_cputopo      get_topo;
    8.42      };
    8.43  };
    8.44