Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Copyright 2019 Madhavan Srinivasan, IBM Corporation.
0004 
0005 #define pr_fmt(fmt) "generic-compat-pmu: " fmt
0006 
0007 #include "isa207-common.h"
0008 
0009 /*
0010  * Raw event encoding:
0011  *
0012  *        60        56        52        48        44        40        36        32
0013  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
0014  *
0015  *        28        24        20        16        12         8         4         0
0016  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
0017  *                                 [ pmc ]                       [    pmcxsel    ]
0018  */
0019 
0020 /*
0021  * Event codes defined in ISA v3.0B
0022  */
0023 #define EVENT(_name, _code) _name = _code,
0024 
0025 enum {
0026     /* Cycles, alternate code */
0027     EVENT(PM_CYC_ALT,           0x100f0)
0028     /* One or more instructions completed in a cycle */
0029     EVENT(PM_CYC_INST_CMPL,         0x100f2)
0030     /* Floating-point instruction completed */
0031     EVENT(PM_FLOP_CMPL,         0x100f4)
0032     /* Instruction ERAT/L1-TLB miss */
0033     EVENT(PM_L1_ITLB_MISS,          0x100f6)
0034     /* All instructions completed and none available */
0035     EVENT(PM_NO_INST_AVAIL,         0x100f8)
0036     /* A load-type instruction completed (ISA v3.0+) */
0037     EVENT(PM_LD_CMPL,           0x100fc)
0038     /* Instruction completed, alternate code (ISA v3.0+) */
0039     EVENT(PM_INST_CMPL_ALT,         0x100fe)
0040     /* A store-type instruction completed */
0041     EVENT(PM_ST_CMPL,           0x200f0)
0042     /* Instruction Dispatched */
0043     EVENT(PM_INST_DISP,         0x200f2)
0044     /* Run_cycles */
0045     EVENT(PM_RUN_CYC,           0x200f4)
0046     /* Data ERAT/L1-TLB miss/reload */
0047     EVENT(PM_L1_DTLB_RELOAD,        0x200f6)
0048     /* Taken branch completed */
0049     EVENT(PM_BR_TAKEN_CMPL,         0x200fa)
0050     /* Demand iCache Miss */
0051     EVENT(PM_L1_ICACHE_MISS,        0x200fc)
0052     /* L1 Dcache reload from memory */
0053     EVENT(PM_L1_RELOAD_FROM_MEM,        0x200fe)
0054     /* L1 Dcache store miss */
0055     EVENT(PM_ST_MISS_L1,            0x300f0)
0056     /* Alternate code for PM_INST_DISP */
0057     EVENT(PM_INST_DISP_ALT,         0x300f2)
0058     /* Branch direction or target mispredicted */
0059     EVENT(PM_BR_MISPREDICT,         0x300f6)
0060     /* Data TLB miss/reload */
0061     EVENT(PM_DTLB_MISS,         0x300fc)
0062     /* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
0063     EVENT(PM_DATA_FROM_L3MISS,      0x300fe)
0064     /* L1 Dcache load miss */
0065     EVENT(PM_LD_MISS_L1,            0x400f0)
0066     /* Cycle when instruction(s) dispatched */
0067     EVENT(PM_CYC_INST_DISP,         0x400f2)
0068     /* Branch or branch target mispredicted */
0069     EVENT(PM_BR_MPRED_CMPL,         0x400f6)
0070     /* Instructions completed with run latch set */
0071     EVENT(PM_RUN_INST_CMPL,         0x400fa)
0072     /* Instruction TLB miss/reload */
0073     EVENT(PM_ITLB_MISS,         0x400fc)
0074     /* Load data not cached */
0075     EVENT(PM_LD_NOT_CACHED,         0x400fe)
0076     /* Instructions */
0077     EVENT(PM_INST_CMPL,         0x500fa)
0078     /* Cycles */
0079     EVENT(PM_CYC,               0x600f4)
0080 };
0081 
0082 #undef EVENT
0083 
0084 /* Table of alternatives, sorted in increasing order of column 0 */
0085 /* Note that in each row, column 0 must be the smallest */
0086 static const unsigned int generic_event_alternatives[][MAX_ALT] = {
0087     { PM_CYC_ALT,           PM_CYC },
0088     { PM_INST_CMPL_ALT,     PM_INST_CMPL },
0089     { PM_INST_DISP,         PM_INST_DISP_ALT },
0090 };
0091 
0092 static int generic_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0093 {
0094     int num_alt = 0;
0095 
0096     num_alt = isa207_get_alternatives(event, alt,
0097                       ARRAY_SIZE(generic_event_alternatives), flags,
0098                       generic_event_alternatives);
0099 
0100     return num_alt;
0101 }
0102 
0103 GENERIC_EVENT_ATTR(cpu-cycles,          PM_CYC);
0104 GENERIC_EVENT_ATTR(instructions,        PM_INST_CMPL);
0105 GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_NO_INST_AVAIL);
0106 GENERIC_EVENT_ATTR(branch-misses,       PM_BR_MPRED_CMPL);
0107 GENERIC_EVENT_ATTR(cache-misses,        PM_LD_MISS_L1);
0108 
0109 CACHE_EVENT_ATTR(L1-dcache-load-misses,     PM_LD_MISS_L1);
0110 CACHE_EVENT_ATTR(L1-dcache-store-misses,    PM_ST_MISS_L1);
0111 CACHE_EVENT_ATTR(L1-icache-load-misses,     PM_L1_ICACHE_MISS);
0112 CACHE_EVENT_ATTR(LLC-load-misses,       PM_DATA_FROM_L3MISS);
0113 CACHE_EVENT_ATTR(branch-load-misses,        PM_BR_MPRED_CMPL);
0114 CACHE_EVENT_ATTR(dTLB-load-misses,      PM_DTLB_MISS);
0115 CACHE_EVENT_ATTR(iTLB-load-misses,      PM_ITLB_MISS);
0116 
0117 static struct attribute *generic_compat_events_attr[] = {
0118     GENERIC_EVENT_PTR(PM_CYC),
0119     GENERIC_EVENT_PTR(PM_INST_CMPL),
0120     GENERIC_EVENT_PTR(PM_NO_INST_AVAIL),
0121     GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
0122     GENERIC_EVENT_PTR(PM_LD_MISS_L1),
0123     CACHE_EVENT_PTR(PM_LD_MISS_L1),
0124     CACHE_EVENT_PTR(PM_ST_MISS_L1),
0125     CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
0126     CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
0127     CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
0128     CACHE_EVENT_PTR(PM_DTLB_MISS),
0129     CACHE_EVENT_PTR(PM_ITLB_MISS),
0130     NULL
0131 };
0132 
0133 static const struct attribute_group generic_compat_pmu_events_group = {
0134     .name = "events",
0135     .attrs = generic_compat_events_attr,
0136 };
0137 
0138 PMU_FORMAT_ATTR(event,      "config:0-19");
0139 PMU_FORMAT_ATTR(pmcxsel,    "config:0-7");
0140 PMU_FORMAT_ATTR(pmc,        "config:16-19");
0141 
0142 static struct attribute *generic_compat_pmu_format_attr[] = {
0143     &format_attr_event.attr,
0144     &format_attr_pmcxsel.attr,
0145     &format_attr_pmc.attr,
0146     NULL,
0147 };
0148 
0149 static const struct attribute_group generic_compat_pmu_format_group = {
0150     .name = "format",
0151     .attrs = generic_compat_pmu_format_attr,
0152 };
0153 
0154 static struct attribute *generic_compat_pmu_caps_attrs[] = {
0155     NULL
0156 };
0157 
0158 static struct attribute_group generic_compat_pmu_caps_group = {
0159     .name  = "caps",
0160     .attrs = generic_compat_pmu_caps_attrs,
0161 };
0162 
0163 static const struct attribute_group *generic_compat_pmu_attr_groups[] = {
0164     &generic_compat_pmu_format_group,
0165     &generic_compat_pmu_events_group,
0166     &generic_compat_pmu_caps_group,
0167     NULL,
0168 };
0169 
0170 static int compat_generic_events[] = {
0171     [PERF_COUNT_HW_CPU_CYCLES] =            PM_CYC,
0172     [PERF_COUNT_HW_INSTRUCTIONS] =          PM_INST_CMPL,
0173     [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =   PM_NO_INST_AVAIL,
0174     [PERF_COUNT_HW_BRANCH_MISSES] =         PM_BR_MPRED_CMPL,
0175     [PERF_COUNT_HW_CACHE_MISSES] =          PM_LD_MISS_L1,
0176 };
0177 
0178 #define C(x)    PERF_COUNT_HW_CACHE_##x
0179 
0180 /*
0181  * Table of generalized cache-related events.
0182  * 0 means not supported, -1 means nonsensical, other values
0183  * are event codes.
0184  */
0185 static u64 generic_compat_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0186     [ C(L1D) ] = {
0187         [ C(OP_READ) ] = {
0188             [ C(RESULT_ACCESS) ] = 0,
0189             [ C(RESULT_MISS)   ] = PM_LD_MISS_L1,
0190         },
0191         [ C(OP_WRITE) ] = {
0192             [ C(RESULT_ACCESS) ] = 0,
0193             [ C(RESULT_MISS)   ] = PM_ST_MISS_L1,
0194         },
0195         [ C(OP_PREFETCH) ] = {
0196             [ C(RESULT_ACCESS) ] = 0,
0197             [ C(RESULT_MISS)   ] = 0,
0198         },
0199     },
0200     [ C(L1I) ] = {
0201         [ C(OP_READ) ] = {
0202             [ C(RESULT_ACCESS) ] = 0,
0203             [ C(RESULT_MISS)   ] = PM_L1_ICACHE_MISS,
0204         },
0205         [ C(OP_WRITE) ] = {
0206             [ C(RESULT_ACCESS) ] = 0,
0207             [ C(RESULT_MISS)   ] = -1,
0208         },
0209         [ C(OP_PREFETCH) ] = {
0210             [ C(RESULT_ACCESS) ] = 0,
0211             [ C(RESULT_MISS)   ] = 0,
0212         },
0213     },
0214     [ C(LL) ] = {
0215         [ C(OP_READ) ] = {
0216             [ C(RESULT_ACCESS) ] = 0,
0217             [ C(RESULT_MISS)   ] = PM_DATA_FROM_L3MISS,
0218         },
0219         [ C(OP_WRITE) ] = {
0220             [ C(RESULT_ACCESS) ] = 0,
0221             [ C(RESULT_MISS)   ] = 0,
0222         },
0223         [ C(OP_PREFETCH) ] = {
0224             [ C(RESULT_ACCESS) ] = 0,
0225             [ C(RESULT_MISS)   ] = 0,
0226         },
0227     },
0228     [ C(DTLB) ] = {
0229         [ C(OP_READ) ] = {
0230             [ C(RESULT_ACCESS) ] = 0,
0231             [ C(RESULT_MISS)   ] = PM_DTLB_MISS,
0232         },
0233         [ C(OP_WRITE) ] = {
0234             [ C(RESULT_ACCESS) ] = -1,
0235             [ C(RESULT_MISS)   ] = -1,
0236         },
0237         [ C(OP_PREFETCH) ] = {
0238             [ C(RESULT_ACCESS) ] = -1,
0239             [ C(RESULT_MISS)   ] = -1,
0240         },
0241     },
0242     [ C(ITLB) ] = {
0243         [ C(OP_READ) ] = {
0244             [ C(RESULT_ACCESS) ] = 0,
0245             [ C(RESULT_MISS)   ] = PM_ITLB_MISS,
0246         },
0247         [ C(OP_WRITE) ] = {
0248             [ C(RESULT_ACCESS) ] = -1,
0249             [ C(RESULT_MISS)   ] = -1,
0250         },
0251         [ C(OP_PREFETCH) ] = {
0252             [ C(RESULT_ACCESS) ] = -1,
0253             [ C(RESULT_MISS)   ] = -1,
0254         },
0255     },
0256     [ C(BPU) ] = {
0257         [ C(OP_READ) ] = {
0258             [ C(RESULT_ACCESS) ] = 0,
0259             [ C(RESULT_MISS)   ] = PM_BR_MPRED_CMPL,
0260         },
0261         [ C(OP_WRITE) ] = {
0262             [ C(RESULT_ACCESS) ] = -1,
0263             [ C(RESULT_MISS)   ] = -1,
0264         },
0265         [ C(OP_PREFETCH) ] = {
0266             [ C(RESULT_ACCESS) ] = -1,
0267             [ C(RESULT_MISS)   ] = -1,
0268         },
0269     },
0270     [ C(NODE) ] = {
0271         [ C(OP_READ) ] = {
0272             [ C(RESULT_ACCESS) ] = -1,
0273             [ C(RESULT_MISS)   ] = -1,
0274         },
0275         [ C(OP_WRITE) ] = {
0276             [ C(RESULT_ACCESS) ] = -1,
0277             [ C(RESULT_MISS)   ] = -1,
0278         },
0279         [ C(OP_PREFETCH) ] = {
0280             [ C(RESULT_ACCESS) ] = -1,
0281             [ C(RESULT_MISS)   ] = -1,
0282         },
0283     },
0284 };
0285 
0286 #undef C
0287 
0288 /*
0289  * We set MMCR0[CC5-6RUN] so we can use counters 5 and 6 for
0290  * PM_INST_CMPL and PM_CYC.
0291  */
0292 static int generic_compute_mmcr(u64 event[], int n_ev,
0293                 unsigned int hwc[], struct mmcr_regs *mmcr,
0294                 struct perf_event *pevents[], u32 flags)
0295 {
0296     int ret;
0297 
0298     ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags);
0299     if (!ret)
0300         mmcr->mmcr0 |= MMCR0_C56RUN;
0301     return ret;
0302 }
0303 
0304 static struct power_pmu generic_compat_pmu = {
0305     .name           = "ISAv3",
0306     .n_counter      = MAX_PMU_COUNTERS,
0307     .add_fields     = ISA207_ADD_FIELDS,
0308     .test_adder     = ISA207_TEST_ADDER,
0309     .compute_mmcr       = generic_compute_mmcr,
0310     .get_constraint     = isa207_get_constraint,
0311     .get_alternatives   = generic_get_alternatives,
0312     .disable_pmc        = isa207_disable_pmc,
0313     .flags          = PPMU_HAS_SIER | PPMU_ARCH_207S,
0314     .n_generic      = ARRAY_SIZE(compat_generic_events),
0315     .generic_events     = compat_generic_events,
0316     .cache_events       = &generic_compat_cache_events,
0317     .attr_groups        = generic_compat_pmu_attr_groups,
0318 };
0319 
0320 int __init init_generic_compat_pmu(void)
0321 {
0322     int rc = 0;
0323 
0324     /*
0325      * From ISA v2.07 on, PMU features are architected;
0326      * we require >= v3.0 because (a) that has PM_LD_CMPL and
0327      * PM_INST_CMPL_ALT, which v2.07 doesn't have, and
0328      * (b) we don't expect any non-IBM Power ISA
0329      * implementations that conform to v2.07 but not v3.0.
0330      */
0331     if (!cpu_has_feature(CPU_FTR_ARCH_300))
0332         return -ENODEV;
0333 
0334     rc = register_power_pmu(&generic_compat_pmu);
0335     if (rc)
0336         return rc;
0337 
0338     /* Tell userspace that EBB is supported */
0339     cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
0340 
0341     return 0;
0342 }