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

[Xen-changelog] [xen-unstable] Add statistic interface for cx.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1211363989 -3600
# Node ID ef019d230080cc1c85a3a9a79c170f898db6be53
# Parent  b9735935a69e49e4caaed8844a50a227bd0725c7
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@xxxxxxxxx>
---
 tools/libxc/xc_pm.c          |   68 +++++++++++++++++++++++++++++++++++++++++++
 tools/libxc/xenctrl.h        |   13 ++++++++
 xen/arch/x86/acpi/cpu_idle.c |   39 ++++++++++++++++++++++++
 xen/arch/x86/acpi/pmstat.c   |   25 +++++++++++++++
 xen/include/public/sysctl.h  |   23 ++++++++++++--
 5 files changed, 163 insertions(+), 5 deletions(-)

diff -r b9735935a69e -r ef019d230080 tools/libxc/xc_pm.c
--- a/tools/libxc/xc_pm.c       Wed May 21 10:59:00 2008 +0100
+++ b/tools/libxc/xc_pm.c       Wed May 21 10:59:49 2008 +0100
@@ -99,3 +99,71 @@ int xc_pm_reset_pxstat(int xc_handle, in
 
     return xc_sysctl(xc_handle, &sysctl);
 }
+
+int xc_pm_get_max_cx(int xc_handle, int cpuid, int *max_cx)
+{
+    DECLARE_SYSCTL;
+    int ret = 0;
+
+    sysctl.cmd = XEN_SYSCTL_get_pmstat;
+    sysctl.u.get_pmstat.type = PMSTAT_get_max_cx;
+    sysctl.u.get_pmstat.cpuid = cpuid;
+    if ( (ret = xc_sysctl(xc_handle, &sysctl)) != 0 )
+        return ret;
+
+    *max_cx = sysctl.u.get_pmstat.u.getcx.nr;
+    return ret;
+}
+
+int xc_pm_get_cxstat(int xc_handle, int cpuid, struct xc_cx_stat *cxpt)
+{
+    DECLARE_SYSCTL;
+    int max_cx, ret;
+
+    if( !cxpt || !(cxpt->triggers) || !(cxpt->residencies) )
+        return -EINVAL;
+
+    if ( (ret = xc_pm_get_max_cx(xc_handle, cpuid, &max_cx)) )
+        goto unlock_0;
+
+    if ( (ret = lock_pages(cxpt, sizeof(struct xc_cx_stat))) )
+        goto unlock_0;
+    if ( (ret = lock_pages(cxpt->triggers, max_cx * sizeof(uint64_t))) )
+        goto unlock_1;
+    if ( (ret = lock_pages(cxpt->residencies, max_cx * sizeof(uint64_t))) )
+        goto unlock_2;
+
+    sysctl.cmd = XEN_SYSCTL_get_pmstat;
+    sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
+    sysctl.u.get_pmstat.cpuid = cpuid;
+    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, cxpt->triggers);
+    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies, 
+                         cxpt->residencies);
+
+    if ( (ret = xc_sysctl(xc_handle, &sysctl)) )
+        goto unlock_3;
+
+    cxpt->nr = sysctl.u.get_pmstat.u.getcx.nr;
+    cxpt->last = sysctl.u.get_pmstat.u.getcx.last;
+    cxpt->idle_time = sysctl.u.get_pmstat.u.getcx.idle_time;
+
+unlock_3:
+    unlock_pages(cxpt->residencies, max_cx * sizeof(uint64_t));
+unlock_2:
+    unlock_pages(cxpt->triggers, max_cx * sizeof(uint64_t));
+unlock_1:
+    unlock_pages(cxpt, sizeof(struct xc_cx_stat));
+unlock_0:
+    return ret;
+}
+
+int xc_pm_reset_cxstat(int xc_handle, int cpuid)
+{
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_get_pmstat;
+    sysctl.u.get_pmstat.type = PMSTAT_reset_cxstat;
+    sysctl.u.get_pmstat.cpuid = cpuid;
+
+    return xc_sysctl(xc_handle, &sysctl);
+}
diff -r b9735935a69e -r ef019d230080 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed May 21 10:59:00 2008 +0100
+++ b/tools/libxc/xenctrl.h     Wed May 21 10:59:49 2008 +0100
@@ -1053,4 +1053,17 @@ int xc_pm_get_pxstat(int xc_handle, int 
 int xc_pm_get_pxstat(int xc_handle, int cpuid, struct xc_px_stat *pxpt);
 int xc_pm_reset_pxstat(int xc_handle, int cpuid);
 
+struct xc_cx_stat {
+    uint32_t nr;    /* entry nr in triggers & residencies, including C0 */
+    uint32_t last;         /* last Cx state */
+    uint64_t idle_time;    /* idle time from boot */
+    uint64_t *triggers;    /* Cx trigger counts */
+    uint64_t *residencies; /* Cx residencies */
+};
+typedef struct xc_cx_stat xc_cx_stat_t;
+
+int xc_pm_get_max_cx(int xc_handle, int cpuid, int *max_cx);
+int xc_pm_get_cxstat(int xc_handle, int cpuid, struct xc_cx_stat *cxpt);
+int xc_pm_reset_cxstat(int xc_handle, int cpuid);
+
 #endif /* XENCTRL_H */
diff -r b9735935a69e -r ef019d230080 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Wed May 21 10:59:00 2008 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c      Wed May 21 10:59:49 2008 +0100
@@ -44,6 +44,7 @@
 #include <asm/hpet.h>
 #include <asm/processor.h>
 #include <public/platform.h>
+#include <public/sysctl.h>
 
 #define DEBUG_PM_CX
 
@@ -940,3 +941,41 @@ long set_cx_pminfo(uint32_t cpu, struct 
         
     return 0;
 }
+
+uint32_t pmstat_get_cx_nr(uint32_t cpuid)
+{
+    return processor_powers[cpuid].count;
+}
+
+int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
+{
+    struct acpi_processor_power *power = &processor_powers[cpuid];
+    struct vcpu *v = idle_vcpu[cpuid];
+    uint64_t usage;
+    int i;
+
+    stat->last = (power->state) ? power->state->type : 0;
+    stat->nr = processor_powers[cpuid].count;
+    stat->idle_time = v->runstate.time[RUNSTATE_running];
+    if ( v->is_running )
+        stat->idle_time += NOW() - v->runstate.state_entry_time;
+
+    for ( i = 0; i < power->count; i++ )
+    {
+        usage = power->states[i].usage;
+        if ( copy_to_guest_offset(stat->triggers, i, &usage, 1) )
+            return -EFAULT;
+    }
+    for ( i = 0; i < power->count; i++ )
+        if ( copy_to_guest_offset(stat->residencies, i, 
+                                  &power->states[i].time, 1) )
+            return -EFAULT;
+
+    return 0;
+}
+
+int pmstat_reset_cx_stat(uint32_t cpuid)
+{
+    return 0;
+}
+
diff -r b9735935a69e -r ef019d230080 xen/arch/x86/acpi/pmstat.c
--- a/xen/arch/x86/acpi/pmstat.c        Wed May 21 10:59:00 2008 +0100
+++ b/xen/arch/x86/acpi/pmstat.c        Wed May 21 10:59:49 2008 +0100
@@ -42,6 +42,10 @@
 
 struct pm_px px_statistic_data[NR_CPUS];
 
+extern uint32_t pmstat_get_cx_nr(uint32_t cpuid);
+extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat);
+extern int pmstat_reset_cx_stat(uint32_t cpuid);
+
 int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
 {
     int ret = 0;
@@ -50,7 +54,7 @@ int do_get_pm_info(struct xen_sysctl_get
 
     /* to protect the case when Px was controlled by dom0-kernel */
     /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */
-    if ( !pmpt->perf.init )
+    if ( !pmpt->perf.init && (op->type & PMSTAT_CATEGORY_MASK) == PMSTAT_PX )
         return -EINVAL;
 
     if ( !cpu_online(op->cpuid) )
@@ -100,6 +104,25 @@ int do_get_pm_info(struct xen_sysctl_get
         break;
     }
 
+    case PMSTAT_get_max_cx:
+    {
+        op->u.getcx.nr = pmstat_get_cx_nr(op->cpuid);
+        ret = 0;
+        break;
+    }
+
+    case PMSTAT_get_cxstat:
+    {
+        ret = pmstat_get_cx_stat(op->cpuid, &op->u.getcx);
+        break;
+    }
+
+    case PMSTAT_reset_cxstat:
+    {
+        ret = pmstat_reset_cx_stat(op->cpuid);
+        break;
+    }
+
     default:
         printk("not defined sub-hypercall @ do_get_pm_info\n");
         ret = -ENOSYS;
diff -r b9735935a69e -r ef019d230080 xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h       Wed May 21 10:59:00 2008 +0100
+++ b/xen/include/public/sysctl.h       Wed May 21 10:59:49 2008 +0100
@@ -233,15 +233,30 @@ typedef struct pm_px_stat pm_px_stat_t;
 typedef struct pm_px_stat pm_px_stat_t;
 DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t);
 
+struct pm_cx_stat {
+    uint32_t nr;    /* entry nr in triggers & residencies, including C0 */
+    uint32_t last;  /* last Cx state */
+    uint64_aligned_t idle_time;                 /* idle time from boot */
+    XEN_GUEST_HANDLE_64(uint64) triggers;    /* Cx trigger counts */
+    XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
+};
+
 struct xen_sysctl_get_pmstat {
-#define PMSTAT_get_max_px   0x11
-#define PMSTAT_get_pxstat   0x12
-#define PMSTAT_reset_pxstat 0x13
+#define PMSTAT_CATEGORY_MASK 0xf0
+#define PMSTAT_PX            0x10
+#define PMSTAT_CX            0x20
+#define PMSTAT_get_max_px    (PMSTAT_PX | 0x1)
+#define PMSTAT_get_pxstat    (PMSTAT_PX | 0x2)
+#define PMSTAT_reset_pxstat  (PMSTAT_PX | 0x3)
+#define PMSTAT_get_max_cx    (PMSTAT_CX | 0x1)
+#define PMSTAT_get_cxstat    (PMSTAT_CX | 0x2)
+#define PMSTAT_reset_cxstat  (PMSTAT_CX | 0x3)
     uint32_t type;
     uint32_t cpuid;
     union {
         struct pm_px_stat getpx;
-        /* other struct for cx, tx, etc */
+        struct pm_cx_stat getcx;
+        /* other struct for tx, etc */
     } u;
 };
 typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;

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


 


Rackspace

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