/* * The L220/PL310 PMU has two equivalent counters, Counter1 and Counter0. * Registers controlling these are laid out in pairs, in descending order, i.e. * the register for Counter1 comes first, followed by the register for * Counter0. * We ensure that idx 0 -> Counter0, and idx1 -> Counter1.
*/ staticstruct perf_event *events[PMU_NR_COUNTERS];
/* Find an unused counter */ staticint l2x0_pmu_find_idx(void)
{ int i;
for (i = 0; i < PMU_NR_COUNTERS; i++) { if (!events[i]) return i;
}
return -1;
}
/* How many counters are allocated? */ staticint l2x0_pmu_num_active_counters(void)
{ int i, cnt = 0;
for (i = 0; i < PMU_NR_COUNTERS; i++) { if (events[i])
cnt++;
}
/* * The L2X0 counters saturate at 0xffffffff rather than wrapping, so we * will *always* lose some number of events when a counter saturates, * and have no way of detecting how many were lost. * * To minimize the impact of this, we try to maximize the period by * always starting counters at zero. To ensure that group ratios are * representative, we poll periodically to avoid counters saturating. * See l2x0_pmu_poll().
*/
local64_set(&hw->prev_count, 0);
l2x0_pmu_counter_write(hw->idx, 0);
}
staticenum hrtimer_restart l2x0_pmu_poll(struct hrtimer *hrtimer)
{ unsignedlong flags; int i;
local_irq_save(flags);
__l2x0_pmu_disable();
for (i = 0; i < PMU_NR_COUNTERS; i++) { struct perf_event *event = events[i];
staticint l2x0_pmu_event_add(struct perf_event *event, int flags)
{ struct hw_perf_event *hw = &event->hw; int idx = l2x0_pmu_find_idx();
if (idx == -1) return -EAGAIN;
/* * Pin the timer, so that the overflows are handled by the chosen * event->cpu (this is the same one as presented in "cpumask" * attribute).
*/ if (l2x0_pmu_num_active_counters() == 0)
hrtimer_start(&l2x0_pmu_hrtimer, l2x0_pmu_poll_period,
HRTIMER_MODE_REL_PINNED);
events[idx] = event;
hw->idx = idx;
l2x0_pmu_event_configure(event);
hw->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
if (flags & PERF_EF_START)
l2x0_pmu_event_start(event, 0);
for (i = 0; i < PMU_NR_COUNTERS; i++) { if (events[i])
l2x0_pmu_event_stop(events[i], PERF_EF_UPDATE);
}
}
void l2x0_pmu_resume(void)
{ int i;
if (!l2x0_pmu) return;
l2x0_pmu_reset();
for (i = 0; i < PMU_NR_COUNTERS; i++) { if (events[i])
l2x0_pmu_event_start(events[i], PERF_EF_RELOAD);
}
l2x0_pmu_enable(l2x0_pmu);
}
void __init l2x0_pmu_register(void __iomem *base, u32 part)
{ /* * Determine whether we support the PMU, and choose the name for sysfs. * This is also used by l2x0_pmu_event_attr_is_visible to determine * which events to display, as the PL310 PMU supports a superset of * L220 events. * * The L210 PMU has a different programmer's interface, and is not * supported by this driver. * * We must defer registering the PMU until the perf subsystem is up and * running, so just stash the name and base, and leave that to another * initcall.
*/ switch (part & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L220:
l2x0_name = "l2c_220"; break; case L2X0_CACHE_ID_PART_L310:
l2x0_name = "l2c_310"; break; default: return;
}
l2x0_base = base;
}
static __init int l2x0_pmu_init(void)
{ int ret;
if (!l2x0_base) return 0;
l2x0_pmu = kzalloc(sizeof(*l2x0_pmu), GFP_KERNEL); if (!l2x0_pmu) {
pr_warn("Unable to allocate L2x0 PMU\n"); return -ENOMEM;
}
/* * We always use a hrtimer rather than an interrupt. * See comments in l2x0_pmu_event_configure and l2x0_pmu_poll. * * Polling once a second allows the counters to fill up to 1/128th on a * quad-core test chip with cores clocked at 400MHz. Hopefully this * leaves sufficient headroom to avoid overflow on production silicon * at higher frequencies.
*/
l2x0_pmu_poll_period = ms_to_ktime(1000);
hrtimer_setup(&l2x0_pmu_hrtimer, l2x0_pmu_poll, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
cpumask_set_cpu(0, &pmu_cpu);
ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_L2X0_ONLINE, "perf/arm/l2x0:online", NULL,
l2x0_pmu_offline_cpu); if (ret) goto out_pmu;
ret = perf_pmu_register(l2x0_pmu, l2x0_name, -1); if (ret) goto out_cpuhp;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.