Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Performance counter support for POWER8 processors.
0004  *
0005  * Copyright 2009 Paul Mackerras, IBM Corporation.
0006  * Copyright 2013 Michael Ellerman, IBM Corporation.
0007  */
0008 
0009 #define pr_fmt(fmt) "power8-pmu: " fmt
0010 
0011 #include "isa207-common.h"
0012 
0013 /*
0014  * Some power8 event codes.
0015  */
0016 #define EVENT(_name, _code) _name = _code,
0017 
0018 enum {
0019 #include "power8-events-list.h"
0020 };
0021 
0022 #undef EVENT
0023 
0024 /* MMCRA IFM bits - POWER8 */
0025 #define POWER8_MMCRA_IFM1       0x0000000040000000UL
0026 #define POWER8_MMCRA_IFM2       0x0000000080000000UL
0027 #define POWER8_MMCRA_IFM3       0x00000000C0000000UL
0028 #define POWER8_MMCRA_BHRB_MASK      0x00000000C0000000UL
0029 
0030 /*
0031  * Raw event encoding for PowerISA v2.07 (Power8):
0032  *
0033  *        60        56        52        48        44        40        36        32
0034  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
0035  *   | | [ ]                           [      thresh_cmp     ]   [  thresh_ctl   ]
0036  *   | |  |                                                              |
0037  *   | |  *- IFM (Linux)                 thresh start/stop OR FAB match -*
0038  *   | *- BHRB (Linux)
0039  *   *- EBB (Linux)
0040  *
0041  *        28        24        20        16        12         8         4         0
0042  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
0043  *   [   ] [  sample ]   [cache]   [ pmc ]   [unit ]   c     m   [    pmcxsel    ]
0044  *     |        |           |                          |     |
0045  *     |        |           |                          |     *- mark
0046  *     |        |           *- L1/L2/L3 cache_sel      |
0047  *     |        |                                      |
0048  *     |        *- sampling mode for marked events     *- combine
0049  *     |
0050  *     *- thresh_sel
0051  *
0052  * Below uses IBM bit numbering.
0053  *
0054  * MMCR1[x:y] = unit    (PMCxUNIT)
0055  * MMCR1[x]   = combine (PMCxCOMB)
0056  *
0057  * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
0058  *  # PM_MRK_FAB_RSP_MATCH
0059  *  MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
0060  * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
0061  *  # PM_MRK_FAB_RSP_MATCH_CYC
0062  *  MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
0063  * else
0064  *  MMCRA[48:55] = thresh_ctl   (THRESH START/END)
0065  *
0066  * if thresh_sel:
0067  *  MMCRA[45:47] = thresh_sel
0068  *
0069  * if thresh_cmp:
0070  *  MMCRA[22:24] = thresh_cmp[0:2]
0071  *  MMCRA[25:31] = thresh_cmp[3:9]
0072  *
0073  * if unit == 6 or unit == 7
0074  *  MMCRC[53:55] = cache_sel[1:3]      (L2EVENT_SEL)
0075  * else if unit == 8 or unit == 9:
0076  *  if cache_sel[0] == 0: # L3 bank
0077  *      MMCRC[47:49] = cache_sel[1:3]  (L3EVENT_SEL0)
0078  *  else if cache_sel[0] == 1:
0079  *      MMCRC[50:51] = cache_sel[2:3]  (L3EVENT_SEL1)
0080  * else if cache_sel[1]: # L1 event
0081  *  MMCR1[16] = cache_sel[2]
0082  * MMCR1[17] = cache_sel[3]
0083  *
0084  * if mark:
0085  *  MMCRA[63]    = 1        (SAMPLE_ENABLE)
0086  *  MMCRA[57:59] = sample[0:2]  (RAND_SAMP_ELIG)
0087  * MMCRA[61:62] = sample[3:4]  (RAND_SAMP_MODE)
0088  *
0089  * if EBB and BHRB:
0090  *  MMCRA[32:33] = IFM
0091  *
0092  */
0093 
0094 /* PowerISA v2.07 format attribute structure*/
0095 extern const struct attribute_group isa207_pmu_format_group;
0096 
0097 /* Table of alternatives, sorted by column 0 */
0098 static const unsigned int event_alternatives[][MAX_ALT] = {
0099     { PM_MRK_ST_CMPL,       PM_MRK_ST_CMPL_ALT },
0100     { PM_BR_MRK_2PATH,      PM_BR_MRK_2PATH_ALT },
0101     { PM_L3_CO_MEPF,        PM_L3_CO_MEPF_ALT },
0102     { PM_MRK_DATA_FROM_L2MISS,  PM_MRK_DATA_FROM_L2MISS_ALT },
0103     { PM_CMPLU_STALL_ALT,       PM_CMPLU_STALL },
0104     { PM_BR_2PATH,          PM_BR_2PATH_ALT },
0105     { PM_INST_DISP,         PM_INST_DISP_ALT },
0106     { PM_RUN_CYC_ALT,       PM_RUN_CYC },
0107     { PM_MRK_FILT_MATCH,        PM_MRK_FILT_MATCH_ALT },
0108     { PM_LD_MISS_L1,        PM_LD_MISS_L1_ALT },
0109     { PM_RUN_INST_CMPL_ALT,     PM_RUN_INST_CMPL },
0110 };
0111 
0112 static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0113 {
0114     int num_alt = 0;
0115 
0116     num_alt = isa207_get_alternatives(event, alt,
0117                       ARRAY_SIZE(event_alternatives), flags,
0118                       event_alternatives);
0119 
0120     return num_alt;
0121 }
0122 
0123 GENERIC_EVENT_ATTR(cpu-cycles,          PM_CYC);
0124 GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC);
0125 GENERIC_EVENT_ATTR(stalled-cycles-backend,  PM_CMPLU_STALL);
0126 GENERIC_EVENT_ATTR(instructions,        PM_INST_CMPL);
0127 GENERIC_EVENT_ATTR(branch-instructions,     PM_BRU_FIN);
0128 GENERIC_EVENT_ATTR(branch-misses,       PM_BR_MPRED_CMPL);
0129 GENERIC_EVENT_ATTR(cache-references,        PM_LD_REF_L1);
0130 GENERIC_EVENT_ATTR(cache-misses,        PM_LD_MISS_L1);
0131 GENERIC_EVENT_ATTR(mem_access,          MEM_ACCESS);
0132 
0133 CACHE_EVENT_ATTR(L1-dcache-load-misses,     PM_LD_MISS_L1);
0134 CACHE_EVENT_ATTR(L1-dcache-loads,       PM_LD_REF_L1);
0135 
0136 CACHE_EVENT_ATTR(L1-dcache-prefetches,      PM_L1_PREF);
0137 CACHE_EVENT_ATTR(L1-dcache-store-misses,    PM_ST_MISS_L1);
0138 CACHE_EVENT_ATTR(L1-icache-load-misses,     PM_L1_ICACHE_MISS);
0139 CACHE_EVENT_ATTR(L1-icache-loads,       PM_INST_FROM_L1);
0140 CACHE_EVENT_ATTR(L1-icache-prefetches,      PM_IC_PREF_WRITE);
0141 
0142 CACHE_EVENT_ATTR(LLC-load-misses,       PM_DATA_FROM_L3MISS);
0143 CACHE_EVENT_ATTR(LLC-loads,         PM_DATA_FROM_L3);
0144 CACHE_EVENT_ATTR(LLC-prefetches,        PM_L3_PREF_ALL);
0145 CACHE_EVENT_ATTR(LLC-store-misses,      PM_L2_ST_MISS);
0146 CACHE_EVENT_ATTR(LLC-stores,            PM_L2_ST);
0147 
0148 CACHE_EVENT_ATTR(branch-load-misses,        PM_BR_MPRED_CMPL);
0149 CACHE_EVENT_ATTR(branch-loads,          PM_BRU_FIN);
0150 CACHE_EVENT_ATTR(dTLB-load-misses,      PM_DTLB_MISS);
0151 CACHE_EVENT_ATTR(iTLB-load-misses,      PM_ITLB_MISS);
0152 
0153 static struct attribute *power8_events_attr[] = {
0154     GENERIC_EVENT_PTR(PM_CYC),
0155     GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
0156     GENERIC_EVENT_PTR(PM_CMPLU_STALL),
0157     GENERIC_EVENT_PTR(PM_INST_CMPL),
0158     GENERIC_EVENT_PTR(PM_BRU_FIN),
0159     GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
0160     GENERIC_EVENT_PTR(PM_LD_REF_L1),
0161     GENERIC_EVENT_PTR(PM_LD_MISS_L1),
0162     GENERIC_EVENT_PTR(MEM_ACCESS),
0163 
0164     CACHE_EVENT_PTR(PM_LD_MISS_L1),
0165     CACHE_EVENT_PTR(PM_LD_REF_L1),
0166     CACHE_EVENT_PTR(PM_L1_PREF),
0167     CACHE_EVENT_PTR(PM_ST_MISS_L1),
0168     CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
0169     CACHE_EVENT_PTR(PM_INST_FROM_L1),
0170     CACHE_EVENT_PTR(PM_IC_PREF_WRITE),
0171     CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
0172     CACHE_EVENT_PTR(PM_DATA_FROM_L3),
0173     CACHE_EVENT_PTR(PM_L3_PREF_ALL),
0174     CACHE_EVENT_PTR(PM_L2_ST_MISS),
0175     CACHE_EVENT_PTR(PM_L2_ST),
0176 
0177     CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
0178     CACHE_EVENT_PTR(PM_BRU_FIN),
0179 
0180     CACHE_EVENT_PTR(PM_DTLB_MISS),
0181     CACHE_EVENT_PTR(PM_ITLB_MISS),
0182     NULL
0183 };
0184 
0185 static const struct attribute_group power8_pmu_events_group = {
0186     .name = "events",
0187     .attrs = power8_events_attr,
0188 };
0189 
0190 static struct attribute *power8_pmu_caps_attrs[] = {
0191     NULL
0192 };
0193 
0194 static struct attribute_group power8_pmu_caps_group = {
0195     .name  = "caps",
0196     .attrs = power8_pmu_caps_attrs,
0197 };
0198 
0199 static const struct attribute_group *power8_pmu_attr_groups[] = {
0200     &isa207_pmu_format_group,
0201     &power8_pmu_events_group,
0202     &power8_pmu_caps_group,
0203     NULL,
0204 };
0205 
0206 static int power8_generic_events[] = {
0207     [PERF_COUNT_HW_CPU_CYCLES] =            PM_CYC,
0208     [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =   PM_GCT_NOSLOT_CYC,
0209     [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =    PM_CMPLU_STALL,
0210     [PERF_COUNT_HW_INSTRUCTIONS] =          PM_INST_CMPL,
0211     [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =       PM_BRU_FIN,
0212     [PERF_COUNT_HW_BRANCH_MISSES] =         PM_BR_MPRED_CMPL,
0213     [PERF_COUNT_HW_CACHE_REFERENCES] =      PM_LD_REF_L1,
0214     [PERF_COUNT_HW_CACHE_MISSES] =          PM_LD_MISS_L1,
0215 };
0216 
0217 static u64 power8_bhrb_filter_map(u64 branch_sample_type)
0218 {
0219     u64 pmu_bhrb_filter = 0;
0220 
0221     /* BHRB and regular PMU events share the same privilege state
0222      * filter configuration. BHRB is always recorded along with a
0223      * regular PMU event. As the privilege state filter is handled
0224      * in the basic PMC configuration of the accompanying regular
0225      * PMU event, we ignore any separate BHRB specific request.
0226      */
0227 
0228     /* No branch filter requested */
0229     if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
0230         return pmu_bhrb_filter;
0231 
0232     /* Invalid branch filter options - HW does not support */
0233     if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
0234         return -1;
0235 
0236     if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
0237         return -1;
0238 
0239     if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
0240         return -1;
0241 
0242     if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
0243         pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
0244         return pmu_bhrb_filter;
0245     }
0246 
0247     /* Every thing else is unsupported */
0248     return -1;
0249 }
0250 
0251 static void power8_config_bhrb(u64 pmu_bhrb_filter)
0252 {
0253     pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
0254 
0255     /* Enable BHRB filter in PMU */
0256     mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
0257 }
0258 
0259 #define C(x)    PERF_COUNT_HW_CACHE_##x
0260 
0261 /*
0262  * Table of generalized cache-related events.
0263  * 0 means not supported, -1 means nonsensical, other values
0264  * are event codes.
0265  */
0266 static u64 power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0267     [ C(L1D) ] = {
0268         [ C(OP_READ) ] = {
0269             [ C(RESULT_ACCESS) ] = PM_LD_REF_L1,
0270             [ C(RESULT_MISS)   ] = PM_LD_MISS_L1,
0271         },
0272         [ C(OP_WRITE) ] = {
0273             [ C(RESULT_ACCESS) ] = 0,
0274             [ C(RESULT_MISS)   ] = PM_ST_MISS_L1,
0275         },
0276         [ C(OP_PREFETCH) ] = {
0277             [ C(RESULT_ACCESS) ] = PM_L1_PREF,
0278             [ C(RESULT_MISS)   ] = 0,
0279         },
0280     },
0281     [ C(L1I) ] = {
0282         [ C(OP_READ) ] = {
0283             [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1,
0284             [ C(RESULT_MISS)   ] = PM_L1_ICACHE_MISS,
0285         },
0286         [ C(OP_WRITE) ] = {
0287             [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE,
0288             [ C(RESULT_MISS)   ] = -1,
0289         },
0290         [ C(OP_PREFETCH) ] = {
0291             [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE,
0292             [ C(RESULT_MISS)   ] = 0,
0293         },
0294     },
0295     [ C(LL) ] = {
0296         [ C(OP_READ) ] = {
0297             [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3,
0298             [ C(RESULT_MISS)   ] = PM_DATA_FROM_L3MISS,
0299         },
0300         [ C(OP_WRITE) ] = {
0301             [ C(RESULT_ACCESS) ] = PM_L2_ST,
0302             [ C(RESULT_MISS)   ] = PM_L2_ST_MISS,
0303         },
0304         [ C(OP_PREFETCH) ] = {
0305             [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL,
0306             [ C(RESULT_MISS)   ] = 0,
0307         },
0308     },
0309     [ C(DTLB) ] = {
0310         [ C(OP_READ) ] = {
0311             [ C(RESULT_ACCESS) ] = 0,
0312             [ C(RESULT_MISS)   ] = PM_DTLB_MISS,
0313         },
0314         [ C(OP_WRITE) ] = {
0315             [ C(RESULT_ACCESS) ] = -1,
0316             [ C(RESULT_MISS)   ] = -1,
0317         },
0318         [ C(OP_PREFETCH) ] = {
0319             [ C(RESULT_ACCESS) ] = -1,
0320             [ C(RESULT_MISS)   ] = -1,
0321         },
0322     },
0323     [ C(ITLB) ] = {
0324         [ C(OP_READ) ] = {
0325             [ C(RESULT_ACCESS) ] = 0,
0326             [ C(RESULT_MISS)   ] = PM_ITLB_MISS,
0327         },
0328         [ C(OP_WRITE) ] = {
0329             [ C(RESULT_ACCESS) ] = -1,
0330             [ C(RESULT_MISS)   ] = -1,
0331         },
0332         [ C(OP_PREFETCH) ] = {
0333             [ C(RESULT_ACCESS) ] = -1,
0334             [ C(RESULT_MISS)   ] = -1,
0335         },
0336     },
0337     [ C(BPU) ] = {
0338         [ C(OP_READ) ] = {
0339             [ C(RESULT_ACCESS) ] = PM_BRU_FIN,
0340             [ C(RESULT_MISS)   ] = PM_BR_MPRED_CMPL,
0341         },
0342         [ C(OP_WRITE) ] = {
0343             [ C(RESULT_ACCESS) ] = -1,
0344             [ C(RESULT_MISS)   ] = -1,
0345         },
0346         [ C(OP_PREFETCH) ] = {
0347             [ C(RESULT_ACCESS) ] = -1,
0348             [ C(RESULT_MISS)   ] = -1,
0349         },
0350     },
0351     [ C(NODE) ] = {
0352         [ C(OP_READ) ] = {
0353             [ C(RESULT_ACCESS) ] = -1,
0354             [ C(RESULT_MISS)   ] = -1,
0355         },
0356         [ C(OP_WRITE) ] = {
0357             [ C(RESULT_ACCESS) ] = -1,
0358             [ C(RESULT_MISS)   ] = -1,
0359         },
0360         [ C(OP_PREFETCH) ] = {
0361             [ C(RESULT_ACCESS) ] = -1,
0362             [ C(RESULT_MISS)   ] = -1,
0363         },
0364     },
0365 };
0366 
0367 #undef C
0368 
0369 static struct power_pmu power8_pmu = {
0370     .name           = "POWER8",
0371     .n_counter      = MAX_PMU_COUNTERS,
0372     .max_alternatives   = MAX_ALT + 1,
0373     .add_fields     = ISA207_ADD_FIELDS,
0374     .test_adder     = ISA207_TEST_ADDER,
0375     .compute_mmcr       = isa207_compute_mmcr,
0376     .config_bhrb        = power8_config_bhrb,
0377     .bhrb_filter_map    = power8_bhrb_filter_map,
0378     .get_constraint     = isa207_get_constraint,
0379     .get_alternatives   = power8_get_alternatives,
0380     .get_mem_data_src   = isa207_get_mem_data_src,
0381     .get_mem_weight     = isa207_get_mem_weight,
0382     .disable_pmc        = isa207_disable_pmc,
0383     .flags          = PPMU_HAS_SIER | PPMU_ARCH_207S,
0384     .n_generic      = ARRAY_SIZE(power8_generic_events),
0385     .generic_events     = power8_generic_events,
0386     .cache_events       = &power8_cache_events,
0387     .attr_groups        = power8_pmu_attr_groups,
0388     .bhrb_nr        = 32,
0389 };
0390 
0391 int __init init_power8_pmu(void)
0392 {
0393     int rc;
0394     unsigned int pvr = mfspr(SPRN_PVR);
0395 
0396     if (PVR_VER(pvr) != PVR_POWER8E && PVR_VER(pvr) != PVR_POWER8NVL &&
0397         PVR_VER(pvr) != PVR_POWER8)
0398         return -ENODEV;
0399 
0400     rc = register_power_pmu(&power8_pmu);
0401     if (rc)
0402         return rc;
0403 
0404     /* Tell userspace that EBB is supported */
0405     cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
0406 
0407     if (cpu_has_feature(CPU_FTR_PMAO_BUG))
0408         pr_info("PMAO restore workaround active.\n");
0409 
0410     return 0;
0411 }