]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
x86/idle: update to include further package/core residency MSRs
authorJan Beulich <jbeulich@suse.com>
Tue, 18 Mar 2014 10:52:34 +0000 (11:52 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 18 Mar 2014 10:52:34 +0000 (11:52 +0100)
With the number of these growing it becomes increasingly desirable to
not repeatedly alter the sysctl interface to accommodate them. Replace
the explicit listing of numbered states by arrays, unused fields of
which will remain untouched by the hypercall.

The adjusted sysctl interface at once fixes an unrelated shortcoming
of the original one: The "nr" field, specifying the size of the
"triggers" and "residencies" arrays, has to be an input (along with
being an output), which the previous implementation didn't obey to.

Note that the bouncing direction in the libxc interface at once gets
corrected to OUT (was BOTH).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Keir Fraser <keir@xen.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
tools/libxc/xc_pm.c
tools/libxc/xenctrl.h
tools/misc/xenpm.c
xen/arch/x86/acpi/cpu_idle.c
xen/include/public/sysctl.h

index f7ac40cb7b6ca79802fcced5d788899854de3608..e4e0fb956e9cc1726df1d9c1708f8c0216206957 100644 (file)
@@ -123,45 +123,53 @@ int xc_pm_get_max_cx(xc_interface *xch, int cpuid, int *max_cx)
 int xc_pm_get_cxstat(xc_interface *xch, int cpuid, struct xc_cx_stat *cxpt)
 {
     DECLARE_SYSCTL;
-    DECLARE_NAMED_HYPERCALL_BOUNCE(triggers, cxpt->triggers, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
-    DECLARE_NAMED_HYPERCALL_BOUNCE(residencies, cxpt->residencies, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
-    int max_cx, ret;
+    DECLARE_NAMED_HYPERCALL_BOUNCE(triggers, cxpt->triggers,
+                                   cxpt->nr * sizeof(*cxpt->triggers),
+                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_NAMED_HYPERCALL_BOUNCE(residencies, cxpt->residencies,
+                                   cxpt->nr * sizeof(*cxpt->residencies),
+                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_NAMED_HYPERCALL_BOUNCE(pc, cxpt->pc,
+                                   cxpt->nr_pc * sizeof(*cxpt->pc),
+                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_NAMED_HYPERCALL_BOUNCE(cc, cxpt->cc,
+                                   cxpt->nr_cc * sizeof(*cxpt->cc),
+                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    int ret = -1;
 
-    if( !cxpt->triggers || !cxpt->residencies )
-        return -EINVAL;
-
-    if ( (ret = xc_pm_get_max_cx(xch, cpuid, &max_cx)) )
-        goto unlock_0;
-
-    HYPERCALL_BOUNCE_SET_SIZE(triggers, max_cx * sizeof(uint64_t));
-    HYPERCALL_BOUNCE_SET_SIZE(residencies, max_cx * sizeof(uint64_t));
-
-    ret = -1;
     if ( xc_hypercall_bounce_pre(xch, triggers) )
         goto unlock_0;
     if ( xc_hypercall_bounce_pre(xch, residencies) )
         goto unlock_1;
+    if ( xc_hypercall_bounce_pre(xch, pc) )
+        goto unlock_2;
+    if ( xc_hypercall_bounce_pre(xch, cc) )
+        goto unlock_3;
 
     sysctl.cmd = XEN_SYSCTL_get_pmstat;
     sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
     sysctl.u.get_pmstat.cpuid = cpuid;
+    sysctl.u.get_pmstat.u.getcx.nr = cxpt->nr;
+    sysctl.u.get_pmstat.u.getcx.nr_pc = cxpt->nr_pc;
+    sysctl.u.get_pmstat.u.getcx.nr_cc = cxpt->nr_cc;
     set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, triggers);
     set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies, residencies);
+    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.pc, pc);
+    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.cc, cc);
 
     if ( (ret = xc_sysctl(xch, &sysctl)) )
-        goto unlock_2;
+        goto unlock_4;
 
     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;
-    cxpt->pc2 = sysctl.u.get_pmstat.u.getcx.pc2;
-    cxpt->pc3 = sysctl.u.get_pmstat.u.getcx.pc3;
-    cxpt->pc6 = sysctl.u.get_pmstat.u.getcx.pc6;
-    cxpt->pc7 = sysctl.u.get_pmstat.u.getcx.pc7;
-    cxpt->cc3 = sysctl.u.get_pmstat.u.getcx.cc3;
-    cxpt->cc6 = sysctl.u.get_pmstat.u.getcx.cc6;
-    cxpt->cc7 = sysctl.u.get_pmstat.u.getcx.cc7;
+    cxpt->nr_pc = sysctl.u.get_pmstat.u.getcx.nr_pc;
+    cxpt->nr_cc = sysctl.u.get_pmstat.u.getcx.nr_cc;
 
+unlock_4:
+    xc_hypercall_bounce_post(xch, cc);
+unlock_3:
+    xc_hypercall_bounce_post(xch, pc);
 unlock_2:
     xc_hypercall_bounce_post(xch, residencies);
 unlock_1:
index 13f816b6397ba0252af594b41de510d9330b5784..e3a32f2d6ed708684e1dce3c74f8d97c900c9155 100644 (file)
@@ -1935,18 +1935,15 @@ int xc_pm_get_pxstat(xc_interface *xch, int cpuid, struct xc_px_stat *pxpt);
 int xc_pm_reset_pxstat(xc_interface *xch, int cpuid);
 
 struct xc_cx_stat {
-    uint32_t nr;    /* entry nr in triggers & residencies, including C0 */
+    uint32_t nr;           /* entry nr in triggers[]/residencies[], incl 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 */
-    uint64_t pc2;
-    uint64_t pc3;
-    uint64_t pc6;
-    uint64_t pc7;
-    uint64_t cc3;
-    uint64_t cc6;
-    uint64_t cc7;
+    uint32_t nr_pc;        /* entry nr in pc[] */
+    uint32_t nr_cc;        /* entry nr in cc[] */
+    uint64_t *pc;          /* 1-biased indexing (i.e. excl C0) */
+    uint64_t *cc;          /* 1-biased indexing (i.e. excl C0) */
 };
 typedef struct xc_cx_stat xc_cx_stat_t;
 
index 2e57f1fcafb76e3640a6b56a848340e56aab6a4e..e43924c21bbfc7a75f08f2a5b8a5313a8e8c5bb3 100644 (file)
@@ -29,6 +29,9 @@
 #include <inttypes.h>
 #include <sys/time.h>
 
+#define MAX_PKG_RESIDENCIES 12
+#define MAX_CORE_RESIDENCIES 8
+
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
 static xc_interface *xc_handle;
@@ -102,7 +105,7 @@ static void parse_cpuid_and_int(int argc, char *argv[],
 
 static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
 {
-    int i;
+    unsigned int i;
 
     printf("cpu id               : %d\n", cpuid);
     printf("total C-states       : %d\n", cxstat->nr);
@@ -115,17 +118,14 @@ static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
         printf("                       residency  [%20"PRIu64" ms]\n",
                cxstat->residencies[i]/1000000UL);
     }
-    printf("pc2                  : [%20"PRIu64" ms]\n"
-           "pc3                  : [%20"PRIu64" ms]\n"
-           "pc6                  : [%20"PRIu64" ms]\n"
-           "pc7                  : [%20"PRIu64" ms]\n",
-            cxstat->pc2/1000000UL, cxstat->pc3/1000000UL,
-            cxstat->pc6/1000000UL, cxstat->pc7/1000000UL);
-    printf("cc3                  : [%20"PRIu64" ms]\n"
-           "cc6                  : [%20"PRIu64" ms]\n"
-           "cc7                  : [%20"PRIu64" ms]\n",
-            cxstat->cc3/1000000UL, cxstat->cc6/1000000UL,
-            cxstat->cc7/1000000UL);
+    for ( i = 0; i < MAX_PKG_RESIDENCIES && i < cxstat->nr_pc; ++i )
+        if ( cxstat->pc[i] )
+           printf("pc%d                  : [%20"PRIu64" ms]\n", i + 1,
+                  cxstat->pc[i] / 1000000UL);
+    for ( i = 0; i < MAX_CORE_RESIDENCIES && i < cxstat->nr_cc; ++i )
+        if ( cxstat->cc[i] )
+           printf("cc%d                  : [%20"PRIu64" ms]\n", i + 1,
+                  cxstat->cc[i] / 1000000UL);
     printf("\n");
 }
 
@@ -145,24 +145,36 @@ static int get_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_cx_
     if ( !max_cx_num )
         return -ENODEV;
 
-    cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
-    if ( !cxstat->triggers )
-        return -ENOMEM;
-    cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
-    if ( !cxstat->residencies )
+    cxstat->triggers = calloc(max_cx_num, sizeof(*cxstat->triggers));
+    cxstat->residencies = calloc(max_cx_num, sizeof(*cxstat->residencies));
+    cxstat->pc = calloc(MAX_PKG_RESIDENCIES, sizeof(*cxstat->pc));
+    cxstat->cc = calloc(MAX_CORE_RESIDENCIES, sizeof(*cxstat->cc));
+    if ( !cxstat->triggers || !cxstat->residencies ||
+         !cxstat->pc || !cxstat->cc )
     {
+        free(cxstat->cc);
+        free(cxstat->pc);
+        free(cxstat->residencies);
         free(cxstat->triggers);
         return -ENOMEM;
     }
 
+    cxstat->nr = max_cx_num;
+    cxstat->nr_pc = MAX_PKG_RESIDENCIES;
+    cxstat->nr_cc = MAX_CORE_RESIDENCIES;
+
     ret = xc_pm_get_cxstat(xc_handle, cpuid, cxstat);
     if( ret )
     {
         ret = -errno;
         free(cxstat->triggers);
         free(cxstat->residencies);
+        free(cxstat->pc);
+        free(cxstat->cc);
         cxstat->triggers = NULL;
         cxstat->residencies = NULL;
+        cxstat->pc = NULL;
+        cxstat->cc = NULL;
     }
 
     return ret;
@@ -198,6 +210,8 @@ static int show_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
 
     free(cxstatinfo.triggers);
     free(cxstatinfo.residencies);
+    free(cxstatinfo.pc);
+    free(cxstatinfo.cc);
     return 0;
 }
 
@@ -482,25 +496,26 @@ static void signal_int_handler(int signo)
             /* print out CC? and PC? */
             for ( i = 0; i < socket_nr; i++ )
             {
+                unsigned int n;
                 uint64_t res;
+
                 for ( j = 0; j <= info.max_cpu_index; j++ )
                 {
                     if ( cpu_to_socket[j] == socket_ids[i] )
                         break;
                 }
                 printf("\nSocket %d\n", socket_ids[i]);
-                res = cxstat_end[j].pc2 - cxstat_start[j].pc2;
-                printf("\tPC2\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL,
-                       100UL * res / (double)sum_cx[j]);
-                res = cxstat_end[j].pc3 - cxstat_start[j].pc3;
-                printf("\tPC3\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL, 
-                       100UL * res / (double)sum_cx[j]);
-                res = cxstat_end[j].pc6 - cxstat_start[j].pc6;
-                printf("\tPC6\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL, 
-                       100UL * res / (double)sum_cx[j]);
-                res = cxstat_end[j].pc7 - cxstat_start[j].pc7;
-                printf("\tPC7\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL, 
-                       100UL * res / (double)sum_cx[j]);
+                for ( n = 0; n < MAX_PKG_RESIDENCIES; ++n )
+                {
+                    if ( n >= cxstat_end[j].nr_pc )
+                        continue;
+                    res = cxstat_end[j].pc[n];
+                    if ( n < cxstat_start[j].nr_pc )
+                        res -= cxstat_start[j].pc[n];
+                    printf("\tPC%u\t%"PRIu64" ms\t%.2f%%\n",
+                           n + 1, res / 1000000UL,
+                           100UL * res / (double)sum_cx[j]);
+                }
                 for ( k = 0; k < core_nr; k++ )
                 {
                     for ( j = 0; j <= info.max_cpu_index; j++ )
@@ -510,15 +525,17 @@ static void signal_int_handler(int signo)
                             break;
                     }
                     printf("\t Core %d CPU %d\n", core_ids[k], j);
-                    res = cxstat_end[j].cc3 - cxstat_start[j].cc3;
-                    printf("\t\tCC3\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL, 
-                           100UL * res / (double)sum_cx[j]);
-                    res = cxstat_end[j].cc6 - cxstat_start[j].cc6;
-                    printf("\t\tCC6\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL, 
-                           100UL * res / (double)sum_cx[j]);
-                    res = cxstat_end[j].cc7 - cxstat_start[j].cc7;
-                    printf("\t\tCC7\t%"PRIu64" ms\t%.2f%%\n",  res / 1000000UL,
-                           100UL * res / (double)sum_cx[j]);
+                    for ( n = 0; n < MAX_CORE_RESIDENCIES; ++n )
+                    {
+                        if ( n >= cxstat_end[j].nr_cc )
+                            continue;
+                        res = cxstat_end[j].cc[n];
+                        if ( n < cxstat_start[j].nr_cc )
+                            res -= cxstat_start[j].cc[n];
+                        printf("\t\tCC%u\t%"PRIu64" ms\t%.2f%%\n",
+                               n + 1, res / 1000000UL,
+                               100UL * res / (double)sum_cx[j]);
+                    }
                 }
             }
         }
@@ -529,6 +546,8 @@ static void signal_int_handler(int signo)
     {
         free(cxstat[i].triggers);
         free(cxstat[i].residencies);
+        free(cxstat[i].pc);
+        free(cxstat[i].cc);
         free(pxstat[i].trans_pt);
         free(pxstat[i].pt);
     }
index 6aaa7abac2c8393d640e160901b8f7d8aab38e45..d2119e27cd14fe66bcf614b8dab09c09dc25128e 100644 (file)
 
 #define GET_HW_RES_IN_NS(msr, val) \
     do { rdmsrl(msr, val); val = tsc_ticks2ns(val); } while( 0 )
-#define GET_PC2_RES(val)  GET_HW_RES_IN_NS(0x60D, val) /* SNB only */
+#define GET_PC2_RES(val)  GET_HW_RES_IN_NS(0x60D, val) /* SNB onwards */
 #define GET_PC3_RES(val)  GET_HW_RES_IN_NS(0x3F8, val)
 #define GET_PC6_RES(val)  GET_HW_RES_IN_NS(0x3F9, val)
 #define GET_PC7_RES(val)  GET_HW_RES_IN_NS(0x3FA, val)
+#define GET_PC8_RES(val)  GET_HW_RES_IN_NS(0x630, val) /* some Haswells only */
+#define GET_PC9_RES(val)  GET_HW_RES_IN_NS(0x631, val) /* some Haswells only */
+#define GET_PC10_RES(val) GET_HW_RES_IN_NS(0x632, val) /* some Haswells only */
+#define GET_CC1_RES(val)  GET_HW_RES_IN_NS(0x660, val) /* Silvermont only */
 #define GET_CC3_RES(val)  GET_HW_RES_IN_NS(0x3FC, val)
 #define GET_CC6_RES(val)  GET_HW_RES_IN_NS(0x3FD, val)
-#define GET_CC7_RES(val)  GET_HW_RES_IN_NS(0x3FE, val) /* SNB only */
+#define GET_CC7_RES(val)  GET_HW_RES_IN_NS(0x3FE, val) /* SNB onwards */
 
 static void lapic_timer_nop(void) { }
 void (*__read_mostly lapic_timer_off)(void);
@@ -111,8 +115,13 @@ struct hw_residencies
 {
     uint64_t pc2;
     uint64_t pc3;
+    uint64_t pc4;
     uint64_t pc6;
     uint64_t pc7;
+    uint64_t pc8;
+    uint64_t pc9;
+    uint64_t pc10;
+    uint64_t cc1;
     uint64_t cc3;
     uint64_t cc6;
     uint64_t cc7;
@@ -128,6 +137,12 @@ static void do_get_hw_residencies(void *arg)
 
     switch ( c->x86_model )
     {
+    /* 4th generation Intel Core (Haswell) */
+    case 0x45:
+        GET_PC8_RES(hw_res->pc8);
+        GET_PC9_RES(hw_res->pc9);
+        GET_PC10_RES(hw_res->pc10);
+        /* fall through */
     /* Sandy bridge */
     case 0x2A:
     case 0x2D:
@@ -137,7 +152,6 @@ static void do_get_hw_residencies(void *arg)
     /* Haswell */
     case 0x3C:
     case 0x3F:
-    case 0x45:
     case 0x46:
     /* future */
     case 0x3D:
@@ -160,6 +174,22 @@ static void do_get_hw_residencies(void *arg)
         GET_CC3_RES(hw_res->cc3);
         GET_CC6_RES(hw_res->cc6);
         break;
+    /* various Atoms */
+    case 0x27:
+        GET_PC3_RES(hw_res->pc2); /* abusing GET_PC3_RES */
+        GET_PC6_RES(hw_res->pc4); /* abusing GET_PC6_RES */
+        GET_PC7_RES(hw_res->pc6); /* abusing GET_PC7_RES */
+        break;
+    /* Silvermont */
+    case 0x37:
+    case 0x4A:
+    case 0x4D:
+    case 0x5A:
+    case 0x5D:
+        GET_PC7_RES(hw_res->pc6); /* abusing GET_PC7_RES */
+        GET_CC1_RES(hw_res->cc1);
+        GET_CC6_RES(hw_res->cc6);
+        break;
     }
 }
 
@@ -179,10 +209,16 @@ static void print_hw_residencies(uint32_t cpu)
 
     get_hw_residencies(cpu, &hw_res);
 
-    printk("PC2[%"PRId64"] PC3[%"PRId64"] PC6[%"PRId64"] PC7[%"PRId64"]\n",
-           hw_res.pc2, hw_res.pc3, hw_res.pc6, hw_res.pc7);
-    printk("CC3[%"PRId64"] CC6[%"PRId64"] CC7[%"PRId64"]\n",
-           hw_res.cc3, hw_res.cc6,hw_res.cc7);
+    printk("PC2[%"PRIu64"] PC%d[%"PRIu64"] PC6[%"PRIu64"] PC7[%"PRIu64"]\n",
+           hw_res.pc2,
+           hw_res.pc4 ? 4 : 3, hw_res.pc4 ?: hw_res.pc3,
+           hw_res.pc6, hw_res.pc7);
+    if ( hw_res.pc8 | hw_res.pc9 | hw_res.pc10 )
+        printk("PC8[%"PRIu64"] PC9[%"PRIu64"] PC10[%"PRIu64"]\n",
+               hw_res.pc8, hw_res.pc9, hw_res.pc10);
+    printk("CC%d[%"PRIu64"] CC6[%"PRIu64"] CC7[%"PRIu64"]\n",
+           hw_res.cc1 ? 1 : 3, hw_res.cc1 ?: hw_res.cc3,
+           hw_res.cc6, hw_res.cc7);
 }
 
 static char* acpi_cstate_method_name[] =
@@ -1100,19 +1136,21 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
     struct acpi_processor_power *power = processor_powers[cpuid];
     uint64_t idle_usage = 0, idle_res = 0;
     uint64_t usage[ACPI_PROCESSOR_MAX_POWER], res[ACPI_PROCESSOR_MAX_POWER];
-    int i;
-    struct hw_residencies hw_res;
+    unsigned int i, nr, nr_pc = 0, nr_cc = 0;
 
     if ( power == NULL )
     {
         stat->last = 0;
         stat->nr = 0;
         stat->idle_time = 0;
+        stat->nr_pc = 0;
+        stat->nr_cc = 0;
         return 0;
     }
 
     stat->last = power->last_state ? power->last_state->idx : 0;
     stat->idle_time = get_cpu_idle_time(cpuid);
+    nr = min(stat->nr, power->count);
 
     /* mimic the stat when detail info hasn't been registered by dom0 */
     if ( pm_idle_save == NULL )
@@ -1121,14 +1159,14 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
 
         usage[1] = idle_usage = 1;
         res[1] = idle_res = stat->idle_time;
-
-        memset(&hw_res, 0, sizeof(hw_res));
     }
     else
     {
+        struct hw_residencies hw_res;
+
         stat->nr = power->count;
 
-        for ( i = 1; i < power->count; i++ )
+        for ( i = 1; i < nr; i++ )
         {
             spin_lock_irq(&power->stat_lock);
             usage[i] = power->states[i].usage;
@@ -1140,22 +1178,42 @@ int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
         }
 
         get_hw_residencies(cpuid, &hw_res);
+
+#define PUT_xC(what, n) do { \
+        if ( stat->nr_##what >= n && \
+             copy_to_guest_offset(stat->what, n - 1, &hw_res.what##n, 1) ) \
+            return -EFAULT; \
+        if ( hw_res.what##n ) \
+            nr_##what = n; \
+    } while ( 0 )
+#define PUT_PC(n) PUT_xC(pc, n)
+        PUT_PC(2);
+        PUT_PC(3);
+        PUT_PC(4);
+        PUT_PC(6);
+        PUT_PC(7);
+        PUT_PC(8);
+        PUT_PC(9);
+        PUT_PC(10);
+#undef PUT_PC
+#define PUT_CC(n) PUT_xC(cc, n)
+        PUT_CC(1);
+        PUT_CC(3);
+        PUT_CC(6);
+        PUT_CC(7);
+#undef PUT_CC
+#undef PUT_xC
     }
 
     usage[0] = idle_usage;
     res[0] = NOW() - idle_res;
 
-    if ( copy_to_guest(stat->triggers, usage, stat->nr) ||
-         copy_to_guest(stat->residencies, res, stat->nr) )
+    if ( copy_to_guest(stat->triggers, usage, nr) ||
+         copy_to_guest(stat->residencies, res, nr) )
         return -EFAULT;
 
-    stat->pc2 = hw_res.pc2;
-    stat->pc3 = hw_res.pc3;
-    stat->pc6 = hw_res.pc6;
-    stat->pc7 = hw_res.pc7;
-    stat->cc3 = hw_res.cc3;
-    stat->cc6 = hw_res.cc6;
-    stat->cc7 = hw_res.cc7;
+    stat->nr_pc = nr_pc;
+    stat->nr_cc = nr_cc;
 
     return 0;
 }
index 8437d31e18870ba8ba8630076b9ca650064d87e7..8ae6870b408395deaae69674a3c19a33dc42de01 100644 (file)
@@ -34,7 +34,7 @@
 #include "xen.h"
 #include "domctl.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000A
+#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000B
 
 /*
  * Read console content from Xen buffer ring.
@@ -226,13 +226,10 @@ struct pm_cx_stat {
     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 */
-    uint64_aligned_t pc2;
-    uint64_aligned_t pc3;
-    uint64_aligned_t pc6;
-    uint64_aligned_t pc7;
-    uint64_aligned_t cc3;
-    uint64_aligned_t cc6;
-    uint64_aligned_t cc7;
+    uint32_t nr_pc;                          /* entry nr in pc[] */
+    uint32_t nr_cc;                          /* entry nr in cc[] */
+    XEN_GUEST_HANDLE_64(uint64) pc;          /* 1-biased indexing */
+    XEN_GUEST_HANDLE_64(uint64) cc;          /* 1-biased indexing */
 };
 
 struct xen_sysctl_get_pmstat {