0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/of.h>
0014 #include <linux/perf/arm_pmu.h>
0015 #include <linux/platform_device.h>
0016
0017 #include <asm/apple_m1_pmu.h>
0018 #include <asm/irq_regs.h>
0019 #include <asm/perf_event.h>
0020
0021 #define M1_PMU_NR_COUNTERS 10
0022
0023 #define M1_PMU_CFG_EVENT GENMASK(7, 0)
0024
0025 #define ANY_BUT_0_1 GENMASK(9, 2)
0026 #define ONLY_2_TO_7 GENMASK(7, 2)
0027 #define ONLY_2_4_6 (BIT(2) | BIT(4) | BIT(6))
0028 #define ONLY_5_6_7 (BIT(5) | BIT(6) | BIT(7))
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 enum m1_pmu_events {
0050 M1_PMU_PERFCTR_UNKNOWN_01 = 0x01,
0051 M1_PMU_PERFCTR_CPU_CYCLES = 0x02,
0052 M1_PMU_PERFCTR_INSTRUCTIONS = 0x8c,
0053 M1_PMU_PERFCTR_UNKNOWN_8d = 0x8d,
0054 M1_PMU_PERFCTR_UNKNOWN_8e = 0x8e,
0055 M1_PMU_PERFCTR_UNKNOWN_8f = 0x8f,
0056 M1_PMU_PERFCTR_UNKNOWN_90 = 0x90,
0057 M1_PMU_PERFCTR_UNKNOWN_93 = 0x93,
0058 M1_PMU_PERFCTR_UNKNOWN_94 = 0x94,
0059 M1_PMU_PERFCTR_UNKNOWN_95 = 0x95,
0060 M1_PMU_PERFCTR_UNKNOWN_96 = 0x96,
0061 M1_PMU_PERFCTR_UNKNOWN_97 = 0x97,
0062 M1_PMU_PERFCTR_UNKNOWN_98 = 0x98,
0063 M1_PMU_PERFCTR_UNKNOWN_99 = 0x99,
0064 M1_PMU_PERFCTR_UNKNOWN_9a = 0x9a,
0065 M1_PMU_PERFCTR_UNKNOWN_9b = 0x9b,
0066 M1_PMU_PERFCTR_UNKNOWN_9c = 0x9c,
0067 M1_PMU_PERFCTR_UNKNOWN_9f = 0x9f,
0068 M1_PMU_PERFCTR_UNKNOWN_bf = 0xbf,
0069 M1_PMU_PERFCTR_UNKNOWN_c0 = 0xc0,
0070 M1_PMU_PERFCTR_UNKNOWN_c1 = 0xc1,
0071 M1_PMU_PERFCTR_UNKNOWN_c4 = 0xc4,
0072 M1_PMU_PERFCTR_UNKNOWN_c5 = 0xc5,
0073 M1_PMU_PERFCTR_UNKNOWN_c6 = 0xc6,
0074 M1_PMU_PERFCTR_UNKNOWN_c8 = 0xc8,
0075 M1_PMU_PERFCTR_UNKNOWN_ca = 0xca,
0076 M1_PMU_PERFCTR_UNKNOWN_cb = 0xcb,
0077 M1_PMU_PERFCTR_UNKNOWN_f5 = 0xf5,
0078 M1_PMU_PERFCTR_UNKNOWN_f6 = 0xf6,
0079 M1_PMU_PERFCTR_UNKNOWN_f7 = 0xf7,
0080 M1_PMU_PERFCTR_UNKNOWN_f8 = 0xf8,
0081 M1_PMU_PERFCTR_UNKNOWN_fd = 0xfd,
0082 M1_PMU_PERFCTR_LAST = M1_PMU_CFG_EVENT,
0083
0084
0085
0086
0087
0088 M1_PMU_CFG_COUNT_USER = BIT(8),
0089 M1_PMU_CFG_COUNT_KERNEL = BIT(9),
0090 };
0091
0092
0093
0094
0095
0096
0097
0098 static const u16 m1_pmu_event_affinity[M1_PMU_PERFCTR_LAST + 1] = {
0099 [0 ... M1_PMU_PERFCTR_LAST] = ANY_BUT_0_1,
0100 [M1_PMU_PERFCTR_UNKNOWN_01] = BIT(7),
0101 [M1_PMU_PERFCTR_CPU_CYCLES] = ANY_BUT_0_1 | BIT(0),
0102 [M1_PMU_PERFCTR_INSTRUCTIONS] = BIT(7) | BIT(1),
0103 [M1_PMU_PERFCTR_UNKNOWN_8d] = ONLY_5_6_7,
0104 [M1_PMU_PERFCTR_UNKNOWN_8e] = ONLY_5_6_7,
0105 [M1_PMU_PERFCTR_UNKNOWN_8f] = ONLY_5_6_7,
0106 [M1_PMU_PERFCTR_UNKNOWN_90] = ONLY_5_6_7,
0107 [M1_PMU_PERFCTR_UNKNOWN_93] = ONLY_5_6_7,
0108 [M1_PMU_PERFCTR_UNKNOWN_94] = ONLY_5_6_7,
0109 [M1_PMU_PERFCTR_UNKNOWN_95] = ONLY_5_6_7,
0110 [M1_PMU_PERFCTR_UNKNOWN_96] = ONLY_5_6_7,
0111 [M1_PMU_PERFCTR_UNKNOWN_97] = BIT(7),
0112 [M1_PMU_PERFCTR_UNKNOWN_98] = ONLY_5_6_7,
0113 [M1_PMU_PERFCTR_UNKNOWN_99] = ONLY_5_6_7,
0114 [M1_PMU_PERFCTR_UNKNOWN_9a] = BIT(7),
0115 [M1_PMU_PERFCTR_UNKNOWN_9b] = ONLY_5_6_7,
0116 [M1_PMU_PERFCTR_UNKNOWN_9c] = ONLY_5_6_7,
0117 [M1_PMU_PERFCTR_UNKNOWN_9f] = BIT(7),
0118 [M1_PMU_PERFCTR_UNKNOWN_bf] = ONLY_5_6_7,
0119 [M1_PMU_PERFCTR_UNKNOWN_c0] = ONLY_5_6_7,
0120 [M1_PMU_PERFCTR_UNKNOWN_c1] = ONLY_5_6_7,
0121 [M1_PMU_PERFCTR_UNKNOWN_c4] = ONLY_5_6_7,
0122 [M1_PMU_PERFCTR_UNKNOWN_c5] = ONLY_5_6_7,
0123 [M1_PMU_PERFCTR_UNKNOWN_c6] = ONLY_5_6_7,
0124 [M1_PMU_PERFCTR_UNKNOWN_c8] = ONLY_5_6_7,
0125 [M1_PMU_PERFCTR_UNKNOWN_ca] = ONLY_5_6_7,
0126 [M1_PMU_PERFCTR_UNKNOWN_cb] = ONLY_5_6_7,
0127 [M1_PMU_PERFCTR_UNKNOWN_f5] = ONLY_2_4_6,
0128 [M1_PMU_PERFCTR_UNKNOWN_f6] = ONLY_2_4_6,
0129 [M1_PMU_PERFCTR_UNKNOWN_f7] = ONLY_2_4_6,
0130 [M1_PMU_PERFCTR_UNKNOWN_f8] = ONLY_2_TO_7,
0131 [M1_PMU_PERFCTR_UNKNOWN_fd] = ONLY_2_4_6,
0132 };
0133
0134 static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
0135 PERF_MAP_ALL_UNSUPPORTED,
0136 [PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CPU_CYCLES,
0137 [PERF_COUNT_HW_INSTRUCTIONS] = M1_PMU_PERFCTR_INSTRUCTIONS,
0138
0139 };
0140
0141
0142 static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
0143 struct device_attribute *attr,
0144 char *page)
0145 {
0146 struct perf_pmu_events_attr *pmu_attr;
0147
0148 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
0149
0150 return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
0151 }
0152
0153 #define M1_PMU_EVENT_ATTR(name, config) \
0154 PMU_EVENT_ATTR_ID(name, m1_pmu_events_sysfs_show, config)
0155
0156 static struct attribute *m1_pmu_event_attrs[] = {
0157 M1_PMU_EVENT_ATTR(cycles, M1_PMU_PERFCTR_CPU_CYCLES),
0158 M1_PMU_EVENT_ATTR(instructions, M1_PMU_PERFCTR_INSTRUCTIONS),
0159 NULL,
0160 };
0161
0162 static const struct attribute_group m1_pmu_events_attr_group = {
0163 .name = "events",
0164 .attrs = m1_pmu_event_attrs,
0165 };
0166
0167 PMU_FORMAT_ATTR(event, "config:0-7");
0168
0169 static struct attribute *m1_pmu_format_attrs[] = {
0170 &format_attr_event.attr,
0171 NULL,
0172 };
0173
0174 static const struct attribute_group m1_pmu_format_attr_group = {
0175 .name = "format",
0176 .attrs = m1_pmu_format_attrs,
0177 };
0178
0179
0180 #define PMU_READ_COUNTER(_idx) \
0181 case _idx: return read_sysreg_s(SYS_IMP_APL_PMC## _idx ##_EL1)
0182
0183 #define PMU_WRITE_COUNTER(_val, _idx) \
0184 case _idx: \
0185 write_sysreg_s(_val, SYS_IMP_APL_PMC## _idx ##_EL1); \
0186 return
0187
0188 static u64 m1_pmu_read_hw_counter(unsigned int index)
0189 {
0190 switch (index) {
0191 PMU_READ_COUNTER(0);
0192 PMU_READ_COUNTER(1);
0193 PMU_READ_COUNTER(2);
0194 PMU_READ_COUNTER(3);
0195 PMU_READ_COUNTER(4);
0196 PMU_READ_COUNTER(5);
0197 PMU_READ_COUNTER(6);
0198 PMU_READ_COUNTER(7);
0199 PMU_READ_COUNTER(8);
0200 PMU_READ_COUNTER(9);
0201 }
0202
0203 BUG();
0204 }
0205
0206 static void m1_pmu_write_hw_counter(u64 val, unsigned int index)
0207 {
0208 switch (index) {
0209 PMU_WRITE_COUNTER(val, 0);
0210 PMU_WRITE_COUNTER(val, 1);
0211 PMU_WRITE_COUNTER(val, 2);
0212 PMU_WRITE_COUNTER(val, 3);
0213 PMU_WRITE_COUNTER(val, 4);
0214 PMU_WRITE_COUNTER(val, 5);
0215 PMU_WRITE_COUNTER(val, 6);
0216 PMU_WRITE_COUNTER(val, 7);
0217 PMU_WRITE_COUNTER(val, 8);
0218 PMU_WRITE_COUNTER(val, 9);
0219 }
0220
0221 BUG();
0222 }
0223
0224 #define get_bit_offset(index, mask) (__ffs(mask) + (index))
0225
0226 static void __m1_pmu_enable_counter(unsigned int index, bool en)
0227 {
0228 u64 val, bit;
0229
0230 switch (index) {
0231 case 0 ... 7:
0232 bit = BIT(get_bit_offset(index, PMCR0_CNT_ENABLE_0_7));
0233 break;
0234 case 8 ... 9:
0235 bit = BIT(get_bit_offset(index - 8, PMCR0_CNT_ENABLE_8_9));
0236 break;
0237 default:
0238 BUG();
0239 }
0240
0241 val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
0242
0243 if (en)
0244 val |= bit;
0245 else
0246 val &= ~bit;
0247
0248 write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
0249 }
0250
0251 static void m1_pmu_enable_counter(unsigned int index)
0252 {
0253 __m1_pmu_enable_counter(index, true);
0254 }
0255
0256 static void m1_pmu_disable_counter(unsigned int index)
0257 {
0258 __m1_pmu_enable_counter(index, false);
0259 }
0260
0261 static void __m1_pmu_enable_counter_interrupt(unsigned int index, bool en)
0262 {
0263 u64 val, bit;
0264
0265 switch (index) {
0266 case 0 ... 7:
0267 bit = BIT(get_bit_offset(index, PMCR0_PMI_ENABLE_0_7));
0268 break;
0269 case 8 ... 9:
0270 bit = BIT(get_bit_offset(index - 8, PMCR0_PMI_ENABLE_8_9));
0271 break;
0272 default:
0273 BUG();
0274 }
0275
0276 val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
0277
0278 if (en)
0279 val |= bit;
0280 else
0281 val &= ~bit;
0282
0283 write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
0284 }
0285
0286 static void m1_pmu_enable_counter_interrupt(unsigned int index)
0287 {
0288 __m1_pmu_enable_counter_interrupt(index, true);
0289 }
0290
0291 static void m1_pmu_disable_counter_interrupt(unsigned int index)
0292 {
0293 __m1_pmu_enable_counter_interrupt(index, false);
0294 }
0295
0296 static void m1_pmu_configure_counter(unsigned int index, u8 event,
0297 bool user, bool kernel)
0298 {
0299 u64 val, user_bit, kernel_bit;
0300 int shift;
0301
0302 switch (index) {
0303 case 0 ... 7:
0304 user_bit = BIT(get_bit_offset(index, PMCR1_COUNT_A64_EL0_0_7));
0305 kernel_bit = BIT(get_bit_offset(index, PMCR1_COUNT_A64_EL1_0_7));
0306 break;
0307 case 8 ... 9:
0308 user_bit = BIT(get_bit_offset(index - 8, PMCR1_COUNT_A64_EL0_8_9));
0309 kernel_bit = BIT(get_bit_offset(index - 8, PMCR1_COUNT_A64_EL1_8_9));
0310 break;
0311 default:
0312 BUG();
0313 }
0314
0315 val = read_sysreg_s(SYS_IMP_APL_PMCR1_EL1);
0316
0317 if (user)
0318 val |= user_bit;
0319 else
0320 val &= ~user_bit;
0321
0322 if (kernel)
0323 val |= kernel_bit;
0324 else
0325 val &= ~kernel_bit;
0326
0327 write_sysreg_s(val, SYS_IMP_APL_PMCR1_EL1);
0328
0329
0330
0331
0332
0333
0334
0335 switch (index) {
0336 case 0 ... 1:
0337 break;
0338 case 2 ... 5:
0339 shift = (index - 2) * 8;
0340 val = read_sysreg_s(SYS_IMP_APL_PMESR0_EL1);
0341 val &= ~((u64)0xff << shift);
0342 val |= (u64)event << shift;
0343 write_sysreg_s(val, SYS_IMP_APL_PMESR0_EL1);
0344 break;
0345 case 6 ... 9:
0346 shift = (index - 6) * 8;
0347 val = read_sysreg_s(SYS_IMP_APL_PMESR1_EL1);
0348 val &= ~((u64)0xff << shift);
0349 val |= (u64)event << shift;
0350 write_sysreg_s(val, SYS_IMP_APL_PMESR1_EL1);
0351 break;
0352 }
0353 }
0354
0355
0356 static void m1_pmu_enable_event(struct perf_event *event)
0357 {
0358 bool user, kernel;
0359 u8 evt;
0360
0361 evt = event->hw.config_base & M1_PMU_CFG_EVENT;
0362 user = event->hw.config_base & M1_PMU_CFG_COUNT_USER;
0363 kernel = event->hw.config_base & M1_PMU_CFG_COUNT_KERNEL;
0364
0365 m1_pmu_disable_counter_interrupt(event->hw.idx);
0366 m1_pmu_disable_counter(event->hw.idx);
0367 isb();
0368
0369 m1_pmu_configure_counter(event->hw.idx, evt, user, kernel);
0370 m1_pmu_enable_counter(event->hw.idx);
0371 m1_pmu_enable_counter_interrupt(event->hw.idx);
0372 isb();
0373 }
0374
0375 static void m1_pmu_disable_event(struct perf_event *event)
0376 {
0377 m1_pmu_disable_counter_interrupt(event->hw.idx);
0378 m1_pmu_disable_counter(event->hw.idx);
0379 isb();
0380 }
0381
0382 static irqreturn_t m1_pmu_handle_irq(struct arm_pmu *cpu_pmu)
0383 {
0384 struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
0385 struct pt_regs *regs;
0386 u64 overflow, state;
0387 int idx;
0388
0389 overflow = read_sysreg_s(SYS_IMP_APL_PMSR_EL1);
0390 if (!overflow) {
0391
0392 state = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
0393 state &= ~PMCR0_IACT;
0394 write_sysreg_s(state, SYS_IMP_APL_PMCR0_EL1);
0395 isb();
0396 return IRQ_NONE;
0397 }
0398
0399 cpu_pmu->stop(cpu_pmu);
0400
0401 regs = get_irq_regs();
0402
0403 for (idx = 0; idx < cpu_pmu->num_events; idx++) {
0404 struct perf_event *event = cpuc->events[idx];
0405 struct perf_sample_data data;
0406
0407 if (!event)
0408 continue;
0409
0410 armpmu_event_update(event);
0411 perf_sample_data_init(&data, 0, event->hw.last_period);
0412 if (!armpmu_event_set_period(event))
0413 continue;
0414
0415 if (perf_event_overflow(event, &data, regs))
0416 m1_pmu_disable_event(event);
0417 }
0418
0419 cpu_pmu->start(cpu_pmu);
0420
0421 return IRQ_HANDLED;
0422 }
0423
0424 static u64 m1_pmu_read_counter(struct perf_event *event)
0425 {
0426 return m1_pmu_read_hw_counter(event->hw.idx);
0427 }
0428
0429 static void m1_pmu_write_counter(struct perf_event *event, u64 value)
0430 {
0431 m1_pmu_write_hw_counter(value, event->hw.idx);
0432 isb();
0433 }
0434
0435 static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
0436 struct perf_event *event)
0437 {
0438 unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
0439 unsigned long affinity = m1_pmu_event_affinity[evtype];
0440 int idx;
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 for_each_set_bit(idx, &affinity, M1_PMU_NR_COUNTERS) {
0451 if (!test_and_set_bit(idx, cpuc->used_mask))
0452 return idx;
0453 }
0454
0455 return -EAGAIN;
0456 }
0457
0458 static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
0459 struct perf_event *event)
0460 {
0461 clear_bit(event->hw.idx, cpuc->used_mask);
0462 }
0463
0464 static void __m1_pmu_set_mode(u8 mode)
0465 {
0466 u64 val;
0467
0468 val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
0469 val &= ~(PMCR0_IMODE | PMCR0_IACT);
0470 val |= FIELD_PREP(PMCR0_IMODE, mode);
0471 write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
0472 isb();
0473 }
0474
0475 static void m1_pmu_start(struct arm_pmu *cpu_pmu)
0476 {
0477 __m1_pmu_set_mode(PMCR0_IMODE_FIQ);
0478 }
0479
0480 static void m1_pmu_stop(struct arm_pmu *cpu_pmu)
0481 {
0482 __m1_pmu_set_mode(PMCR0_IMODE_OFF);
0483 }
0484
0485 static int m1_pmu_map_event(struct perf_event *event)
0486 {
0487
0488
0489
0490
0491
0492 event->hw.flags |= ARMPMU_EVT_47BIT;
0493 return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
0494 }
0495
0496 static void m1_pmu_reset(void *info)
0497 {
0498 int i;
0499
0500 __m1_pmu_set_mode(PMCR0_IMODE_OFF);
0501
0502 for (i = 0; i < M1_PMU_NR_COUNTERS; i++) {
0503 m1_pmu_disable_counter(i);
0504 m1_pmu_disable_counter_interrupt(i);
0505 m1_pmu_write_hw_counter(0, i);
0506 }
0507
0508 isb();
0509 }
0510
0511 static int m1_pmu_set_event_filter(struct hw_perf_event *event,
0512 struct perf_event_attr *attr)
0513 {
0514 unsigned long config_base = 0;
0515
0516 if (!attr->exclude_guest)
0517 return -EINVAL;
0518 if (!attr->exclude_kernel)
0519 config_base |= M1_PMU_CFG_COUNT_KERNEL;
0520 if (!attr->exclude_user)
0521 config_base |= M1_PMU_CFG_COUNT_USER;
0522
0523 event->config_base = config_base;
0524
0525 return 0;
0526 }
0527
0528 static int m1_pmu_init(struct arm_pmu *cpu_pmu)
0529 {
0530 cpu_pmu->handle_irq = m1_pmu_handle_irq;
0531 cpu_pmu->enable = m1_pmu_enable_event;
0532 cpu_pmu->disable = m1_pmu_disable_event;
0533 cpu_pmu->read_counter = m1_pmu_read_counter;
0534 cpu_pmu->write_counter = m1_pmu_write_counter;
0535 cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
0536 cpu_pmu->clear_event_idx = m1_pmu_clear_event_idx;
0537 cpu_pmu->start = m1_pmu_start;
0538 cpu_pmu->stop = m1_pmu_stop;
0539 cpu_pmu->map_event = m1_pmu_map_event;
0540 cpu_pmu->reset = m1_pmu_reset;
0541 cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
0542
0543 cpu_pmu->num_events = M1_PMU_NR_COUNTERS;
0544 cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
0545 cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
0546 return 0;
0547 }
0548
0549
0550 static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
0551 {
0552 cpu_pmu->name = "apple_icestorm_pmu";
0553 return m1_pmu_init(cpu_pmu);
0554 }
0555
0556 static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
0557 {
0558 cpu_pmu->name = "apple_firestorm_pmu";
0559 return m1_pmu_init(cpu_pmu);
0560 }
0561
0562 static const struct of_device_id m1_pmu_of_device_ids[] = {
0563 { .compatible = "apple,icestorm-pmu", .data = m1_pmu_ice_init, },
0564 { .compatible = "apple,firestorm-pmu", .data = m1_pmu_fire_init, },
0565 { },
0566 };
0567 MODULE_DEVICE_TABLE(of, m1_pmu_of_device_ids);
0568
0569 static int m1_pmu_device_probe(struct platform_device *pdev)
0570 {
0571 return arm_pmu_device_probe(pdev, m1_pmu_of_device_ids, NULL);
0572 }
0573
0574 static struct platform_driver m1_pmu_driver = {
0575 .driver = {
0576 .name = "apple-m1-cpu-pmu",
0577 .of_match_table = m1_pmu_of_device_ids,
0578 .suppress_bind_attrs = true,
0579 },
0580 .probe = m1_pmu_device_probe,
0581 };
0582
0583 module_platform_driver(m1_pmu_driver);
0584 MODULE_LICENSE("GPL v2");