1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/perf_event.h> 3 #include <linux/types.h> 4 5 #include <asm/cpu_device_id.h> 6 7 #include "../perf_event.h" 8 9 /* 10 * Not sure about some of these 11 */ 12 static const u64 p6_perfmon_event_map[] = 13 { 14 [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, /* CPU_CLK_UNHALTED */ 15 [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, /* INST_RETIRED */ 16 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, /* L2_RQSTS:M:E:S:I */ 17 [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, /* L2_RQSTS:I */ 18 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, /* BR_INST_RETIRED */ 19 [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, /* BR_MISS_PRED_RETIRED */ 20 [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, /* BUS_DRDY_CLOCKS */ 21 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2, /* RESOURCE_STALLS */ 22 23 }; 24 25 static const u64 __initconst p6_hw_cache_event_ids 26 [PERF_COUNT_HW_CACHE_MAX] 27 [PERF_COUNT_HW_CACHE_OP_MAX] 28 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 29 { 30 [ C(L1D) ] = { 31 [ C(OP_READ) ] = { 32 [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */ 33 [ C(RESULT_MISS) ] = 0x0045, /* DCU_LINES_IN */ 34 }, 35 [ C(OP_WRITE) ] = { 36 [ C(RESULT_ACCESS) ] = 0, 37 [ C(RESULT_MISS) ] = 0x0f29, /* L2_LD:M:E:S:I */ 38 }, 39 [ C(OP_PREFETCH) ] = { 40 [ C(RESULT_ACCESS) ] = 0, 41 [ C(RESULT_MISS) ] = 0, 42 }, 43 }, 44 [ C(L1I ) ] = { 45 [ C(OP_READ) ] = { 46 [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */ 47 [ C(RESULT_MISS) ] = 0x0f28, /* L2_IFETCH:M:E:S:I */ 48 }, 49 [ C(OP_WRITE) ] = { 50 [ C(RESULT_ACCESS) ] = -1, 51 [ C(RESULT_MISS) ] = -1, 52 }, 53 [ C(OP_PREFETCH) ] = { 54 [ C(RESULT_ACCESS) ] = 0, 55 [ C(RESULT_MISS) ] = 0, 56 }, 57 }, 58 [ C(LL ) ] = { 59 [ C(OP_READ) ] = { 60 [ C(RESULT_ACCESS) ] = 0, 61 [ C(RESULT_MISS) ] = 0, 62 }, 63 [ C(OP_WRITE) ] = { 64 [ C(RESULT_ACCESS) ] = 0, 65 [ C(RESULT_MISS) ] = 0x0025, /* L2_M_LINES_INM */ 66 }, 67 [ C(OP_PREFETCH) ] = { 68 [ C(RESULT_ACCESS) ] = 0, 69 [ C(RESULT_MISS) ] = 0, 70 }, 71 }, 72 [ C(DTLB) ] = { 73 [ C(OP_READ) ] = { 74 [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */ 75 [ C(RESULT_MISS) ] = 0, 76 }, 77 [ C(OP_WRITE) ] = { 78 [ C(RESULT_ACCESS) ] = 0, 79 [ C(RESULT_MISS) ] = 0, 80 }, 81 [ C(OP_PREFETCH) ] = { 82 [ C(RESULT_ACCESS) ] = 0, 83 [ C(RESULT_MISS) ] = 0, 84 }, 85 }, 86 [ C(ITLB) ] = { 87 [ C(OP_READ) ] = { 88 [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */ 89 [ C(RESULT_MISS) ] = 0x0085, /* ITLB_MISS */ 90 }, 91 [ C(OP_WRITE) ] = { 92 [ C(RESULT_ACCESS) ] = -1, 93 [ C(RESULT_MISS) ] = -1, 94 }, 95 [ C(OP_PREFETCH) ] = { 96 [ C(RESULT_ACCESS) ] = -1, 97 [ C(RESULT_MISS) ] = -1, 98 }, 99 }, 100 [ C(BPU ) ] = { 101 [ C(OP_READ) ] = { 102 [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED */ 103 [ C(RESULT_MISS) ] = 0x00c5, /* BR_MISS_PRED_RETIRED */ 104 }, 105 [ C(OP_WRITE) ] = { 106 [ C(RESULT_ACCESS) ] = -1, 107 [ C(RESULT_MISS) ] = -1, 108 }, 109 [ C(OP_PREFETCH) ] = { 110 [ C(RESULT_ACCESS) ] = -1, 111 [ C(RESULT_MISS) ] = -1, 112 }, 113 }, 114 }; 115 116 static u64 p6_pmu_event_map(int hw_event) 117 { 118 return p6_perfmon_event_map[hw_event]; 119 } 120 121 /* 122 * Event setting that is specified not to count anything. 123 * We use this to effectively disable a counter. 124 * 125 * L2_RQSTS with 0 MESI unit mask. 126 */ 127 #define P6_NOP_EVENT 0x0000002EULL 128 129 static struct event_constraint p6_event_constraints[] = 130 { 131 INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ 132 INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ 133 INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ 134 INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ 135 INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ 136 INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ 137 EVENT_CONSTRAINT_END 138 }; 139 140 static void p6_pmu_disable_all(void) 141 { 142 u64 val; 143 144 /* p6 only has one enable register */ 145 rdmsrl(MSR_P6_EVNTSEL0, val); 146 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; 147 wrmsrl(MSR_P6_EVNTSEL0, val); 148 } 149 150 static void p6_pmu_enable_all(int added) 151 { 152 unsigned long val; 153 154 /* p6 only has one enable register */ 155 rdmsrl(MSR_P6_EVNTSEL0, val); 156 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 157 wrmsrl(MSR_P6_EVNTSEL0, val); 158 } 159 160 static inline void 161 p6_pmu_disable_event(struct perf_event *event) 162 { 163 struct hw_perf_event *hwc = &event->hw; 164 u64 val = P6_NOP_EVENT; 165 166 (void)wrmsrl_safe(hwc->config_base, val); 167 } 168 169 static void p6_pmu_enable_event(struct perf_event *event) 170 { 171 struct hw_perf_event *hwc = &event->hw; 172 u64 val; 173 174 val = hwc->config; 175 176 /* 177 * p6 only has a global event enable, set on PerfEvtSel0 178 * We "disable" events by programming P6_NOP_EVENT 179 * and we rely on p6_pmu_enable_all() being called 180 * to actually enable the events. 181 */ 182 183 (void)wrmsrl_safe(hwc->config_base, val); 184 } 185 186 PMU_FORMAT_ATTR(event, "config:0-7" ); 187 PMU_FORMAT_ATTR(umask, "config:8-15" ); 188 PMU_FORMAT_ATTR(edge, "config:18" ); 189 PMU_FORMAT_ATTR(pc, "config:19" ); 190 PMU_FORMAT_ATTR(inv, "config:23" ); 191 PMU_FORMAT_ATTR(cmask, "config:24-31" ); 192 193 static struct attribute *intel_p6_formats_attr[] = { 194 &format_attr_event.attr, 195 &format_attr_umask.attr, 196 &format_attr_edge.attr, 197 &format_attr_pc.attr, 198 &format_attr_inv.attr, 199 &format_attr_cmask.attr, 200 NULL, 201 }; 202 203 static __initconst const struct x86_pmu p6_pmu = { 204 .name = "p6", 205 .handle_irq = x86_pmu_handle_irq, 206 .disable_all = p6_pmu_disable_all, 207 .enable_all = p6_pmu_enable_all, 208 .enable = p6_pmu_enable_event, 209 .disable = p6_pmu_disable_event, 210 .hw_config = x86_pmu_hw_config, 211 .schedule_events = x86_schedule_events, 212 .eventsel = MSR_P6_EVNTSEL0, 213 .perfctr = MSR_P6_PERFCTR0, 214 .event_map = p6_pmu_event_map, 215 .max_events = ARRAY_SIZE(p6_perfmon_event_map), 216 .apic = 1, 217 .max_period = (1ULL << 31) - 1, 218 .version = 0, 219 .cntr_mask64 = 0x3, 220 /* 221 * Events have 40 bits implemented. However they are designed such 222 * that bits [32-39] are sign extensions of bit 31. As such the 223 * effective width of a event for P6-like PMU is 32 bits only. 224 * 225 * See IA-32 Intel Architecture Software developer manual Vol 3B 226 */ 227 .cntval_bits = 32, 228 .cntval_mask = (1ULL << 32) - 1, 229 .get_event_constraints = x86_get_event_constraints, 230 .event_constraints = p6_event_constraints, 231 232 .format_attrs = intel_p6_formats_attr, 233 .events_sysfs_show = intel_event_sysfs_show, 234 235 }; 236 237 static __init void p6_pmu_rdpmc_quirk(void) 238 { 239 if (boot_cpu_data.x86_stepping < 9) { 240 /* 241 * PPro erratum 26; fixed in stepping 9 and above. 242 */ 243 pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n"); 244 x86_pmu.attr_rdpmc_broken = 1; 245 x86_pmu.attr_rdpmc = 0; 246 } 247 } 248 249 __init int p6_pmu_init(void) 250 { 251 x86_pmu = p6_pmu; 252 253 if (boot_cpu_data.x86_vfm == INTEL_PENTIUM_PRO) 254 x86_add_quirk(p6_pmu_rdpmc_quirk); 255 256 memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, 257 sizeof(hw_cache_event_ids)); 258 259 return 0; 260 } 261