]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
misc: tegra-profiler: get perfmon extension
authorIgor Nabirushkin <inabirushkin@nvidia.com>
Thu, 5 Jun 2014 05:10:47 +0000 (09:10 +0400)
committerDhiren Parmar <dparmar@nvidia.com>
Tue, 12 Aug 2014 12:46:59 +0000 (05:46 -0700)
Add version of the ARMv8 NVIDIA perfmon extension to
device capabilities.

Bug 1520757

Change-Id: I18d10133272a10e3faf5022b4579c7dfea78791e
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/419274
(cherry picked from commit 1973fe595ad0fc5ec45e65df3c70ffbeaac94e7e)
Reviewed-on: http://git-master/r/454453
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Tested-by: Maxim Morin <mmorin@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
drivers/misc/tegra-profiler/arm_pmu.h
drivers/misc/tegra-profiler/armv7_pmu.c
drivers/misc/tegra-profiler/armv8_events.h
drivers/misc/tegra-profiler/armv8_pmu.c
drivers/misc/tegra-profiler/quadd.h
drivers/misc/tegra-profiler/quadd_proc.c
drivers/misc/tegra-profiler/version.h

index b0d139a9488a25a9ad98b49c01bcf90eb9718ef6..6071c469fe834ce2b24bbc0fa4520067aa890cd8 100644 (file)
@@ -28,9 +28,17 @@ struct quadd_pmu_event_info {
        struct list_head list;
 };
 
+#define QUADD_ARCH_NAME_MAX    64
+
+struct quadd_arch_info {
+       int type;
+       int ver;
+
+       char name[QUADD_ARCH_NAME_MAX];
+};
+
 struct quadd_pmu_ctx {
-       int arch;
-       char arch_name[64];
+       struct quadd_arch_info arch;
 
        u32 counters_mask;
 
index 97ccb65255b5d16816b4d9e24b1074d336893f36..1962a3ea0ba23600fbc10a9778468331ef1b75cb 100644 (file)
@@ -301,8 +301,8 @@ static u32 armv7_pmu_adjust_value(u32 value, int event_id)
        * so currently we are devided by two
        */
        if (pmu_ctx.l1_cache_rw &&
-           (pmu_ctx.arch == QUADD_ARM_CPU_TYPE_CORTEX_A8 ||
-           pmu_ctx.arch == QUADD_ARM_CPU_TYPE_CORTEX_A9) &&
+           (pmu_ctx.arch.type == QUADD_ARM_CPU_TYPE_CORTEX_A8 ||
+           pmu_ctx.arch.type == QUADD_ARM_CPU_TYPE_CORTEX_A9) &&
            (event_id == QUADD_EVENT_TYPE_L1_DCACHE_READ_MISSES ||
            event_id == QUADD_EVENT_TYPE_L1_DCACHE_WRITE_MISSES)) {
                return value / 2;
@@ -722,6 +722,11 @@ static int get_current_events(int *events, int max_events)
        return i;
 }
 
+static struct quadd_arch_info *get_arch(void)
+{
+       return &pmu_ctx.arch;
+}
+
 static struct quadd_event_source_interface pmu_armv7_int = {
        .enable                 = pmu_enable,
        .disable                = pmu_disable,
@@ -737,6 +742,7 @@ static struct quadd_event_source_interface pmu_armv7_int = {
        .set_events             = set_events,
        .get_supported_events   = get_supported_events,
        .get_current_events     = get_current_events,
+       .get_arch               = get_arch,
 };
 
 struct quadd_event_source_interface *quadd_armv7_pmu_init(void)
@@ -748,11 +754,18 @@ struct quadd_event_source_interface *quadd_armv7_pmu_init(void)
        cpu_implementer = cpu_id >> 24;
        part_number = cpu_id & 0xFFF0;
 
+       pmu_ctx.arch.type = QUADD_ARM_CPU_TYPE_UNKNOWN;
+       pmu_ctx.arch.ver = 0;
+       strncpy(pmu_ctx.arch.name, "Unknown",
+               sizeof(pmu_ctx.arch.name));
+
        if (cpu_implementer == ARM_CPU_IMP_ARM) {
                switch (part_number) {
                case ARM_CPU_PART_CORTEX_A9:
-                       pmu_ctx.arch = QUADD_ARM_CPU_TYPE_CORTEX_A9;
-                       strcpy(pmu_ctx.arch_name, "Cortex A9");
+                       pmu_ctx.arch.type = QUADD_ARM_CPU_TYPE_CORTEX_A9;
+                       strncpy(pmu_ctx.arch.name, "Cortex A9",
+                               sizeof(pmu_ctx.arch.name));
+
                        pmu_ctx.counters_mask =
                                QUADD_ARMV7_COUNTERS_MASK_CORTEX_A9;
                        pmu_ctx.current_map = quadd_armv7_a9_events_map;
@@ -760,8 +773,10 @@ struct quadd_event_source_interface *quadd_armv7_pmu_init(void)
                        break;
 
                case ARM_CPU_PART_CORTEX_A15:
-                       pmu_ctx.arch = QUADD_ARM_CPU_TYPE_CORTEX_A15;
-                       strcpy(pmu_ctx.arch_name, "Cortex A15");
+                       pmu_ctx.arch.type = QUADD_ARM_CPU_TYPE_CORTEX_A15;
+                       strncpy(pmu_ctx.arch.name, "Cortex A15",
+                               sizeof(pmu_ctx.arch.name));
+
                        pmu_ctx.counters_mask =
                                QUADD_ARMV7_COUNTERS_MASK_CORTEX_A15;
                        pmu_ctx.current_map = quadd_armv7_a15_events_map;
@@ -769,8 +784,7 @@ struct quadd_event_source_interface *quadd_armv7_pmu_init(void)
                        break;
 
                default:
-                       pmu_ctx.arch = QUADD_ARM_CPU_TYPE_UNKNOWN;
-                       strcpy(pmu_ctx.arch_name, "Unknown");
+                       pmu_ctx.arch.type = QUADD_ARM_CPU_TYPE_UNKNOWN;
                        pmu_ctx.current_map = NULL;
                        break;
                }
@@ -778,7 +792,9 @@ struct quadd_event_source_interface *quadd_armv7_pmu_init(void)
 
        INIT_LIST_HEAD(&pmu_ctx.used_events);
 
-       pr_info("arch: %s\n", pmu_ctx.arch_name);
+       pmu_ctx.arch.name[sizeof(pmu_ctx.arch.name) - 1] = '\0';
+       pr_info("arch: %s, type: %d, ver: %d\n",
+               pmu_ctx.arch.name, pmu_ctx.arch.type, pmu_ctx.arch.ver);
 
        return pmu;
 }
index e5fcf080c91072a822edc264c78dacc537e191d3..1d675ddddabf5517af181117e663cae0934a9db3 100644 (file)
@@ -52,11 +52,11 @@ enum {
 #define QUADD_ARMV8_PMCR_LC            (1 << 6)
 
 /* Number of event counters */
-#define        QUADD_ARMV8_PMCR_N_SHIFT        16
+#define        QUADD_ARMV8_PMCR_N_SHIFT        11
 #define        QUADD_ARMV8_PMCR_N_MASK         0x1f
 
 /* Identification code */
-#define        QUADD_ARMV8_PMCR_IDCODE_SHIFT   11
+#define        QUADD_ARMV8_PMCR_IDCODE_SHIFT   16
 #define        QUADD_ARMV8_PMCR_IDCODE_MASK    0xff
 
 /* Implementer code */
@@ -81,6 +81,9 @@ enum {
 
 #define QUADD_ARMV8_COUNTERS_MASK_PMUV3        0x3f
 
+#define QUADD_ARMV8_PMU_NVEXT_SHIFT    4
+#define QUADD_ARMV8_PMU_NVEXT_MASK     0x0f
+
 /*
  * ARMv8 PMUv3 Performance Events handling code.
  * Common event types.
index 9bc8eb232b62d03577e692b60349578ba8359345..7a4ffc17079a66a14111df98954c44f78c26c584 100644 (file)
@@ -219,9 +219,15 @@ armv8_pmu_pmovsclr_write(int idx)
        asm volatile("msr pmovsclr_el0, %0" : : "r" (BIT(idx)));
 }
 
-/*********************************************************************/
-
+static inline u32
+armv8_id_afr0_el1_read(void)
+{
+       u32 val;
 
+       /* Read Auxiliary Feature Register 0 */
+       asm volatile("mrs %0, id_afr0_el1" : "=r" (val));
+       return val;
+}
 
 static void enable_counter(int idx)
 {
@@ -710,7 +716,10 @@ static int get_current_events(int *events, int max_events)
        return i;
 }
 
-/*********************************************************************/
+static struct quadd_arch_info *get_arch(void)
+{
+       return &pmu_ctx.arch;
+}
 
 static struct quadd_event_source_interface pmu_armv8_int = {
        .enable                 = pmu_enable,
@@ -727,6 +736,7 @@ static struct quadd_event_source_interface pmu_armv8_int = {
        .set_events             = set_events,
        .get_supported_events   = get_supported_events,
        .get_current_events     = get_current_events,
+       .get_arch               = get_arch,
 };
 
 struct quadd_event_source_interface *quadd_armv8_pmu_init(void)
@@ -737,11 +747,16 @@ struct quadd_event_source_interface *quadd_armv8_pmu_init(void)
        u64 aa64_dfr = read_cpuid(ID_AA64DFR0_EL1);
        aa64_dfr = (aa64_dfr >> 8) & 0x0f;
 
-       pmu_ctx.arch = QUADD_AA64_CPU_TYPE_UNKNOWN;
+       strncpy(pmu_ctx.arch.name, "Unknown", sizeof(pmu_ctx.arch.name));
+       pmu_ctx.arch.type = QUADD_AA64_CPU_TYPE_UNKNOWN;
+       pmu_ctx.arch.ver = 0;
 
        switch (aa64_dfr) {
        case QUADD_AA64_PMUVER_PMUV3:
-               strcpy(pmu_ctx.arch_name, "AA64 PmuV3");
+               strncpy(pmu_ctx.arch.name, "AA64 PmuV3",
+                       sizeof(pmu_ctx.arch.name));
+               pmu_ctx.arch.name[sizeof(pmu_ctx.arch.name) - 1] = '\0';
+
                pmu_ctx.counters_mask =
                        QUADD_ARMV8_COUNTERS_MASK_PMUV3;
                pmu_ctx.current_map = quadd_armv8_pmuv3_events_map;
@@ -755,19 +770,35 @@ struct quadd_event_source_interface *quadd_armv8_pmu_init(void)
                pr_info("imp: %#x, idcode: %#x\n", imp, idcode);
 
                if (imp == ARM_CPU_IMP_ARM) {
-                       strcat(pmu_ctx.arch_name, " ARM");
+                       strncat(pmu_ctx.arch.name, " ARM",
+                               sizeof(pmu_ctx.arch.name) -
+                               strlen(pmu_ctx.arch.name));
+                       pmu_ctx.arch.name[sizeof(pmu_ctx.arch.name) - 1] = '\0';
+
                        if (idcode == QUADD_AA64_CPU_IDCODE_CORTEX_A57) {
-                               pmu_ctx.arch = QUADD_AA64_CPU_TYPE_CORTEX_A57;
-                               strcat(pmu_ctx.arch_name, " CORTEX_A57");
+                               pmu_ctx.arch.type =
+                                       QUADD_AA64_CPU_TYPE_CORTEX_A57;
+                               strncat(pmu_ctx.arch.name, " CORTEX_A57",
+                                       sizeof(pmu_ctx.arch.name) -
+                                       strlen(pmu_ctx.arch.name));
                        } else {
-                               pmu_ctx.arch = QUADD_AA64_CPU_TYPE_ARM;
+                               pmu_ctx.arch.type = QUADD_AA64_CPU_TYPE_ARM;
                        }
                } else if (imp == QUADD_AA64_CPU_IMP_NVIDIA) {
-                       strcat(pmu_ctx.arch_name, " Nvidia");
-                       pmu_ctx.arch = QUADD_AA64_CPU_TYPE_DENVER;
+                       u32 ext_ver = armv8_id_afr0_el1_read();
+                       ext_ver = (ext_ver >> QUADD_ARMV8_PMU_NVEXT_SHIFT) &
+                                 QUADD_ARMV8_PMU_NVEXT_MASK;
+
+                       strncat(pmu_ctx.arch.name, " NVIDIA (Denver)",
+                               sizeof(pmu_ctx.arch.name) -
+                               strlen(pmu_ctx.arch.name));
+                       pmu_ctx.arch.type = QUADD_AA64_CPU_TYPE_DENVER;
+                       pmu_ctx.arch.ver = ext_ver;
                } else {
-                       strcat(pmu_ctx.arch_name, " Unknown");
-                       pmu_ctx.arch = QUADD_AA64_CPU_TYPE_UNKNOWN_IMP;
+                       strncat(pmu_ctx.arch.name, " Unknown implementor code",
+                               sizeof(pmu_ctx.arch.name) -
+                               strlen(pmu_ctx.arch.name));
+                       pmu_ctx.arch.type = QUADD_AA64_CPU_TYPE_UNKNOWN_IMP;
                }
 
                pmu = &pmu_armv8_int;
@@ -780,7 +811,9 @@ struct quadd_event_source_interface *quadd_armv8_pmu_init(void)
 
        INIT_LIST_HEAD(&pmu_ctx.used_events);
 
-       pr_info("arch: %s\n", pmu_ctx.arch_name);
+       pmu_ctx.arch.name[sizeof(pmu_ctx.arch.name) - 1] = '\0';
+       pr_info("arch: %s, type: %d, ver: %d\n",
+               pmu_ctx.arch.name, pmu_ctx.arch.type, pmu_ctx.arch.ver);
 
        return pmu;
 }
index 9de52c773722c6088e9ed875456a1dedae186be7..c25835e29f09bdc0265fa26d43d9d5f75bd0427a 100644 (file)
@@ -25,6 +25,7 @@ struct event_data;
 struct quadd_comm_data_interface;
 struct quadd_hrt_ctx;
 struct quadd_module_state;
+struct quadd_arch_info;
 
 struct quadd_event_source_interface {
        int (*enable)(void);
@@ -35,6 +36,7 @@ struct quadd_event_source_interface {
        int (*set_events)(int *events, int size);
        int (*get_supported_events)(int *events, int max_events);
        int (*get_current_events)(int *events, int max_events);
+       struct quadd_arch_info * (*get_arch)(void);
 };
 
 struct source_info {
index b7993e8ac8e6046e43cb7f94b0eca6f033ba53f7..8f656fae213e67548687355d9908315cad1becb9 100644 (file)
@@ -24,6 +24,7 @@
 #include "quadd.h"
 #include "version.h"
 #include "quadd_proc.h"
+#include "arm_pmu.h"
 
 #define YES_NO(x) ((x) ? "yes" : "no")
 
@@ -58,6 +59,10 @@ static int show_capabilities(struct seq_file *f, void *offset)
        struct quadd_comm_cap *cap = &ctx->cap;
        struct quadd_events_cap *event = &cap->events_cap;
        unsigned int extra = cap->reserved[QUADD_COMM_CAP_IDX_EXTRA];
+       struct quadd_arch_info *arch = NULL;
+
+       if (ctx->pmu)
+               arch = ctx->pmu->get_arch();
 
        seq_printf(f, "pmu:                                   %s\n",
                   YES_NO(cap->pmu));
@@ -69,7 +74,7 @@ static int show_capabilities(struct seq_file *f, void *offset)
        seq_printf(f, "l2 cache:                              %s\n",
                   YES_NO(cap->l2_cache));
        if (cap->l2_cache) {
-               seq_printf(f, "multiple l2 events:             %s\n",
+               seq_printf(f, "multiple l2 events:                    %s\n",
                           YES_NO(cap->l2_multiple_events));
        }
 
@@ -92,6 +97,15 @@ static int show_capabilities(struct seq_file *f, void *offset)
        seq_printf(f, "information about unwind entry:        %s\n",
                   YES_NO(extra & QUADD_COMM_CAP_EXTRA_UNW_ENTRY_TYPE));
 
+       seq_puts(f, "\n");
+
+       if (arch) {
+               seq_printf(f, "pmu arch:                              %s\n",
+                       arch->name);
+               seq_printf(f, "pmu arch version:                      %d\n",
+                       arch->ver);
+       }
+
        seq_puts(f, "\n");
        seq_puts(f, "Supported events:\n");
        seq_printf(f, "cpu_cycles:                     %s\n",
index 779dc6b5ac4d0197428c9622efbeacb68010857b..392ea70b7a913974aeea6a7e98bad2cd76510006 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __QUADD_VERSION_H
 #define __QUADD_VERSION_H
 
-#define QUADD_MODULE_VERSION           "1.71"
+#define QUADD_MODULE_VERSION           "1.72"
 #define QUADD_MODULE_BRANCH            "Dev"
 
 #endif /* __QUADD_VERSION_H */