WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] xenoprof: support Intel's architectural p

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xenoprof: support Intel's architectural perfmon registers.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 15 Sep 2009 02:15:10 -0700
Delivery-date: Tue, 15 Sep 2009 02:15:25 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1253005396 -3600
# Node ID 15f5cff84adf32d1d24245207fc6e9a72a4cae13
# Parent  65968459de751a49498b1ad23279e272a6dfd044
xenoprof: support Intel's architectural perfmon registers.

One benefit is that more perfmon counters can be used on Nehalem.

Signed-off-by: Yang Zhang <yang.zhang@xxxxxxxxx>
Signed-off-by: Yang Xiaowei <xiaowei.yang@xxxxxxxxx>
---
 xen/arch/x86/cpu/intel.c              |    6 +
 xen/arch/x86/oprofile/nmi_int.c       |   31 ++++--
 xen/arch/x86/oprofile/op_model_ppro.c |  157 +++++++++++++++++++++++++---------
 xen/arch/x86/oprofile/op_x86_model.h  |    8 +
 xen/include/asm-x86/cpufeature.h      |    3 
 5 files changed, 150 insertions(+), 55 deletions(-)

diff -r 65968459de75 -r 15f5cff84adf xen/arch/x86/cpu/intel.c
--- a/xen/arch/x86/cpu/intel.c  Tue Sep 15 10:02:15 2009 +0100
+++ b/xen/arch/x86/cpu/intel.c  Tue Sep 15 10:03:16 2009 +0100
@@ -148,6 +148,12 @@ static void __devinit init_intel(struct 
 
        select_idle_routine(c);
        l2 = init_intel_cacheinfo(c);
+       if (c->cpuid_level > 9) {
+               unsigned eax = cpuid_eax(10);
+               /* Check for version and the number of counters */
+               if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+                       set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
+       }
 
        /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until 
model 3 mask 3 */
        if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
diff -r 65968459de75 -r 15f5cff84adf xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c   Tue Sep 15 10:02:15 2009 +0100
+++ b/xen/arch/x86/oprofile/nmi_int.c   Tue Sep 15 10:03:16 2009 +0100
@@ -374,22 +374,29 @@ static int __init ppro_init(char ** cpu_
                ppro_has_global_ctrl = 1;
                break;
        case 26:
+               arch_perfmon_setup_counters();
                *cpu_type = "i386/core_i7";
                ppro_has_global_ctrl = 1;
                break;
        case 28:
                *cpu_type = "i386/atom";
-               ppro_has_global_ctrl = 1;
                break;
        default:
                /* Unknown */
-               printk("xenoprof: Initialization failed. "
-                      "Intel processor model %d for P6 class family is not "
-                      "supported\n", cpu_model);
                return 0;
        }
 
        model = &op_ppro_spec;
+       return 1;
+}
+
+static int __init arch_perfmon_init(char **cpu_type)
+{
+       if (!cpu_has_arch_perfmon)
+               return 0;
+       *cpu_type = "i386/arch_perfmon";
+       model = &op_arch_perfmon_spec;
+       arch_perfmon_setup_counters();
        return 1;
 }
 
@@ -397,6 +404,7 @@ static int __init nmi_init(void)
 {
        __u8 vendor = current_cpu_data.x86_vendor;
        __u8 family = current_cpu_data.x86;
+       __u8 _model = current_cpu_data.x86_model;
  
        if (!cpu_has_apic) {
                printk("xenoprof: Initialization failed. No APIC\n");
@@ -438,21 +446,22 @@ static int __init nmi_init(void)
                        switch (family) {
                                /* Pentium IV */
                                case 0xf:
-                                       if (!p4_init(&cpu_type))
-                                               return -ENODEV;
+                                       p4_init(&cpu_type);
                                        break;
 
                                /* A P6-class processor */
                                case 6:
-                                       if (!ppro_init(&cpu_type))
-                                               return -ENODEV;
+                                       ppro_init(&cpu_type);
                                        break;
 
                                default:
+                               break;
+                       }
+                       if (!cpu_type && !arch_perfmon_init(&cpu_type)) {
                                printk("xenoprof: Initialization failed. "
-                                      "Intel processor family %d is not "
-                                      "supported\n", family);
-                                       return -ENODEV;
+                                      "Intel processor family %d model %d"
+                                      "is not supported\n", family, _model);
+                               return -ENODEV;
                        }
                        break;
 
diff -r 65968459de75 -r 15f5cff84adf xen/arch/x86/oprofile/op_model_ppro.c
--- a/xen/arch/x86/oprofile/op_model_ppro.c     Tue Sep 15 10:02:15 2009 +0100
+++ b/xen/arch/x86/oprofile/op_model_ppro.c     Tue Sep 15 10:03:16 2009 +0100
@@ -24,12 +24,24 @@
 #include "op_x86_model.h"
 #include "op_counter.h"
 
-#define NUM_COUNTERS 2
-#define NUM_CONTROLS 2
-
-#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} 
while (0)
-#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 
-1);} while (0)
-#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+/*
+ * Intel "Architectural Performance Monitoring" CPUID
+ * detection/enumeration details:
+ */
+union cpuid10_eax {
+       struct {
+               unsigned int version_id:8;
+               unsigned int num_counters:8;
+               unsigned int bit_width:8;
+               unsigned int mask_length:8;
+       } split;
+       unsigned int full;
+};
+
+static int num_counters = 2;
+static int counter_width = 32;
+
+#define CTR_OVERFLOWED(n) (!((n) & (1ULL<<(counter_width-1)))) 
 
 #define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), 
(h));} while (0)
 #define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), 
(h));} while (0)
@@ -43,43 +55,60 @@
 #define CTRL_SET_EVENT(val, e) (val |= e)
 #define IS_ACTIVE(val) (val & (1 << 22) )  
 #define IS_ENABLE(val) (val & (1 << 20) )
-static unsigned long reset_value[NUM_COUNTERS];
+static unsigned long reset_value[OP_MAX_COUNTER];
 int ppro_has_global_ctrl = 0;
 extern int is_passive(struct domain *d);
  
 static void ppro_fill_in_addresses(struct op_msrs * const msrs)
 {
-       msrs->counters[0].addr = MSR_P6_PERFCTR0;
-       msrs->counters[1].addr = MSR_P6_PERFCTR1;
+       int i;
+
+       for (i = 0; i < num_counters; i++)
+               msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+       for (i = 0; i < num_counters; i++)
+               msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+}
+
+
+static void ppro_setup_ctrs(struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       int i;
        
-       msrs->controls[0].addr = MSR_P6_EVNTSEL0;
-       msrs->controls[1].addr = MSR_P6_EVNTSEL1;
-}
-
-
-static void ppro_setup_ctrs(struct op_msrs const * const msrs)
-{
-       unsigned int low, high;
-       int i;
+       if (cpu_has_arch_perfmon) {
+               union cpuid10_eax eax;
+               eax.full = cpuid_eax(0xa);
+
+               /*
+                * For Core2 (family 6, model 15), don't reset the
+                * counter width:
+                */
+               if (!(eax.split.version_id == 0 &&
+                       current_cpu_data.x86 == 6 &&
+                               current_cpu_data.x86_model == 15)) {
+
+                       if (counter_width < eax.split.bit_width)
+                               counter_width = eax.split.bit_width;
+               }
+       }
 
        /* clear all counters */
-       for (i = 0 ; i < NUM_CONTROLS; ++i) {
+       for (i = 0 ; i < num_counters; ++i) {
                CTRL_READ(low, high, msrs, i);
                CTRL_CLEAR(low);
                CTRL_WRITE(low, high, msrs, i);
        }
        
        /* avoid a false detection of ctr overflows in NMI handler */
-       for (i = 0; i < NUM_COUNTERS; ++i) {
-               CTR_WRITE(1, msrs, i);
-       }
+       for (i = 0; i < num_counters; ++i)
+               wrmsrl(msrs->counters[i].addr, -1LL);
 
        /* enable active counters */
-       for (i = 0; i < NUM_COUNTERS; ++i) {
+       for (i = 0; i < num_counters; ++i) {
                if (counter_config[i].enabled) {
                        reset_value[i] = counter_config[i].count;
 
-                       CTR_WRITE(counter_config[i].count, msrs, i);
+                       wrmsrl(msrs->counters[i].addr, -reset_value[i]);
 
                        CTRL_READ(low, high, msrs, i);
                        CTRL_CLEAR(low);
@@ -89,6 +118,8 @@ static void ppro_setup_ctrs(struct op_ms
                        CTRL_SET_UM(low, counter_config[i].unit_mask);
                        CTRL_SET_EVENT(low, counter_config[i].event);
                        CTRL_WRITE(low, high, msrs, i);
+               } else {
+                       reset_value[i] = 0;
                }
        }
 }
@@ -102,26 +133,26 @@ static int ppro_check_ctrs(unsigned int 
                            struct op_msrs const * const msrs,
                            struct cpu_user_regs * const regs)
 {
-       unsigned int low, high;
+       u64 val;
        int i;
        int ovf = 0;
        unsigned long eip = regs->eip;
        int mode = xenoprofile_get_mode(current, regs);
        struct arch_msr_pair *msrs_content = vcpu_vpmu(current)->context;
 
-       for (i = 0 ; i < NUM_COUNTERS; ++i) {
+       for (i = 0 ; i < num_counters; ++i) {
                if (!reset_value[i])
                        continue;
-               CTR_READ(low, high, msrs, i);
-               if (CTR_OVERFLOWED(low)) {
+               rdmsrl(msrs->counters[i].addr, val);
+               if (CTR_OVERFLOWED(val)) {
                        xenoprof_log_event(current, regs, eip, mode, i);
-                       CTR_WRITE(reset_value[i], msrs, i);
+                       wrmsrl(msrs->counters[i].addr, -reset_value[i]);
                        if ( is_passive(current->domain) && (mode != 2) && 
                                (vcpu_vpmu(current)->flags & 
PASSIVE_DOMAIN_ALLOCATED) ) 
                        {
                                if ( IS_ACTIVE(msrs_content[i].control) )
                                {
-                                       msrs_content[i].counter = (low | 
(u64)high << 32);
+                                       msrs_content[i].counter = val;
                                        if ( IS_ENABLE(msrs_content[i].control) 
)
                                                ovf = 2;
                                }
@@ -144,7 +175,7 @@ static void ppro_start(struct op_msrs co
        unsigned int low,high;
        int i;
 
-       for (i = 0; i < NUM_COUNTERS; ++i) {
+       for (i = 0; i < num_counters; ++i) {
                if (reset_value[i]) {
                        CTRL_READ(low, high, msrs, i);
                        CTRL_SET_ACTIVE(low);
@@ -155,7 +186,7 @@ static void ppro_start(struct op_msrs co
      * However, this may not hold true when xenoprof starts to run.
      */
     if ( ppro_has_global_ctrl )
-        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, (1<<NUM_COUNTERS) - 1);
+        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, (1<<num_counters) - 1);
 }
 
 
@@ -164,7 +195,7 @@ static void ppro_stop(struct op_msrs con
        unsigned int low,high;
        int i;
 
-       for (i = 0; i < NUM_COUNTERS; ++i) {
+       for (i = 0; i < num_counters; ++i) {
                if (!reset_value[i])
                        continue;
                CTRL_READ(low, high, msrs, i);
@@ -178,14 +209,14 @@ static int ppro_is_arch_pmu_msr(u64 msr_
 static int ppro_is_arch_pmu_msr(u64 msr_index, int *type, int *index)
 {
        if ( (msr_index >= MSR_IA32_PERFCTR0) &&
-            (msr_index < (MSR_IA32_PERFCTR0 + NUM_COUNTERS)) )
+            (msr_index < (MSR_IA32_PERFCTR0 + num_counters)) )
        {
                *type = MSR_TYPE_ARCH_COUNTER;
                *index = msr_index - MSR_IA32_PERFCTR0;
                return 1;
         }
         if ( (msr_index >= MSR_P6_EVNTSEL0) &&
-            (msr_index < (MSR_P6_EVNTSEL0 + NUM_CONTROLS)) )
+            (msr_index < (MSR_P6_EVNTSEL0 + num_counters)) )
         {
                *type = MSR_TYPE_ARCH_CTRL;
                *index = msr_index - MSR_P6_EVNTSEL0;
@@ -199,11 +230,11 @@ static int ppro_allocate_msr(struct vcpu
 {
        struct vpmu_struct *vpmu = vcpu_vpmu(v);
        struct arch_msr_pair *msr_content;
-       
-       msr_content = xmalloc_bytes( sizeof(struct arch_msr_pair) * 
NUM_COUNTERS );
+
+       msr_content = xmalloc_bytes( sizeof(struct arch_msr_pair) * 
num_counters );
        if ( !msr_content )
                goto out;
-       memset(msr_content, 0, sizeof(struct arch_msr_pair) * NUM_COUNTERS);
+       memset(msr_content, 0, sizeof(struct arch_msr_pair) * num_counters);
        vpmu->context = (void *)msr_content;
        vpmu->flags = 0;
        vpmu->flags |= PASSIVE_DOMAIN_ALLOCATED;
@@ -254,9 +285,39 @@ static void ppro_save_msr(struct vcpu *v
        }       
 }
 
-struct op_x86_model_spec const op_ppro_spec = {
-       .num_counters = NUM_COUNTERS,
-       .num_controls = NUM_CONTROLS,
+/*
+ * Architectural performance monitoring.
+ *
+ * Newer Intel CPUs (Core1+) have support for architectural
+ * events described in CPUID 0xA. See the IA32 SDM Vol3b.18 for details.
+ * The advantage of this is that it can be done without knowing about
+ * the specific CPU.
+ */
+void arch_perfmon_setup_counters(void)
+{
+       union cpuid10_eax eax;
+
+       eax.full = cpuid_eax(0xa);
+
+       /* Workaround for BIOS bugs in 6/15. Taken from perfmon2 */
+       if (eax.split.version_id == 0 && current_cpu_data.x86 == 6 &&
+           current_cpu_data.x86_model == 15) {
+               eax.split.version_id = 2;
+               eax.split.num_counters = 2;
+               eax.split.bit_width = 40;
+       }
+
+       num_counters = min_t(u8, eax.split.num_counters, OP_MAX_COUNTER);
+
+       op_arch_perfmon_spec.num_counters = num_counters;
+       op_arch_perfmon_spec.num_controls = num_counters;
+       op_ppro_spec.num_counters = num_counters;
+       op_ppro_spec.num_controls = num_counters;
+}
+
+struct op_x86_model_spec op_ppro_spec = {
+       .num_counters = 2,
+       .num_controls = 2,
        .fill_in_addresses = &ppro_fill_in_addresses,
        .setup_ctrs = &ppro_setup_ctrs,
        .check_ctrs = &ppro_check_ctrs,
@@ -268,3 +329,17 @@ struct op_x86_model_spec const op_ppro_s
        .load_msr = &ppro_load_msr,
        .save_msr = &ppro_save_msr
 };
+
+struct op_x86_model_spec op_arch_perfmon_spec = {
+       /* num_counters/num_controls filled in at runtime */
+       .fill_in_addresses = &ppro_fill_in_addresses,
+       .setup_ctrs = &ppro_setup_ctrs,
+       .check_ctrs = &ppro_check_ctrs,
+       .start = &ppro_start,
+       .stop = &ppro_stop,
+       .is_arch_pmu_msr = &ppro_is_arch_pmu_msr,
+       .allocated_msr = &ppro_allocate_msr,
+       .free_msr = &ppro_free_msr,
+       .load_msr = &ppro_load_msr,
+       .save_msr = &ppro_save_msr
+};
diff -r 65968459de75 -r 15f5cff84adf xen/arch/x86/oprofile/op_x86_model.h
--- a/xen/arch/x86/oprofile/op_x86_model.h      Tue Sep 15 10:02:15 2009 +0100
+++ b/xen/arch/x86/oprofile/op_x86_model.h      Tue Sep 15 10:03:16 2009 +0100
@@ -32,8 +32,8 @@ struct pt_regs;
  * various x86 CPU model's perfctr support.
  */
 struct op_x86_model_spec {
-       unsigned int const num_counters;
-       unsigned int const num_controls;
+       unsigned int num_counters;
+       unsigned int num_controls;
        void (*fill_in_addresses)(struct op_msrs * const msrs);
        void (*setup_ctrs)(struct op_msrs const * const msrs);
        int (*check_ctrs)(unsigned int const cpu, 
@@ -48,9 +48,11 @@ struct op_x86_model_spec {
         void (*save_msr)(struct vcpu * const v, int type, int index, u64 
msr_content);
 };
 
-extern struct op_x86_model_spec const op_ppro_spec;
+extern struct op_x86_model_spec op_ppro_spec;
+extern struct op_x86_model_spec op_arch_perfmon_spec;
 extern struct op_x86_model_spec const op_p4_spec;
 extern struct op_x86_model_spec const op_p4_ht2_spec;
 extern struct op_x86_model_spec const op_athlon_spec;
 
+void arch_perfmon_setup_counters(void);
 #endif /* OP_X86_MODEL_H */
diff -r 65968459de75 -r 15f5cff84adf xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h  Tue Sep 15 10:02:15 2009 +0100
+++ b/xen/include/asm-x86/cpufeature.h  Tue Sep 15 10:03:16 2009 +0100
@@ -76,6 +76,7 @@
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_NOSTOP_TSC (3*32+ 9) /* TSC does not stop in C states */
 #define X86_FEATURE_ARAT       (3*32+ 10) /* Always running APIC timer */
+#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
@@ -188,6 +189,8 @@
                                  && boot_cpu_has(X86_FEATURE_FFXSR))
 
 #define cpu_has_x2apic          boot_cpu_has(X86_FEATURE_X2APIC)
+#define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
+
 #endif /* __ASM_I386_CPUFEATURE_H */
 
 /* 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] xenoprof: support Intel's architectural perfmon registers., Xen patchbot-unstable <=