Lines Matching +full:event +full:-

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Performance event support - Freescale Embedded Performance Monitor
5 * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
23 struct perf_event *event[MAX_HWEVENTS]; member
162 static void fsl_emb_pmu_read(struct perf_event *event) in fsl_emb_pmu_read() argument
166 if (event->hw.state & PERF_HES_STOPPED) in fsl_emb_pmu_read()
171 * are soft-disabled, as long as interrupts are hard-enabled. in fsl_emb_pmu_read()
175 prev = local64_read(&event->hw.prev_count); in fsl_emb_pmu_read()
177 val = read_pmc(event->hw.idx); in fsl_emb_pmu_read()
178 } while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev); in fsl_emb_pmu_read()
181 delta = (val - prev) & 0xfffffffful; in fsl_emb_pmu_read()
182 local64_add(delta, &event->count); in fsl_emb_pmu_read()
183 local64_sub(delta, &event->hw.period_left); in fsl_emb_pmu_read()
198 if (!cpuhw->disabled) { in fsl_emb_pmu_disable()
199 cpuhw->disabled = 1; in fsl_emb_pmu_disable()
204 if (!cpuhw->pmcs_enabled) { in fsl_emb_pmu_disable()
206 cpuhw->pmcs_enabled = 1; in fsl_emb_pmu_disable()
225 * Re-enable all events if disable == 0.
236 if (!cpuhw->disabled) in fsl_emb_pmu_enable()
239 cpuhw->disabled = 0; in fsl_emb_pmu_enable()
240 ppc_set_pmu_inuse(cpuhw->n_events != 0); in fsl_emb_pmu_enable()
242 if (cpuhw->n_events > 0) { in fsl_emb_pmu_enable()
255 struct perf_event *event; in collect_events() local
259 return -1; in collect_events()
263 for_each_sibling_event(event, group) { in collect_events()
264 if (!is_software_event(event) && in collect_events()
265 event->state != PERF_EVENT_STATE_OFF) { in collect_events()
267 return -1; in collect_events()
268 ctrs[n] = event; in collect_events()
276 static int fsl_emb_pmu_add(struct perf_event *event, int flags) in fsl_emb_pmu_add() argument
279 int ret = -EAGAIN; in fsl_emb_pmu_add()
280 int num_counters = ppmu->n_counter; in fsl_emb_pmu_add()
284 perf_pmu_disable(event->pmu); in fsl_emb_pmu_add()
287 if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) in fsl_emb_pmu_add()
288 num_counters = ppmu->n_restricted; in fsl_emb_pmu_add()
291 * Allocate counters from top-down, so that restricted-capable in fsl_emb_pmu_add()
294 for (i = num_counters - 1; i >= 0; i--) { in fsl_emb_pmu_add()
295 if (cpuhw->event[i]) in fsl_emb_pmu_add()
304 event->hw.idx = i; in fsl_emb_pmu_add()
305 cpuhw->event[i] = event; in fsl_emb_pmu_add()
306 ++cpuhw->n_events; in fsl_emb_pmu_add()
309 if (event->hw.sample_period) { in fsl_emb_pmu_add()
310 s64 left = local64_read(&event->hw.period_left); in fsl_emb_pmu_add()
312 val = 0x80000000L - left; in fsl_emb_pmu_add()
314 local64_set(&event->hw.prev_count, val); in fsl_emb_pmu_add()
317 event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE; in fsl_emb_pmu_add()
320 event->hw.state &= ~(PERF_HES_STOPPED | PERF_HES_UPTODATE); in fsl_emb_pmu_add()
324 perf_event_update_userpage(event); in fsl_emb_pmu_add()
326 write_pmlcb(i, event->hw.config >> 32); in fsl_emb_pmu_add()
327 write_pmlca(i, event->hw.config_base); in fsl_emb_pmu_add()
332 perf_pmu_enable(event->pmu); in fsl_emb_pmu_add()
337 static void fsl_emb_pmu_del(struct perf_event *event, int flags) in fsl_emb_pmu_del() argument
340 int i = event->hw.idx; in fsl_emb_pmu_del()
342 perf_pmu_disable(event->pmu); in fsl_emb_pmu_del()
346 fsl_emb_pmu_read(event); in fsl_emb_pmu_del()
350 WARN_ON(event != cpuhw->event[event->hw.idx]); in fsl_emb_pmu_del()
356 cpuhw->event[i] = NULL; in fsl_emb_pmu_del()
357 event->hw.idx = -1; in fsl_emb_pmu_del()
360 * TODO: if at least one restricted event exists, and we in fsl_emb_pmu_del()
361 * just freed up a non-restricted-capable counter, and in fsl_emb_pmu_del()
362 * there is a restricted-capable counter occupied by in fsl_emb_pmu_del()
363 * a non-restricted event, migrate that event to the in fsl_emb_pmu_del()
367 cpuhw->n_events--; in fsl_emb_pmu_del()
370 perf_pmu_enable(event->pmu); in fsl_emb_pmu_del()
374 static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags) in fsl_emb_pmu_start() argument
380 if (event->hw.idx < 0 || !event->hw.sample_period) in fsl_emb_pmu_start()
383 if (!(event->hw.state & PERF_HES_STOPPED)) in fsl_emb_pmu_start()
387 WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); in fsl_emb_pmu_start()
390 perf_pmu_disable(event->pmu); in fsl_emb_pmu_start()
392 event->hw.state = 0; in fsl_emb_pmu_start()
393 left = local64_read(&event->hw.period_left); in fsl_emb_pmu_start()
396 val = 0x80000000L - left; in fsl_emb_pmu_start()
397 write_pmc(event->hw.idx, val); in fsl_emb_pmu_start()
399 perf_event_update_userpage(event); in fsl_emb_pmu_start()
400 perf_pmu_enable(event->pmu); in fsl_emb_pmu_start()
404 static void fsl_emb_pmu_stop(struct perf_event *event, int ef_flags) in fsl_emb_pmu_stop() argument
408 if (event->hw.idx < 0 || !event->hw.sample_period) in fsl_emb_pmu_stop()
411 if (event->hw.state & PERF_HES_STOPPED) in fsl_emb_pmu_stop()
415 perf_pmu_disable(event->pmu); in fsl_emb_pmu_stop()
417 fsl_emb_pmu_read(event); in fsl_emb_pmu_stop()
418 event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; in fsl_emb_pmu_stop()
419 write_pmc(event->hw.idx, 0); in fsl_emb_pmu_stop()
421 perf_event_update_userpage(event); in fsl_emb_pmu_stop()
422 perf_pmu_enable(event->pmu); in fsl_emb_pmu_stop()
429 static void hw_perf_event_destroy(struct perf_event *event) in hw_perf_event_destroy() argument
431 if (!atomic_add_unless(&num_events, -1, 1)) { in hw_perf_event_destroy()
447 if (!ppmu->cache_events) in hw_perf_cache_event()
448 return -EINVAL; in hw_perf_cache_event()
458 return -EINVAL; in hw_perf_cache_event()
460 ev = (*ppmu->cache_events)[type][op][result]; in hw_perf_cache_event()
462 return -EOPNOTSUPP; in hw_perf_cache_event()
463 if (ev == -1) in hw_perf_cache_event()
464 return -EINVAL; in hw_perf_cache_event()
469 static int fsl_emb_pmu_event_init(struct perf_event *event) in fsl_emb_pmu_event_init() argument
478 if (ppmu->n_counter > MAX_HWEVENTS) { in fsl_emb_pmu_event_init()
480 ppmu->n_counter, MAX_HWEVENTS); in fsl_emb_pmu_event_init()
481 ppmu->n_counter = MAX_HWEVENTS; in fsl_emb_pmu_event_init()
484 switch (event->attr.type) { in fsl_emb_pmu_event_init()
486 ev = event->attr.config; in fsl_emb_pmu_event_init()
487 if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) in fsl_emb_pmu_event_init()
488 return -EOPNOTSUPP; in fsl_emb_pmu_event_init()
489 ev = ppmu->generic_events[ev]; in fsl_emb_pmu_event_init()
493 err = hw_perf_cache_event(event->attr.config, &ev); in fsl_emb_pmu_event_init()
499 ev = event->attr.config; in fsl_emb_pmu_event_init()
503 return -ENOENT; in fsl_emb_pmu_event_init()
506 event->hw.config = ppmu->xlate_event(ev); in fsl_emb_pmu_event_init()
507 if (!(event->hw.config & FSL_EMB_EVENT_VALID)) in fsl_emb_pmu_event_init()
508 return -EINVAL; in fsl_emb_pmu_event_init()
512 * other hardware events in the group. We assume the event in fsl_emb_pmu_event_init()
516 if (event->group_leader != event) { in fsl_emb_pmu_event_init()
517 n = collect_events(event->group_leader, in fsl_emb_pmu_event_init()
518 ppmu->n_counter - 1, events); in fsl_emb_pmu_event_init()
520 return -EINVAL; in fsl_emb_pmu_event_init()
523 if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) { in fsl_emb_pmu_event_init()
526 if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED) in fsl_emb_pmu_event_init()
530 if (num_restricted >= ppmu->n_restricted) in fsl_emb_pmu_event_init()
531 return -EINVAL; in fsl_emb_pmu_event_init()
534 event->hw.idx = -1; in fsl_emb_pmu_event_init()
536 event->hw.config_base = PMLCA_CE | PMLCA_FCM1 | in fsl_emb_pmu_event_init()
539 if (event->attr.exclude_user) in fsl_emb_pmu_event_init()
540 event->hw.config_base |= PMLCA_FCU; in fsl_emb_pmu_event_init()
541 if (event->attr.exclude_kernel) in fsl_emb_pmu_event_init()
542 event->hw.config_base |= PMLCA_FCS; in fsl_emb_pmu_event_init()
543 if (event->attr.exclude_idle) in fsl_emb_pmu_event_init()
544 return -ENOTSUPP; in fsl_emb_pmu_event_init()
546 event->hw.last_period = event->hw.sample_period; in fsl_emb_pmu_event_init()
547 local64_set(&event->hw.period_left, event->hw.last_period); in fsl_emb_pmu_event_init()
560 err = -EBUSY; in fsl_emb_pmu_event_init()
568 event->destroy = hw_perf_event_destroy; in fsl_emb_pmu_event_init()
586 * things if requested. Note that interrupts are hard-disabled
589 static void record_and_restart(struct perf_event *event, unsigned long val, in record_and_restart() argument
592 u64 period = event->hw.sample_period; in record_and_restart()
596 if (event->hw.state & PERF_HES_STOPPED) { in record_and_restart()
597 write_pmc(event->hw.idx, 0); in record_and_restart()
602 prev = local64_read(&event->hw.prev_count); in record_and_restart()
603 delta = (val - prev) & 0xfffffffful; in record_and_restart()
604 local64_add(delta, &event->count); in record_and_restart()
607 * See if the total period for this event has expired, in record_and_restart()
611 left = local64_read(&event->hw.period_left) - delta; in record_and_restart()
618 event->hw.last_period = event->hw.sample_period; in record_and_restart()
621 val = 0x80000000LL - left; in record_and_restart()
624 write_pmc(event->hw.idx, val); in record_and_restart()
625 local64_set(&event->hw.prev_count, val); in record_and_restart()
626 local64_set(&event->hw.period_left, left); in record_and_restart()
627 perf_event_update_userpage(event); in record_and_restart()
635 perf_sample_data_init(&data, 0, event->hw.last_period); in record_and_restart()
637 if (perf_event_overflow(event, &data, regs)) in record_and_restart()
638 fsl_emb_pmu_stop(event, 0); in record_and_restart()
646 struct perf_event *event; in perf_event_interrupt() local
649 for (i = 0; i < ppmu->n_counter; ++i) { in perf_event_interrupt()
650 event = cpuhw->event[i]; in perf_event_interrupt()
654 if (event) { in perf_event_interrupt()
655 /* event has overflowed */ in perf_event_interrupt()
656 record_and_restart(event, val, regs); in perf_event_interrupt()
685 return -EBUSY; /* something's already registered */ in register_fsl_emb_pmu()
689 pmu->name); in register_fsl_emb_pmu()