ia64/xen-unstable

changeset 17690:ef019d230080

Add statistic interface for cx.

Implement statistic interface for cx via sysctl & libxc. Provide a
easy way to collect processor cx info within dom0.

Signed-off-by: Wei Gang <gang.wei@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed May 21 10:59:49 2008 +0100 (2008-05-21)
parents b9735935a69e
children ff23c9a11085
files tools/libxc/xc_pm.c tools/libxc/xenctrl.h xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/acpi/pmstat.c xen/include/public/sysctl.h
line diff
     1.1 --- a/tools/libxc/xc_pm.c	Wed May 21 10:59:00 2008 +0100
     1.2 +++ b/tools/libxc/xc_pm.c	Wed May 21 10:59:49 2008 +0100
     1.3 @@ -99,3 +99,71 @@ int xc_pm_reset_pxstat(int xc_handle, in
     1.4  
     1.5      return xc_sysctl(xc_handle, &sysctl);
     1.6  }
     1.7 +
     1.8 +int xc_pm_get_max_cx(int xc_handle, int cpuid, int *max_cx)
     1.9 +{
    1.10 +    DECLARE_SYSCTL;
    1.11 +    int ret = 0;
    1.12 +
    1.13 +    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    1.14 +    sysctl.u.get_pmstat.type = PMSTAT_get_max_cx;
    1.15 +    sysctl.u.get_pmstat.cpuid = cpuid;
    1.16 +    if ( (ret = xc_sysctl(xc_handle, &sysctl)) != 0 )
    1.17 +        return ret;
    1.18 +
    1.19 +    *max_cx = sysctl.u.get_pmstat.u.getcx.nr;
    1.20 +    return ret;
    1.21 +}
    1.22 +
    1.23 +int xc_pm_get_cxstat(int xc_handle, int cpuid, struct xc_cx_stat *cxpt)
    1.24 +{
    1.25 +    DECLARE_SYSCTL;
    1.26 +    int max_cx, ret;
    1.27 +
    1.28 +    if( !cxpt || !(cxpt->triggers) || !(cxpt->residencies) )
    1.29 +        return -EINVAL;
    1.30 +
    1.31 +    if ( (ret = xc_pm_get_max_cx(xc_handle, cpuid, &max_cx)) )
    1.32 +        goto unlock_0;
    1.33 +
    1.34 +    if ( (ret = lock_pages(cxpt, sizeof(struct xc_cx_stat))) )
    1.35 +        goto unlock_0;
    1.36 +    if ( (ret = lock_pages(cxpt->triggers, max_cx * sizeof(uint64_t))) )
    1.37 +        goto unlock_1;
    1.38 +    if ( (ret = lock_pages(cxpt->residencies, max_cx * sizeof(uint64_t))) )
    1.39 +        goto unlock_2;
    1.40 +
    1.41 +    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    1.42 +    sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
    1.43 +    sysctl.u.get_pmstat.cpuid = cpuid;
    1.44 +    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, cxpt->triggers);
    1.45 +    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies, 
    1.46 +                         cxpt->residencies);
    1.47 +
    1.48 +    if ( (ret = xc_sysctl(xc_handle, &sysctl)) )
    1.49 +        goto unlock_3;
    1.50 +
    1.51 +    cxpt->nr = sysctl.u.get_pmstat.u.getcx.nr;
    1.52 +    cxpt->last = sysctl.u.get_pmstat.u.getcx.last;
    1.53 +    cxpt->idle_time = sysctl.u.get_pmstat.u.getcx.idle_time;
    1.54 +
    1.55 +unlock_3:
    1.56 +    unlock_pages(cxpt->residencies, max_cx * sizeof(uint64_t));
    1.57 +unlock_2:
    1.58 +    unlock_pages(cxpt->triggers, max_cx * sizeof(uint64_t));
    1.59 +unlock_1:
    1.60 +    unlock_pages(cxpt, sizeof(struct xc_cx_stat));
    1.61 +unlock_0:
    1.62 +    return ret;
    1.63 +}
    1.64 +
    1.65 +int xc_pm_reset_cxstat(int xc_handle, int cpuid)
    1.66 +{
    1.67 +    DECLARE_SYSCTL;
    1.68 +
    1.69 +    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    1.70 +    sysctl.u.get_pmstat.type = PMSTAT_reset_cxstat;
    1.71 +    sysctl.u.get_pmstat.cpuid = cpuid;
    1.72 +
    1.73 +    return xc_sysctl(xc_handle, &sysctl);
    1.74 +}
     2.1 --- a/tools/libxc/xenctrl.h	Wed May 21 10:59:00 2008 +0100
     2.2 +++ b/tools/libxc/xenctrl.h	Wed May 21 10:59:49 2008 +0100
     2.3 @@ -1053,4 +1053,17 @@ int xc_pm_get_max_px(int xc_handle, int 
     2.4  int xc_pm_get_pxstat(int xc_handle, int cpuid, struct xc_px_stat *pxpt);
     2.5  int xc_pm_reset_pxstat(int xc_handle, int cpuid);
     2.6  
     2.7 +struct xc_cx_stat {
     2.8 +    uint32_t nr;    /* entry nr in triggers & residencies, including C0 */
     2.9 +    uint32_t last;         /* last Cx state */
    2.10 +    uint64_t idle_time;    /* idle time from boot */
    2.11 +    uint64_t *triggers;    /* Cx trigger counts */
    2.12 +    uint64_t *residencies; /* Cx residencies */
    2.13 +};
    2.14 +typedef struct xc_cx_stat xc_cx_stat_t;
    2.15 +
    2.16 +int xc_pm_get_max_cx(int xc_handle, int cpuid, int *max_cx);
    2.17 +int xc_pm_get_cxstat(int xc_handle, int cpuid, struct xc_cx_stat *cxpt);
    2.18 +int xc_pm_reset_cxstat(int xc_handle, int cpuid);
    2.19 +
    2.20  #endif /* XENCTRL_H */
     3.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Wed May 21 10:59:00 2008 +0100
     3.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Wed May 21 10:59:49 2008 +0100
     3.3 @@ -44,6 +44,7 @@
     3.4  #include <asm/hpet.h>
     3.5  #include <asm/processor.h>
     3.6  #include <public/platform.h>
     3.7 +#include <public/sysctl.h>
     3.8  
     3.9  #define DEBUG_PM_CX
    3.10  
    3.11 @@ -940,3 +941,41 @@ long set_cx_pminfo(uint32_t cpu, struct 
    3.12          
    3.13      return 0;
    3.14  }
    3.15 +
    3.16 +uint32_t pmstat_get_cx_nr(uint32_t cpuid)
    3.17 +{
    3.18 +    return processor_powers[cpuid].count;
    3.19 +}
    3.20 +
    3.21 +int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
    3.22 +{
    3.23 +    struct acpi_processor_power *power = &processor_powers[cpuid];
    3.24 +    struct vcpu *v = idle_vcpu[cpuid];
    3.25 +    uint64_t usage;
    3.26 +    int i;
    3.27 +
    3.28 +    stat->last = (power->state) ? power->state->type : 0;
    3.29 +    stat->nr = processor_powers[cpuid].count;
    3.30 +    stat->idle_time = v->runstate.time[RUNSTATE_running];
    3.31 +    if ( v->is_running )
    3.32 +        stat->idle_time += NOW() - v->runstate.state_entry_time;
    3.33 +
    3.34 +    for ( i = 0; i < power->count; i++ )
    3.35 +    {
    3.36 +        usage = power->states[i].usage;
    3.37 +        if ( copy_to_guest_offset(stat->triggers, i, &usage, 1) )
    3.38 +            return -EFAULT;
    3.39 +    }
    3.40 +    for ( i = 0; i < power->count; i++ )
    3.41 +        if ( copy_to_guest_offset(stat->residencies, i, 
    3.42 +                                  &power->states[i].time, 1) )
    3.43 +            return -EFAULT;
    3.44 +
    3.45 +    return 0;
    3.46 +}
    3.47 +
    3.48 +int pmstat_reset_cx_stat(uint32_t cpuid)
    3.49 +{
    3.50 +    return 0;
    3.51 +}
    3.52 +
     4.1 --- a/xen/arch/x86/acpi/pmstat.c	Wed May 21 10:59:00 2008 +0100
     4.2 +++ b/xen/arch/x86/acpi/pmstat.c	Wed May 21 10:59:49 2008 +0100
     4.3 @@ -42,6 +42,10 @@
     4.4  
     4.5  struct pm_px px_statistic_data[NR_CPUS];
     4.6  
     4.7 +extern uint32_t pmstat_get_cx_nr(uint32_t cpuid);
     4.8 +extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat);
     4.9 +extern int pmstat_reset_cx_stat(uint32_t cpuid);
    4.10 +
    4.11  int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
    4.12  {
    4.13      int ret = 0;
    4.14 @@ -50,7 +54,7 @@ int do_get_pm_info(struct xen_sysctl_get
    4.15  
    4.16      /* to protect the case when Px was controlled by dom0-kernel */
    4.17      /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */
    4.18 -    if ( !pmpt->perf.init )
    4.19 +    if ( !pmpt->perf.init && (op->type & PMSTAT_CATEGORY_MASK) == PMSTAT_PX )
    4.20          return -EINVAL;
    4.21  
    4.22      if ( !cpu_online(op->cpuid) )
    4.23 @@ -100,6 +104,25 @@ int do_get_pm_info(struct xen_sysctl_get
    4.24          break;
    4.25      }
    4.26  
    4.27 +    case PMSTAT_get_max_cx:
    4.28 +    {
    4.29 +        op->u.getcx.nr = pmstat_get_cx_nr(op->cpuid);
    4.30 +        ret = 0;
    4.31 +        break;
    4.32 +    }
    4.33 +
    4.34 +    case PMSTAT_get_cxstat:
    4.35 +    {
    4.36 +        ret = pmstat_get_cx_stat(op->cpuid, &op->u.getcx);
    4.37 +        break;
    4.38 +    }
    4.39 +
    4.40 +    case PMSTAT_reset_cxstat:
    4.41 +    {
    4.42 +        ret = pmstat_reset_cx_stat(op->cpuid);
    4.43 +        break;
    4.44 +    }
    4.45 +
    4.46      default:
    4.47          printk("not defined sub-hypercall @ do_get_pm_info\n");
    4.48          ret = -ENOSYS;
     5.1 --- a/xen/include/public/sysctl.h	Wed May 21 10:59:00 2008 +0100
     5.2 +++ b/xen/include/public/sysctl.h	Wed May 21 10:59:49 2008 +0100
     5.3 @@ -233,15 +233,30 @@ struct pm_px_stat {
     5.4  typedef struct pm_px_stat pm_px_stat_t;
     5.5  DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t);
     5.6  
     5.7 +struct pm_cx_stat {
     5.8 +    uint32_t nr;    /* entry nr in triggers & residencies, including C0 */
     5.9 +    uint32_t last;  /* last Cx state */
    5.10 +    uint64_aligned_t idle_time;                 /* idle time from boot */
    5.11 +    XEN_GUEST_HANDLE_64(uint64) triggers;    /* Cx trigger counts */
    5.12 +    XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
    5.13 +};
    5.14 +
    5.15  struct xen_sysctl_get_pmstat {
    5.16 -#define PMSTAT_get_max_px   0x11
    5.17 -#define PMSTAT_get_pxstat   0x12
    5.18 -#define PMSTAT_reset_pxstat 0x13
    5.19 +#define PMSTAT_CATEGORY_MASK 0xf0
    5.20 +#define PMSTAT_PX            0x10
    5.21 +#define PMSTAT_CX            0x20
    5.22 +#define PMSTAT_get_max_px    (PMSTAT_PX | 0x1)
    5.23 +#define PMSTAT_get_pxstat    (PMSTAT_PX | 0x2)
    5.24 +#define PMSTAT_reset_pxstat  (PMSTAT_PX | 0x3)
    5.25 +#define PMSTAT_get_max_cx    (PMSTAT_CX | 0x1)
    5.26 +#define PMSTAT_get_cxstat    (PMSTAT_CX | 0x2)
    5.27 +#define PMSTAT_reset_cxstat  (PMSTAT_CX | 0x3)
    5.28      uint32_t type;
    5.29      uint32_t cpuid;
    5.30      union {
    5.31          struct pm_px_stat getpx;
    5.32 -        /* other struct for cx, tx, etc */
    5.33 +        struct pm_cx_stat getcx;
    5.34 +        /* other struct for tx, etc */
    5.35      } u;
    5.36  };
    5.37  typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;