Lines Matching +full:interrupt +full:- +full:counter
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
20 * own interrupt enable bit).
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
31 * enable the interrupt.
107 * can use a raw counter.
170 * can use a raw counter.
220 enum armv6_counters counter) in armv6_pmcr_counter_has_overflowed() argument
224 if (ARMV6_CYCLE_COUNTER == counter) in armv6_pmcr_counter_has_overflowed()
226 else if (ARMV6_COUNTER0 == counter) in armv6_pmcr_counter_has_overflowed()
228 else if (ARMV6_COUNTER1 == counter) in armv6_pmcr_counter_has_overflowed()
231 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6_pmcr_counter_has_overflowed()
238 struct hw_perf_event *hwc = &event->hw; in armv6pmu_read_counter()
239 int counter = hwc->idx; in armv6pmu_read_counter() local
242 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_read_counter()
244 else if (ARMV6_COUNTER0 == counter) in armv6pmu_read_counter()
246 else if (ARMV6_COUNTER1 == counter) in armv6pmu_read_counter()
249 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_read_counter()
256 struct hw_perf_event *hwc = &event->hw; in armv6pmu_write_counter()
257 int counter = hwc->idx; in armv6pmu_write_counter() local
259 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_write_counter()
261 else if (ARMV6_COUNTER0 == counter) in armv6pmu_write_counter()
263 else if (ARMV6_COUNTER1 == counter) in armv6pmu_write_counter()
266 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_write_counter()
272 struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); in armv6pmu_enable_event()
273 struct hw_perf_event *hwc = &event->hw; in armv6pmu_enable_event()
274 struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_enable_event()
275 int idx = hwc->idx; in armv6pmu_enable_event()
282 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | in armv6pmu_enable_event()
286 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | in armv6pmu_enable_event()
289 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_enable_event()
294 * Mask out the current event and set the counter to count the event in armv6pmu_enable_event()
297 raw_spin_lock_irqsave(&events->pmu_lock, flags); in armv6pmu_enable_event()
302 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); in armv6pmu_enable_event()
310 struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_handle_irq()
326 for (idx = 0; idx < cpu_pmu->num_events; ++idx) { in armv6pmu_handle_irq()
327 struct perf_event *event = cpuc->events[idx]; in armv6pmu_handle_irq()
335 * We have a single interrupt for all counters. Check that in armv6pmu_handle_irq()
336 * each counter has overflowed before we process it. in armv6pmu_handle_irq()
341 hwc = &event->hw; in armv6pmu_handle_irq()
343 perf_sample_data_init(&data, 0, hwc->last_period); in armv6pmu_handle_irq()
348 cpu_pmu->disable(event); in armv6pmu_handle_irq()
366 struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_start()
368 raw_spin_lock_irqsave(&events->pmu_lock, flags); in armv6pmu_start()
372 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); in armv6pmu_start()
378 struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_stop()
380 raw_spin_lock_irqsave(&events->pmu_lock, flags); in armv6pmu_stop()
384 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); in armv6pmu_stop()
391 struct hw_perf_event *hwc = &event->hw; in armv6pmu_get_event_idx()
392 /* Always place a cycle counter into the cycle counter. */ in armv6pmu_get_event_idx()
393 if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) { in armv6pmu_get_event_idx()
394 if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) in armv6pmu_get_event_idx()
395 return -EAGAIN; in armv6pmu_get_event_idx()
400 * For anything other than a cycle counter, try and use in armv6pmu_get_event_idx()
403 if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) in armv6pmu_get_event_idx()
406 if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) in armv6pmu_get_event_idx()
410 return -EAGAIN; in armv6pmu_get_event_idx()
417 clear_bit(event->hw.idx, cpuc->used_mask); in armv6pmu_clear_event_idx()
423 struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); in armv6pmu_disable_event()
424 struct hw_perf_event *hwc = &event->hw; in armv6pmu_disable_event()
425 struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_disable_event()
426 int idx = hwc->idx; in armv6pmu_disable_event()
438 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_disable_event()
443 * Mask out the current event and set the counter to count the number in armv6pmu_disable_event()
447 raw_spin_lock_irqsave(&events->pmu_lock, flags); in armv6pmu_disable_event()
452 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); in armv6pmu_disable_event()
458 struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); in armv6mpcore_pmu_disable_event()
459 struct hw_perf_event *hwc = &event->hw; in armv6mpcore_pmu_disable_event()
460 struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); in armv6mpcore_pmu_disable_event()
461 int idx = hwc->idx; in armv6mpcore_pmu_disable_event()
470 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6mpcore_pmu_disable_event()
476 * simply disable the interrupt reporting. in armv6mpcore_pmu_disable_event()
478 raw_spin_lock_irqsave(&events->pmu_lock, flags); in armv6mpcore_pmu_disable_event()
483 raw_spin_unlock_irqrestore(&events->pmu_lock, flags); in armv6mpcore_pmu_disable_event()
494 cpu_pmu->handle_irq = armv6pmu_handle_irq; in armv6pmu_init()
495 cpu_pmu->enable = armv6pmu_enable_event; in armv6pmu_init()
496 cpu_pmu->disable = armv6pmu_disable_event; in armv6pmu_init()
497 cpu_pmu->read_counter = armv6pmu_read_counter; in armv6pmu_init()
498 cpu_pmu->write_counter = armv6pmu_write_counter; in armv6pmu_init()
499 cpu_pmu->get_event_idx = armv6pmu_get_event_idx; in armv6pmu_init()
500 cpu_pmu->clear_event_idx = armv6pmu_clear_event_idx; in armv6pmu_init()
501 cpu_pmu->start = armv6pmu_start; in armv6pmu_init()
502 cpu_pmu->stop = armv6pmu_stop; in armv6pmu_init()
503 cpu_pmu->map_event = armv6_map_event; in armv6pmu_init()
504 cpu_pmu->num_events = 3; in armv6pmu_init()
510 cpu_pmu->name = "armv6_1136"; in armv6_1136_pmu_init()
517 cpu_pmu->name = "armv6_1156"; in armv6_1156_pmu_init()
524 cpu_pmu->name = "armv6_1176"; in armv6_1176_pmu_init()
532 * disable the interrupt reporting and update the event. When unthrottling we
533 * reset the period and enable the interrupt reporting.
544 cpu_pmu->name = "armv6_11mpcore"; in armv6mpcore_pmu_init()
545 cpu_pmu->handle_irq = armv6pmu_handle_irq; in armv6mpcore_pmu_init()
546 cpu_pmu->enable = armv6pmu_enable_event; in armv6mpcore_pmu_init()
547 cpu_pmu->disable = armv6mpcore_pmu_disable_event; in armv6mpcore_pmu_init()
548 cpu_pmu->read_counter = armv6pmu_read_counter; in armv6mpcore_pmu_init()
549 cpu_pmu->write_counter = armv6pmu_write_counter; in armv6mpcore_pmu_init()
550 cpu_pmu->get_event_idx = armv6pmu_get_event_idx; in armv6mpcore_pmu_init()
551 cpu_pmu->clear_event_idx = armv6pmu_clear_event_idx; in armv6mpcore_pmu_init()
552 cpu_pmu->start = armv6pmu_start; in armv6mpcore_pmu_init()
553 cpu_pmu->stop = armv6pmu_stop; in armv6mpcore_pmu_init()
554 cpu_pmu->map_event = armv6mpcore_map_event; in armv6mpcore_pmu_init()
555 cpu_pmu->num_events = 3; in armv6mpcore_pmu_init()
561 {.compatible = "arm,arm11mpcore-pmu", .data = armv6mpcore_pmu_init},
562 {.compatible = "arm,arm1176-pmu", .data = armv6_1176_pmu_init},
563 {.compatible = "arm,arm1136-pmu", .data = armv6_1136_pmu_init},
583 .name = "armv6-pmu",