Lines Matching +full:counter +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0
3 * ARMv6 Performance counter handling code.
7 * ARMv6 has 2 configurable performance counters and a single cycle counter.
16 * the event bus. The procedure for disabling a configurable counter is:
17 * - change the counter to count the ETMEXTOUT[0] signal (0x20). This
18 * effectively stops the counter from counting.
19 * - disable the counter's interrupt generation (each counter has it's
21 * Once stopped, the counter value can be written as 0 to reset.
23 * To enable a counter:
24 * - enable the counter's interrupt generation.
25 * - set the new event type.
27 * Note: the dedicated cycle counter only counts cycles and can't be
29 * cycle counter, we have to just disable the interrupt reporting and start
30 * ignoring that counter. When re-enabling, we have to reset the value and
44 ARMV6_PERFCTR_ICACHE_MISS = 0x0,
45 ARMV6_PERFCTR_IBUF_STALL = 0x1,
46 ARMV6_PERFCTR_DDEP_STALL = 0x2,
47 ARMV6_PERFCTR_ITLB_MISS = 0x3,
48 ARMV6_PERFCTR_DTLB_MISS = 0x4,
49 ARMV6_PERFCTR_BR_EXEC = 0x5,
50 ARMV6_PERFCTR_BR_MISPREDICT = 0x6,
51 ARMV6_PERFCTR_INSTR_EXEC = 0x7,
52 ARMV6_PERFCTR_DCACHE_HIT = 0x9,
53 ARMV6_PERFCTR_DCACHE_ACCESS = 0xA,
54 ARMV6_PERFCTR_DCACHE_MISS = 0xB,
55 ARMV6_PERFCTR_DCACHE_WBACK = 0xC,
56 ARMV6_PERFCTR_SW_PC_CHANGE = 0xD,
57 ARMV6_PERFCTR_MAIN_TLB_MISS = 0xF,
58 ARMV6_PERFCTR_EXPL_D_ACCESS = 0x10,
59 ARMV6_PERFCTR_LSU_FULL_STALL = 0x11,
60 ARMV6_PERFCTR_WBUF_DRAINED = 0x12,
61 ARMV6_PERFCTR_CPU_CYCLES = 0xFF,
62 ARMV6_PERFCTR_NOP = 0x20,
66 ARMV6_CYCLE_COUNTER = 0,
107 * can use a raw counter.
120 asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r"(val)); in armv6_pmcr_read()
127 asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r"(val)); in armv6_pmcr_write()
130 #define ARMV6_PMCR_ENABLE (1 << 0)
141 #define ARMV6_PMCR_EVT_COUNT0_MASK (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
143 #define ARMV6_PMCR_EVT_COUNT1_MASK (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
157 enum armv6_counters counter) in armv6_pmcr_counter_has_overflowed() argument
159 int ret = 0; in armv6_pmcr_counter_has_overflowed()
161 if (ARMV6_CYCLE_COUNTER == counter) in armv6_pmcr_counter_has_overflowed()
163 else if (ARMV6_COUNTER0 == counter) in armv6_pmcr_counter_has_overflowed()
165 else if (ARMV6_COUNTER1 == counter) in armv6_pmcr_counter_has_overflowed()
168 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6_pmcr_counter_has_overflowed()
175 struct hw_perf_event *hwc = &event->hw; in armv6pmu_read_counter()
176 int counter = hwc->idx; in armv6pmu_read_counter() local
177 unsigned long value = 0; in armv6pmu_read_counter()
179 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_read_counter()
180 asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r"(value)); in armv6pmu_read_counter()
181 else if (ARMV6_COUNTER0 == counter) in armv6pmu_read_counter()
182 asm volatile("mrc p15, 0, %0, c15, c12, 2" : "=r"(value)); in armv6pmu_read_counter()
183 else if (ARMV6_COUNTER1 == counter) in armv6pmu_read_counter()
184 asm volatile("mrc p15, 0, %0, c15, c12, 3" : "=r"(value)); in armv6pmu_read_counter()
186 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_read_counter()
193 struct hw_perf_event *hwc = &event->hw; in armv6pmu_write_counter()
194 int counter = hwc->idx; in armv6pmu_write_counter() local
196 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_write_counter()
197 asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r"(value)); in armv6pmu_write_counter()
198 else if (ARMV6_COUNTER0 == counter) in armv6pmu_write_counter()
199 asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r"(value)); in armv6pmu_write_counter()
200 else if (ARMV6_COUNTER1 == counter) in armv6pmu_write_counter()
201 asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r"(value)); in armv6pmu_write_counter()
203 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_write_counter()
209 struct hw_perf_event *hwc = &event->hw; in armv6pmu_enable_event()
210 int idx = hwc->idx; in armv6pmu_enable_event()
213 mask = 0; in armv6pmu_enable_event()
217 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | in armv6pmu_enable_event()
221 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | in armv6pmu_enable_event()
224 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_enable_event()
229 * Mask out the current event and set the counter to count the event in armv6pmu_enable_event()
243 struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_handle_irq()
259 for (idx = 0; idx < cpu_pmu->num_events; ++idx) { in armv6pmu_handle_irq()
260 struct perf_event *event = cpuc->events[idx]; in armv6pmu_handle_irq()
269 * each counter has overflowed before we process it. in armv6pmu_handle_irq()
274 hwc = &event->hw; in armv6pmu_handle_irq()
276 perf_sample_data_init(&data, 0, hwc->last_period); in armv6pmu_handle_irq()
281 cpu_pmu->disable(event); in armv6pmu_handle_irq()
318 struct hw_perf_event *hwc = &event->hw; in armv6pmu_get_event_idx()
319 /* Always place a cycle counter into the cycle counter. */ in armv6pmu_get_event_idx()
320 if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) { in armv6pmu_get_event_idx()
321 if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) in armv6pmu_get_event_idx()
322 return -EAGAIN; in armv6pmu_get_event_idx()
327 * For anything other than a cycle counter, try and use in armv6pmu_get_event_idx()
330 if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) in armv6pmu_get_event_idx()
333 if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) in armv6pmu_get_event_idx()
337 return -EAGAIN; in armv6pmu_get_event_idx()
344 clear_bit(event->hw.idx, cpuc->used_mask); in armv6pmu_clear_event_idx()
350 struct hw_perf_event *hwc = &event->hw; in armv6pmu_disable_event()
351 int idx = hwc->idx; in armv6pmu_disable_event()
355 evt = 0; in armv6pmu_disable_event()
363 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_disable_event()
368 * Mask out the current event and set the counter to count the number in armv6pmu_disable_event()
381 &armv6_perf_cache_map, 0xFF); in armv6_map_event()
386 cpu_pmu->handle_irq = armv6pmu_handle_irq; in armv6pmu_init()
387 cpu_pmu->enable = armv6pmu_enable_event; in armv6pmu_init()
388 cpu_pmu->disable = armv6pmu_disable_event; in armv6pmu_init()
389 cpu_pmu->read_counter = armv6pmu_read_counter; in armv6pmu_init()
390 cpu_pmu->write_counter = armv6pmu_write_counter; in armv6pmu_init()
391 cpu_pmu->get_event_idx = armv6pmu_get_event_idx; in armv6pmu_init()
392 cpu_pmu->clear_event_idx = armv6pmu_clear_event_idx; in armv6pmu_init()
393 cpu_pmu->start = armv6pmu_start; in armv6pmu_init()
394 cpu_pmu->stop = armv6pmu_stop; in armv6pmu_init()
395 cpu_pmu->map_event = armv6_map_event; in armv6pmu_init()
396 cpu_pmu->num_events = 3; in armv6pmu_init()
402 cpu_pmu->name = "armv6_1136"; in armv6_1136_pmu_init()
403 return 0; in armv6_1136_pmu_init()
409 cpu_pmu->name = "armv6_1156"; in armv6_1156_pmu_init()
410 return 0; in armv6_1156_pmu_init()
416 cpu_pmu->name = "armv6_1176"; in armv6_1176_pmu_init()
417 return 0; in armv6_1176_pmu_init()
421 {.compatible = "arm,arm1176-pmu", .data = armv6_1176_pmu_init},
422 {.compatible = "arm,arm1136-pmu", .data = armv6_1136_pmu_init},
441 .name = "armv6-pmu",