1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // Copyright 2019 Madhavan Srinivasan, IBM Corporation. 4 5 #define pr_fmt(fmt) "generic-compat-pmu: " fmt 6 7 #include "isa207-common.h" 8 9 /* 10 * Raw event encoding: 11 * 12 * 60 56 52 48 44 40 36 32 13 * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | 14 * 15 * 28 24 20 16 12 8 4 0 16 * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | 17 * [ pmc ] [unit ] [ ] m [ pmcxsel ] 18 * | | 19 * | *- mark 20 * | 21 * | 22 * *- combine 23 * 24 * Below uses IBM bit numbering. 25 * 26 * MMCR1[x:y] = unit (PMCxUNIT) 27 * MMCR1[24] = pmc1combine[0] 28 * MMCR1[25] = pmc1combine[1] 29 * MMCR1[26] = pmc2combine[0] 30 * MMCR1[27] = pmc2combine[1] 31 * MMCR1[28] = pmc3combine[0] 32 * MMCR1[29] = pmc3combine[1] 33 * MMCR1[30] = pmc4combine[0] 34 * MMCR1[31] = pmc4combine[1] 35 * 36 */ 37 38 /* 39 * Some power9 event codes. 40 */ 41 #define EVENT(_name, _code) _name = _code, 42 43 enum { 44 EVENT(PM_CYC, 0x0001e) 45 EVENT(PM_INST_CMPL, 0x00002) 46 }; 47 48 #undef EVENT 49 50 GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); 51 GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL); 52 53 static struct attribute *generic_compat_events_attr[] = { 54 GENERIC_EVENT_PTR(PM_CYC), 55 GENERIC_EVENT_PTR(PM_INST_CMPL), 56 NULL 57 }; 58 59 static struct attribute_group generic_compat_pmu_events_group = { 60 .name = "events", 61 .attrs = generic_compat_events_attr, 62 }; 63 64 PMU_FORMAT_ATTR(event, "config:0-19"); 65 PMU_FORMAT_ATTR(pmcxsel, "config:0-7"); 66 PMU_FORMAT_ATTR(mark, "config:8"); 67 PMU_FORMAT_ATTR(combine, "config:10-11"); 68 PMU_FORMAT_ATTR(unit, "config:12-15"); 69 PMU_FORMAT_ATTR(pmc, "config:16-19"); 70 71 static struct attribute *generic_compat_pmu_format_attr[] = { 72 &format_attr_event.attr, 73 &format_attr_pmcxsel.attr, 74 &format_attr_mark.attr, 75 &format_attr_combine.attr, 76 &format_attr_unit.attr, 77 &format_attr_pmc.attr, 78 NULL, 79 }; 80 81 static struct attribute_group generic_compat_pmu_format_group = { 82 .name = "format", 83 .attrs = generic_compat_pmu_format_attr, 84 }; 85 86 static const struct attribute_group *generic_compat_pmu_attr_groups[] = { 87 &generic_compat_pmu_format_group, 88 &generic_compat_pmu_events_group, 89 NULL, 90 }; 91 92 static int compat_generic_events[] = { 93 [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC, 94 [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, 95 }; 96 97 #define C(x) PERF_COUNT_HW_CACHE_##x 98 99 /* 100 * Table of generalized cache-related events. 101 * 0 means not supported, -1 means nonsensical, other values 102 * are event codes. 103 */ 104 static int generic_compat_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { 105 [ C(L1D) ] = { 106 [ C(OP_READ) ] = { 107 [ C(RESULT_ACCESS) ] = 0, 108 [ C(RESULT_MISS) ] = 0, 109 }, 110 [ C(OP_WRITE) ] = { 111 [ C(RESULT_ACCESS) ] = 0, 112 [ C(RESULT_MISS) ] = 0, 113 }, 114 [ C(OP_PREFETCH) ] = { 115 [ C(RESULT_ACCESS) ] = 0, 116 [ C(RESULT_MISS) ] = 0, 117 }, 118 }, 119 [ C(L1I) ] = { 120 [ C(OP_READ) ] = { 121 [ C(RESULT_ACCESS) ] = 0, 122 [ C(RESULT_MISS) ] = 0, 123 }, 124 [ C(OP_WRITE) ] = { 125 [ C(RESULT_ACCESS) ] = 0, 126 [ C(RESULT_MISS) ] = -1, 127 }, 128 [ C(OP_PREFETCH) ] = { 129 [ C(RESULT_ACCESS) ] = 0, 130 [ C(RESULT_MISS) ] = 0, 131 }, 132 }, 133 [ C(LL) ] = { 134 [ C(OP_READ) ] = { 135 [ C(RESULT_ACCESS) ] = 0, 136 [ C(RESULT_MISS) ] = 0, 137 }, 138 [ C(OP_WRITE) ] = { 139 [ C(RESULT_ACCESS) ] = 0, 140 [ C(RESULT_MISS) ] = 0, 141 }, 142 [ C(OP_PREFETCH) ] = { 143 [ C(RESULT_ACCESS) ] = 0, 144 [ C(RESULT_MISS) ] = 0, 145 }, 146 }, 147 [ C(DTLB) ] = { 148 [ C(OP_READ) ] = { 149 [ C(RESULT_ACCESS) ] = 0, 150 [ C(RESULT_MISS) ] = 0, 151 }, 152 [ C(OP_WRITE) ] = { 153 [ C(RESULT_ACCESS) ] = -1, 154 [ C(RESULT_MISS) ] = -1, 155 }, 156 [ C(OP_PREFETCH) ] = { 157 [ C(RESULT_ACCESS) ] = -1, 158 [ C(RESULT_MISS) ] = -1, 159 }, 160 }, 161 [ C(ITLB) ] = { 162 [ C(OP_READ) ] = { 163 [ C(RESULT_ACCESS) ] = 0, 164 [ C(RESULT_MISS) ] = 0, 165 }, 166 [ C(OP_WRITE) ] = { 167 [ C(RESULT_ACCESS) ] = -1, 168 [ C(RESULT_MISS) ] = -1, 169 }, 170 [ C(OP_PREFETCH) ] = { 171 [ C(RESULT_ACCESS) ] = -1, 172 [ C(RESULT_MISS) ] = -1, 173 }, 174 }, 175 [ C(BPU) ] = { 176 [ C(OP_READ) ] = { 177 [ C(RESULT_ACCESS) ] = 0, 178 [ C(RESULT_MISS) ] = 0, 179 }, 180 [ C(OP_WRITE) ] = { 181 [ C(RESULT_ACCESS) ] = -1, 182 [ C(RESULT_MISS) ] = -1, 183 }, 184 [ C(OP_PREFETCH) ] = { 185 [ C(RESULT_ACCESS) ] = -1, 186 [ C(RESULT_MISS) ] = -1, 187 }, 188 }, 189 [ C(NODE) ] = { 190 [ C(OP_READ) ] = { 191 [ C(RESULT_ACCESS) ] = -1, 192 [ C(RESULT_MISS) ] = -1, 193 }, 194 [ C(OP_WRITE) ] = { 195 [ C(RESULT_ACCESS) ] = -1, 196 [ C(RESULT_MISS) ] = -1, 197 }, 198 [ C(OP_PREFETCH) ] = { 199 [ C(RESULT_ACCESS) ] = -1, 200 [ C(RESULT_MISS) ] = -1, 201 }, 202 }, 203 }; 204 205 #undef C 206 207 static struct power_pmu generic_compat_pmu = { 208 .name = "GENERIC_COMPAT", 209 .n_counter = MAX_PMU_COUNTERS, 210 .add_fields = ISA207_ADD_FIELDS, 211 .test_adder = ISA207_TEST_ADDER, 212 .compute_mmcr = isa207_compute_mmcr, 213 .get_constraint = isa207_get_constraint, 214 .disable_pmc = isa207_disable_pmc, 215 .flags = PPMU_HAS_SIER | PPMU_ARCH_207S, 216 .n_generic = ARRAY_SIZE(compat_generic_events), 217 .generic_events = compat_generic_events, 218 .cache_events = &generic_compat_cache_events, 219 .attr_groups = generic_compat_pmu_attr_groups, 220 }; 221 222 int init_generic_compat_pmu(void) 223 { 224 int rc = 0; 225 226 rc = register_power_pmu(&generic_compat_pmu); 227 if (rc) 228 return rc; 229 230 /* Tell userspace that EBB is supported */ 231 cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB; 232 233 return 0; 234 } 235