Lines Matching +full:hw +full:- +full:monitor

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.
37 * Read one performance monitor counter (PMC).
166 if (event->hw.state & PERF_HES_STOPPED)
170 * Performance monitor interrupts come even when interrupts
171 * are soft-disabled, as long as interrupts are hard-enabled.
175 prev = local64_read(&event->hw.prev_count);
177 val = read_pmc(event->hw.idx);
178 } while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
181 delta = (val - prev) & 0xfffffffful;
182 local64_add(delta, &event->count);
183 local64_sub(delta, &event->hw.period_left);
198 if (!cpuhw->disabled) {
199 cpuhw->disabled = 1;
204 if (!cpuhw->pmcs_enabled) {
206 cpuhw->pmcs_enabled = 1;
225 * Re-enable all events if disable == 0.
236 if (!cpuhw->disabled)
239 cpuhw->disabled = 0;
240 ppc_set_pmu_inuse(cpuhw->n_events != 0);
242 if (cpuhw->n_events > 0) {
259 return -1;
265 event->state != PERF_EVENT_STATE_OFF) {
267 return -1;
279 int ret = -EAGAIN;
280 int num_counters = ppmu->n_counter;
284 perf_pmu_disable(event->pmu);
287 if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
288 num_counters = ppmu->n_restricted;
291 * Allocate counters from top-down, so that restricted-capable
294 for (i = num_counters - 1; i >= 0; i--) {
295 if (cpuhw->event[i])
304 event->hw.idx = i;
305 cpuhw->event[i] = event;
306 ++cpuhw->n_events;
309 if (event->hw.sample_period) {
310 s64 left = local64_read(&event->hw.period_left);
312 val = 0x80000000L - left;
314 local64_set(&event->hw.prev_count, val);
317 event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
320 event->hw.state &= ~(PERF_HES_STOPPED | PERF_HES_UPTODATE);
326 write_pmlcb(i, event->hw.config >> 32);
327 write_pmlca(i, event->hw.config_base);
332 perf_pmu_enable(event->pmu);
340 int i = event->hw.idx;
342 perf_pmu_disable(event->pmu);
350 WARN_ON(event != cpuhw->event[event->hw.idx]);
356 cpuhw->event[i] = NULL;
357 event->hw.idx = -1;
361 * just freed up a non-restricted-capable counter, and
362 * there is a restricted-capable counter occupied by
363 * a non-restricted event, migrate that event to the
367 cpuhw->n_events--;
370 perf_pmu_enable(event->pmu);
380 if (event->hw.idx < 0 || !event->hw.sample_period)
383 if (!(event->hw.state & PERF_HES_STOPPED))
387 WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
390 perf_pmu_disable(event->pmu);
392 event->hw.state = 0;
393 left = local64_read(&event->hw.period_left);
396 val = 0x80000000L - left;
397 write_pmc(event->hw.idx, val);
400 perf_pmu_enable(event->pmu);
408 if (event->hw.idx < 0 || !event->hw.sample_period)
411 if (event->hw.state & PERF_HES_STOPPED)
415 perf_pmu_disable(event->pmu);
418 event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
419 write_pmc(event->hw.idx, 0);
422 perf_pmu_enable(event->pmu);
431 if (!atomic_add_unless(&num_events, -1, 1)) {
447 if (!ppmu->cache_events)
448 return -EINVAL;
458 return -EINVAL;
460 ev = (*ppmu->cache_events)[type][op][result];
462 return -EOPNOTSUPP;
463 if (ev == -1)
464 return -EINVAL;
478 if (ppmu->n_counter > MAX_HWEVENTS) {
480 ppmu->n_counter, MAX_HWEVENTS);
481 ppmu->n_counter = MAX_HWEVENTS;
484 switch (event->attr.type) {
486 ev = event->attr.config;
487 if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
488 return -EOPNOTSUPP;
489 ev = ppmu->generic_events[ev];
493 err = hw_perf_cache_event(event->attr.config, &ev);
499 ev = event->attr.config;
503 return -ENOENT;
506 event->hw.config = ppmu->xlate_event(ev);
507 if (!(event->hw.config & FSL_EMB_EVENT_VALID))
508 return -EINVAL;
516 if (event->group_leader != event) {
517 n = collect_events(event->group_leader,
518 ppmu->n_counter - 1, events);
520 return -EINVAL;
523 if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
526 if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED)
530 if (num_restricted >= ppmu->n_restricted)
531 return -EINVAL;
534 event->hw.idx = -1;
536 event->hw.config_base = PMLCA_CE | PMLCA_FCM1 |
539 if (event->attr.exclude_user)
540 event->hw.config_base |= PMLCA_FCU;
541 if (event->attr.exclude_kernel)
542 event->hw.config_base |= PMLCA_FCS;
543 if (event->attr.exclude_idle)
544 return -ENOTSUPP;
546 event->hw.last_period = event->hw.sample_period;
547 local64_set(&event->hw.period_left, event->hw.last_period);
560 err = -EBUSY;
568 event->destroy = hw_perf_event_destroy;
586 * things if requested. Note that interrupts are hard-disabled
592 u64 period = event->hw.sample_period;
593 const u64 last_period = event->hw.last_period;
597 if (event->hw.state & PERF_HES_STOPPED) {
598 write_pmc(event->hw.idx, 0);
603 prev = local64_read(&event->hw.prev_count);
604 delta = (val - prev) & 0xfffffffful;
605 local64_add(delta, &event->count);
612 left = local64_read(&event->hw.period_left) - delta;
619 event->hw.last_period = event->hw.sample_period;
622 val = 0x80000000LL - left;
625 write_pmc(event->hw.idx, val);
626 local64_set(&event->hw.prev_count, val);
627 local64_set(&event->hw.period_left, left);
649 for (i = 0; i < ppmu->n_counter; ++i) {
650 event = cpuhw->event[i];
685 return -EBUSY; /* something's already registered */
688 pr_info("%s performance monitor hardware support registered\n",
689 pmu->name);