linux/arch/powerpc/perf/power8-pmu.c
<<
>>
Prefs
   1/*
   2 * Performance counter support for POWER8 processors.
   3 *
   4 * Copyright 2009 Paul Mackerras, IBM Corporation.
   5 * Copyright 2013 Michael Ellerman, IBM Corporation.
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * as published by the Free Software Foundation; either version
  10 * 2 of the License, or (at your option) any later version.
  11 */
  12
  13#define pr_fmt(fmt)     "power8-pmu: " fmt
  14
  15#include "isa207-common.h"
  16
  17/*
  18 * Some power8 event codes.
  19 */
  20#define EVENT(_name, _code)     _name = _code,
  21
  22enum {
  23#include "power8-events-list.h"
  24};
  25
  26#undef EVENT
  27
  28/* MMCRA IFM bits - POWER8 */
  29#define POWER8_MMCRA_IFM1               0x0000000040000000UL
  30#define POWER8_MMCRA_IFM2               0x0000000080000000UL
  31#define POWER8_MMCRA_IFM3               0x00000000C0000000UL
  32
  33/* PowerISA v2.07 format attribute structure*/
  34extern struct attribute_group isa207_pmu_format_group;
  35
  36/* Table of alternatives, sorted by column 0 */
  37static const unsigned int event_alternatives[][MAX_ALT] = {
  38        { PM_MRK_ST_CMPL,               PM_MRK_ST_CMPL_ALT },
  39        { PM_BR_MRK_2PATH,              PM_BR_MRK_2PATH_ALT },
  40        { PM_L3_CO_MEPF,                PM_L3_CO_MEPF_ALT },
  41        { PM_MRK_DATA_FROM_L2MISS,      PM_MRK_DATA_FROM_L2MISS_ALT },
  42        { PM_CMPLU_STALL_ALT,           PM_CMPLU_STALL },
  43        { PM_BR_2PATH,                  PM_BR_2PATH_ALT },
  44        { PM_INST_DISP,                 PM_INST_DISP_ALT },
  45        { PM_RUN_CYC_ALT,               PM_RUN_CYC },
  46        { PM_MRK_FILT_MATCH,            PM_MRK_FILT_MATCH_ALT },
  47        { PM_LD_MISS_L1,                PM_LD_MISS_L1_ALT },
  48        { PM_RUN_INST_CMPL_ALT,         PM_RUN_INST_CMPL },
  49};
  50
  51static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
  52{
  53        int num_alt = 0;
  54
  55        num_alt = isa207_get_alternatives(event, alt,
  56                                          ARRAY_SIZE(event_alternatives), flags,
  57                                          event_alternatives);
  58
  59        return num_alt;
  60}
  61
  62GENERIC_EVENT_ATTR(cpu-cycles,                  PM_CYC);
  63GENERIC_EVENT_ATTR(stalled-cycles-frontend,     PM_GCT_NOSLOT_CYC);
  64GENERIC_EVENT_ATTR(stalled-cycles-backend,      PM_CMPLU_STALL);
  65GENERIC_EVENT_ATTR(instructions,                PM_INST_CMPL);
  66GENERIC_EVENT_ATTR(branch-instructions,         PM_BRU_FIN);
  67GENERIC_EVENT_ATTR(branch-misses,               PM_BR_MPRED_CMPL);
  68GENERIC_EVENT_ATTR(cache-references,            PM_LD_REF_L1);
  69GENERIC_EVENT_ATTR(cache-misses,                PM_LD_MISS_L1);
  70GENERIC_EVENT_ATTR(mem_access,                  MEM_ACCESS);
  71
  72CACHE_EVENT_ATTR(L1-dcache-load-misses,         PM_LD_MISS_L1);
  73CACHE_EVENT_ATTR(L1-dcache-loads,               PM_LD_REF_L1);
  74
  75CACHE_EVENT_ATTR(L1-dcache-prefetches,          PM_L1_PREF);
  76CACHE_EVENT_ATTR(L1-dcache-store-misses,        PM_ST_MISS_L1);
  77CACHE_EVENT_ATTR(L1-icache-load-misses,         PM_L1_ICACHE_MISS);
  78CACHE_EVENT_ATTR(L1-icache-loads,               PM_INST_FROM_L1);
  79CACHE_EVENT_ATTR(L1-icache-prefetches,          PM_IC_PREF_WRITE);
  80
  81CACHE_EVENT_ATTR(LLC-load-misses,               PM_DATA_FROM_L3MISS);
  82CACHE_EVENT_ATTR(LLC-loads,                     PM_DATA_FROM_L3);
  83CACHE_EVENT_ATTR(LLC-prefetches,                PM_L3_PREF_ALL);
  84CACHE_EVENT_ATTR(LLC-store-misses,              PM_L2_ST_MISS);
  85CACHE_EVENT_ATTR(LLC-stores,                    PM_L2_ST);
  86
  87CACHE_EVENT_ATTR(branch-load-misses,            PM_BR_MPRED_CMPL);
  88CACHE_EVENT_ATTR(branch-loads,                  PM_BRU_FIN);
  89CACHE_EVENT_ATTR(dTLB-load-misses,              PM_DTLB_MISS);
  90CACHE_EVENT_ATTR(iTLB-load-misses,              PM_ITLB_MISS);
  91
  92static struct attribute *power8_events_attr[] = {
  93        GENERIC_EVENT_PTR(PM_CYC),
  94        GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
  95        GENERIC_EVENT_PTR(PM_CMPLU_STALL),
  96        GENERIC_EVENT_PTR(PM_INST_CMPL),
  97        GENERIC_EVENT_PTR(PM_BRU_FIN),
  98        GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
  99        GENERIC_EVENT_PTR(PM_LD_REF_L1),
 100        GENERIC_EVENT_PTR(PM_LD_MISS_L1),
 101        GENERIC_EVENT_PTR(MEM_ACCESS),
 102
 103        CACHE_EVENT_PTR(PM_LD_MISS_L1),
 104        CACHE_EVENT_PTR(PM_LD_REF_L1),
 105        CACHE_EVENT_PTR(PM_L1_PREF),
 106        CACHE_EVENT_PTR(PM_ST_MISS_L1),
 107        CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
 108        CACHE_EVENT_PTR(PM_INST_FROM_L1),
 109        CACHE_EVENT_PTR(PM_IC_PREF_WRITE),
 110        CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
 111        CACHE_EVENT_PTR(PM_DATA_FROM_L3),
 112        CACHE_EVENT_PTR(PM_L3_PREF_ALL),
 113        CACHE_EVENT_PTR(PM_L2_ST_MISS),
 114        CACHE_EVENT_PTR(PM_L2_ST),
 115
 116        CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
 117        CACHE_EVENT_PTR(PM_BRU_FIN),
 118
 119        CACHE_EVENT_PTR(PM_DTLB_MISS),
 120        CACHE_EVENT_PTR(PM_ITLB_MISS),
 121        NULL
 122};
 123
 124static struct attribute_group power8_pmu_events_group = {
 125        .name = "events",
 126        .attrs = power8_events_attr,
 127};
 128
 129static const struct attribute_group *power8_pmu_attr_groups[] = {
 130        &isa207_pmu_format_group,
 131        &power8_pmu_events_group,
 132        NULL,
 133};
 134
 135static int power8_generic_events[] = {
 136        [PERF_COUNT_HW_CPU_CYCLES] =                    PM_CYC,
 137        [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =       PM_GCT_NOSLOT_CYC,
 138        [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =        PM_CMPLU_STALL,
 139        [PERF_COUNT_HW_INSTRUCTIONS] =                  PM_INST_CMPL,
 140        [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =           PM_BRU_FIN,
 141        [PERF_COUNT_HW_BRANCH_MISSES] =                 PM_BR_MPRED_CMPL,
 142        [PERF_COUNT_HW_CACHE_REFERENCES] =              PM_LD_REF_L1,
 143        [PERF_COUNT_HW_CACHE_MISSES] =                  PM_LD_MISS_L1,
 144};
 145
 146static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 147{
 148        u64 pmu_bhrb_filter = 0;
 149
 150        /* BHRB and regular PMU events share the same privilege state
 151         * filter configuration. BHRB is always recorded along with a
 152         * regular PMU event. As the privilege state filter is handled
 153         * in the basic PMC configuration of the accompanying regular
 154         * PMU event, we ignore any separate BHRB specific request.
 155         */
 156
 157        /* No branch filter requested */
 158        if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
 159                return pmu_bhrb_filter;
 160
 161        /* Invalid branch filter options - HW does not support */
 162        if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
 163                return -1;
 164
 165        if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
 166                return -1;
 167
 168        if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
 169                return -1;
 170
 171        if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
 172                pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
 173                return pmu_bhrb_filter;
 174        }
 175
 176        /* Every thing else is unsupported */
 177        return -1;
 178}
 179
 180static void power8_config_bhrb(u64 pmu_bhrb_filter)
 181{
 182        /* Enable BHRB filter in PMU */
 183        mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
 184}
 185
 186#define C(x)    PERF_COUNT_HW_CACHE_##x
 187
 188/*
 189 * Table of generalized cache-related events.
 190 * 0 means not supported, -1 means nonsensical, other values
 191 * are event codes.
 192 */
 193static int power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 194        [ C(L1D) ] = {
 195                [ C(OP_READ) ] = {
 196                        [ C(RESULT_ACCESS) ] = PM_LD_REF_L1,
 197                        [ C(RESULT_MISS)   ] = PM_LD_MISS_L1,
 198                },
 199                [ C(OP_WRITE) ] = {
 200                        [ C(RESULT_ACCESS) ] = 0,
 201                        [ C(RESULT_MISS)   ] = PM_ST_MISS_L1,
 202                },
 203                [ C(OP_PREFETCH) ] = {
 204                        [ C(RESULT_ACCESS) ] = PM_L1_PREF,
 205                        [ C(RESULT_MISS)   ] = 0,
 206                },
 207        },
 208        [ C(L1I) ] = {
 209                [ C(OP_READ) ] = {
 210                        [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1,
 211                        [ C(RESULT_MISS)   ] = PM_L1_ICACHE_MISS,
 212                },
 213                [ C(OP_WRITE) ] = {
 214                        [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE,
 215                        [ C(RESULT_MISS)   ] = -1,
 216                },
 217                [ C(OP_PREFETCH) ] = {
 218                        [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE,
 219                        [ C(RESULT_MISS)   ] = 0,
 220                },
 221        },
 222        [ C(LL) ] = {
 223                [ C(OP_READ) ] = {
 224                        [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3,
 225                        [ C(RESULT_MISS)   ] = PM_DATA_FROM_L3MISS,
 226                },
 227                [ C(OP_WRITE) ] = {
 228                        [ C(RESULT_ACCESS) ] = PM_L2_ST,
 229                        [ C(RESULT_MISS)   ] = PM_L2_ST_MISS,
 230                },
 231                [ C(OP_PREFETCH) ] = {
 232                        [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL,
 233                        [ C(RESULT_MISS)   ] = 0,
 234                },
 235        },
 236        [ C(DTLB) ] = {
 237                [ C(OP_READ) ] = {
 238                        [ C(RESULT_ACCESS) ] = 0,
 239                        [ C(RESULT_MISS)   ] = PM_DTLB_MISS,
 240                },
 241                [ C(OP_WRITE) ] = {
 242                        [ C(RESULT_ACCESS) ] = -1,
 243                        [ C(RESULT_MISS)   ] = -1,
 244                },
 245                [ C(OP_PREFETCH) ] = {
 246                        [ C(RESULT_ACCESS) ] = -1,
 247                        [ C(RESULT_MISS)   ] = -1,
 248                },
 249        },
 250        [ C(ITLB) ] = {
 251                [ C(OP_READ) ] = {
 252                        [ C(RESULT_ACCESS) ] = 0,
 253                        [ C(RESULT_MISS)   ] = PM_ITLB_MISS,
 254                },
 255                [ C(OP_WRITE) ] = {
 256                        [ C(RESULT_ACCESS) ] = -1,
 257                        [ C(RESULT_MISS)   ] = -1,
 258                },
 259                [ C(OP_PREFETCH) ] = {
 260                        [ C(RESULT_ACCESS) ] = -1,
 261                        [ C(RESULT_MISS)   ] = -1,
 262                },
 263        },
 264        [ C(BPU) ] = {
 265                [ C(OP_READ) ] = {
 266                        [ C(RESULT_ACCESS) ] = PM_BRU_FIN,
 267                        [ C(RESULT_MISS)   ] = PM_BR_MPRED_CMPL,
 268                },
 269                [ C(OP_WRITE) ] = {
 270                        [ C(RESULT_ACCESS) ] = -1,
 271                        [ C(RESULT_MISS)   ] = -1,
 272                },
 273                [ C(OP_PREFETCH) ] = {
 274                        [ C(RESULT_ACCESS) ] = -1,
 275                        [ C(RESULT_MISS)   ] = -1,
 276                },
 277        },
 278        [ C(NODE) ] = {
 279                [ C(OP_READ) ] = {
 280                        [ C(RESULT_ACCESS) ] = -1,
 281                        [ C(RESULT_MISS)   ] = -1,
 282                },
 283                [ C(OP_WRITE) ] = {
 284                        [ C(RESULT_ACCESS) ] = -1,
 285                        [ C(RESULT_MISS)   ] = -1,
 286                },
 287                [ C(OP_PREFETCH) ] = {
 288                        [ C(RESULT_ACCESS) ] = -1,
 289                        [ C(RESULT_MISS)   ] = -1,
 290                },
 291        },
 292};
 293
 294#undef C
 295
 296static struct power_pmu power8_pmu = {
 297        .name                   = "POWER8",
 298        .n_counter              = MAX_PMU_COUNTERS,
 299        .max_alternatives       = MAX_ALT + 1,
 300        .add_fields             = ISA207_ADD_FIELDS,
 301        .test_adder             = ISA207_TEST_ADDER,
 302        .compute_mmcr           = isa207_compute_mmcr,
 303        .config_bhrb            = power8_config_bhrb,
 304        .bhrb_filter_map        = power8_bhrb_filter_map,
 305        .get_constraint         = isa207_get_constraint,
 306        .get_alternatives       = power8_get_alternatives,
 307        .get_mem_data_src       = isa207_get_mem_data_src,
 308        .get_mem_weight         = isa207_get_mem_weight,
 309        .disable_pmc            = isa207_disable_pmc,
 310        .flags                  = PPMU_HAS_SIER | PPMU_ARCH_207S,
 311        .n_generic              = ARRAY_SIZE(power8_generic_events),
 312        .generic_events         = power8_generic_events,
 313        .cache_events           = &power8_cache_events,
 314        .attr_groups            = power8_pmu_attr_groups,
 315        .bhrb_nr                = 32,
 316};
 317
 318static int __init init_power8_pmu(void)
 319{
 320        int rc;
 321
 322        if (!cur_cpu_spec->oprofile_cpu_type ||
 323            strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8"))
 324                return -ENODEV;
 325
 326        rc = register_power_pmu(&power8_pmu);
 327        if (rc)
 328                return rc;
 329
 330        /* Tell userspace that EBB is supported */
 331        cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
 332
 333        if (cpu_has_feature(CPU_FTR_PMAO_BUG))
 334                pr_info("PMAO restore workaround active.\n");
 335
 336        return 0;
 337}
 338early_initcall(init_power8_pmu);
 339