0001
0002 #include <linux/perf_event.h>
0003 #include <linux/types.h>
0004
0005 #include "../perf_event.h"
0006
0007
0008
0009
0010 static const u64 p6_perfmon_event_map[] =
0011 {
0012 [PERF_COUNT_HW_CPU_CYCLES] = 0x0079,
0013 [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
0014 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e,
0015 [PERF_COUNT_HW_CACHE_MISSES] = 0x012e,
0016 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4,
0017 [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5,
0018 [PERF_COUNT_HW_BUS_CYCLES] = 0x0062,
0019 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,
0020
0021 };
0022
0023 static const u64 __initconst p6_hw_cache_event_ids
0024 [PERF_COUNT_HW_CACHE_MAX]
0025 [PERF_COUNT_HW_CACHE_OP_MAX]
0026 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
0027 {
0028 [ C(L1D) ] = {
0029 [ C(OP_READ) ] = {
0030 [ C(RESULT_ACCESS) ] = 0x0043,
0031 [ C(RESULT_MISS) ] = 0x0045,
0032 },
0033 [ C(OP_WRITE) ] = {
0034 [ C(RESULT_ACCESS) ] = 0,
0035 [ C(RESULT_MISS) ] = 0x0f29,
0036 },
0037 [ C(OP_PREFETCH) ] = {
0038 [ C(RESULT_ACCESS) ] = 0,
0039 [ C(RESULT_MISS) ] = 0,
0040 },
0041 },
0042 [ C(L1I ) ] = {
0043 [ C(OP_READ) ] = {
0044 [ C(RESULT_ACCESS) ] = 0x0080,
0045 [ C(RESULT_MISS) ] = 0x0f28,
0046 },
0047 [ C(OP_WRITE) ] = {
0048 [ C(RESULT_ACCESS) ] = -1,
0049 [ C(RESULT_MISS) ] = -1,
0050 },
0051 [ C(OP_PREFETCH) ] = {
0052 [ C(RESULT_ACCESS) ] = 0,
0053 [ C(RESULT_MISS) ] = 0,
0054 },
0055 },
0056 [ C(LL ) ] = {
0057 [ C(OP_READ) ] = {
0058 [ C(RESULT_ACCESS) ] = 0,
0059 [ C(RESULT_MISS) ] = 0,
0060 },
0061 [ C(OP_WRITE) ] = {
0062 [ C(RESULT_ACCESS) ] = 0,
0063 [ C(RESULT_MISS) ] = 0x0025,
0064 },
0065 [ C(OP_PREFETCH) ] = {
0066 [ C(RESULT_ACCESS) ] = 0,
0067 [ C(RESULT_MISS) ] = 0,
0068 },
0069 },
0070 [ C(DTLB) ] = {
0071 [ C(OP_READ) ] = {
0072 [ C(RESULT_ACCESS) ] = 0x0043,
0073 [ C(RESULT_MISS) ] = 0,
0074 },
0075 [ C(OP_WRITE) ] = {
0076 [ C(RESULT_ACCESS) ] = 0,
0077 [ C(RESULT_MISS) ] = 0,
0078 },
0079 [ C(OP_PREFETCH) ] = {
0080 [ C(RESULT_ACCESS) ] = 0,
0081 [ C(RESULT_MISS) ] = 0,
0082 },
0083 },
0084 [ C(ITLB) ] = {
0085 [ C(OP_READ) ] = {
0086 [ C(RESULT_ACCESS) ] = 0x0080,
0087 [ C(RESULT_MISS) ] = 0x0085,
0088 },
0089 [ C(OP_WRITE) ] = {
0090 [ C(RESULT_ACCESS) ] = -1,
0091 [ C(RESULT_MISS) ] = -1,
0092 },
0093 [ C(OP_PREFETCH) ] = {
0094 [ C(RESULT_ACCESS) ] = -1,
0095 [ C(RESULT_MISS) ] = -1,
0096 },
0097 },
0098 [ C(BPU ) ] = {
0099 [ C(OP_READ) ] = {
0100 [ C(RESULT_ACCESS) ] = 0x00c4,
0101 [ C(RESULT_MISS) ] = 0x00c5,
0102 },
0103 [ C(OP_WRITE) ] = {
0104 [ C(RESULT_ACCESS) ] = -1,
0105 [ C(RESULT_MISS) ] = -1,
0106 },
0107 [ C(OP_PREFETCH) ] = {
0108 [ C(RESULT_ACCESS) ] = -1,
0109 [ C(RESULT_MISS) ] = -1,
0110 },
0111 },
0112 };
0113
0114 static u64 p6_pmu_event_map(int hw_event)
0115 {
0116 return p6_perfmon_event_map[hw_event];
0117 }
0118
0119
0120
0121
0122
0123
0124
0125 #define P6_NOP_EVENT 0x0000002EULL
0126
0127 static struct event_constraint p6_event_constraints[] =
0128 {
0129 INTEL_EVENT_CONSTRAINT(0xc1, 0x1),
0130 INTEL_EVENT_CONSTRAINT(0x10, 0x1),
0131 INTEL_EVENT_CONSTRAINT(0x11, 0x2),
0132 INTEL_EVENT_CONSTRAINT(0x12, 0x2),
0133 INTEL_EVENT_CONSTRAINT(0x13, 0x2),
0134 INTEL_EVENT_CONSTRAINT(0x14, 0x1),
0135 EVENT_CONSTRAINT_END
0136 };
0137
0138 static void p6_pmu_disable_all(void)
0139 {
0140 u64 val;
0141
0142
0143 rdmsrl(MSR_P6_EVNTSEL0, val);
0144 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
0145 wrmsrl(MSR_P6_EVNTSEL0, val);
0146 }
0147
0148 static void p6_pmu_enable_all(int added)
0149 {
0150 unsigned long val;
0151
0152
0153 rdmsrl(MSR_P6_EVNTSEL0, val);
0154 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
0155 wrmsrl(MSR_P6_EVNTSEL0, val);
0156 }
0157
0158 static inline void
0159 p6_pmu_disable_event(struct perf_event *event)
0160 {
0161 struct hw_perf_event *hwc = &event->hw;
0162 u64 val = P6_NOP_EVENT;
0163
0164 (void)wrmsrl_safe(hwc->config_base, val);
0165 }
0166
0167 static void p6_pmu_enable_event(struct perf_event *event)
0168 {
0169 struct hw_perf_event *hwc = &event->hw;
0170 u64 val;
0171
0172 val = hwc->config;
0173
0174
0175
0176
0177
0178
0179
0180
0181 (void)wrmsrl_safe(hwc->config_base, val);
0182 }
0183
0184 PMU_FORMAT_ATTR(event, "config:0-7" );
0185 PMU_FORMAT_ATTR(umask, "config:8-15" );
0186 PMU_FORMAT_ATTR(edge, "config:18" );
0187 PMU_FORMAT_ATTR(pc, "config:19" );
0188 PMU_FORMAT_ATTR(inv, "config:23" );
0189 PMU_FORMAT_ATTR(cmask, "config:24-31" );
0190
0191 static struct attribute *intel_p6_formats_attr[] = {
0192 &format_attr_event.attr,
0193 &format_attr_umask.attr,
0194 &format_attr_edge.attr,
0195 &format_attr_pc.attr,
0196 &format_attr_inv.attr,
0197 &format_attr_cmask.attr,
0198 NULL,
0199 };
0200
0201 static __initconst const struct x86_pmu p6_pmu = {
0202 .name = "p6",
0203 .handle_irq = x86_pmu_handle_irq,
0204 .disable_all = p6_pmu_disable_all,
0205 .enable_all = p6_pmu_enable_all,
0206 .enable = p6_pmu_enable_event,
0207 .disable = p6_pmu_disable_event,
0208 .hw_config = x86_pmu_hw_config,
0209 .schedule_events = x86_schedule_events,
0210 .eventsel = MSR_P6_EVNTSEL0,
0211 .perfctr = MSR_P6_PERFCTR0,
0212 .event_map = p6_pmu_event_map,
0213 .max_events = ARRAY_SIZE(p6_perfmon_event_map),
0214 .apic = 1,
0215 .max_period = (1ULL << 31) - 1,
0216 .version = 0,
0217 .num_counters = 2,
0218
0219
0220
0221
0222
0223
0224
0225 .cntval_bits = 32,
0226 .cntval_mask = (1ULL << 32) - 1,
0227 .get_event_constraints = x86_get_event_constraints,
0228 .event_constraints = p6_event_constraints,
0229
0230 .format_attrs = intel_p6_formats_attr,
0231 .events_sysfs_show = intel_event_sysfs_show,
0232
0233 };
0234
0235 static __init void p6_pmu_rdpmc_quirk(void)
0236 {
0237 if (boot_cpu_data.x86_stepping < 9) {
0238
0239
0240
0241 pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
0242 x86_pmu.attr_rdpmc_broken = 1;
0243 x86_pmu.attr_rdpmc = 0;
0244 }
0245 }
0246
0247 __init int p6_pmu_init(void)
0248 {
0249 x86_pmu = p6_pmu;
0250
0251 switch (boot_cpu_data.x86_model) {
0252 case 1:
0253 x86_add_quirk(p6_pmu_rdpmc_quirk);
0254 break;
0255
0256 case 3:
0257 case 5:
0258 case 6:
0259 break;
0260
0261 case 7:
0262 case 8:
0263 case 10:
0264 case 11:
0265 break;
0266
0267 case 9:
0268 case 13:
0269 break;
0270
0271 default:
0272 pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
0273 return -ENODEV;
0274 }
0275
0276 memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
0277 sizeof(hw_cache_event_ids));
0278
0279 return 0;
0280 }