struct xtensa_pmu_events { /* Array of events currently on this core */ struct perf_event *event[XCHAL_NUM_PERF_COUNTERS]; /* Bitmap of used hardware counters */ unsignedlong used_mask[BITS_TO_LONGS(XCHAL_NUM_PERF_COUNTERS)];
}; static DEFINE_PER_CPU(struct xtensa_pmu_events, xtensa_pmu_events);
staticconst u32 xtensa_hw_ctl[] = {
[PERF_COUNT_HW_CPU_CYCLES] = XTENSA_PMU_MASK(0, 0x1),
[PERF_COUNT_HW_INSTRUCTIONS] = XTENSA_PMU_MASK(2, 0xffff),
[PERF_COUNT_HW_CACHE_REFERENCES] = XTENSA_PMU_MASK(10, 0x1),
[PERF_COUNT_HW_CACHE_MISSES] = XTENSA_PMU_MASK(12, 0x1), /* Taken and non-taken branches + taken loop ends */
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XTENSA_PMU_MASK(2, 0x490), /* Instruction-related + other global stall cycles */
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XTENSA_PMU_MASK(4, 0x1ff), /* Data-related global stall cycles */
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = XTENSA_PMU_MASK(3, 0x1ff),
};
/* * Starts/Stops a counter present on the PMU. The PMI handler * should stop the counter when perf_event_overflow() returns * !0. ->start() will be used to continue.
*/ staticvoid xtensa_pmu_start(struct perf_event *event, int flags)
{ struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx;
/* * Adds/Removes a counter to/from the PMU, can be done inside * a transaction, see the ->*_txn() methods.
*/ staticint xtensa_pmu_add(struct perf_event *event, int flags)
{ struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events); struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx;
if (__test_and_set_bit(idx, ev->used_mask)) {
idx = find_first_zero_bit(ev->used_mask,
XCHAL_NUM_PERF_COUNTERS); if (idx == XCHAL_NUM_PERF_COUNTERS) return -EAGAIN;
local_irq_save(flags);
pr_info("CPU#%d: PMG: 0x%08lx\n", smp_processor_id(),
get_er(XTENSA_PMU_PMG)); for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i)
pr_info("PM%d: 0x%08lx, PMCTRL%d: 0x%08lx, PMSTAT%d: 0x%08lx\n",
i, get_er(XTENSA_PMU_PM(i)),
i, get_er(XTENSA_PMU_PMCTRL(i)),
i, get_er(XTENSA_PMU_PMSTAT(i)));
local_irq_restore(flags);
}
set_er(0, XTENSA_PMU_PMG); for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i) {
set_er(0, XTENSA_PMU_PMCTRL(i));
set_er(get_er(XTENSA_PMU_PMSTAT(i)), XTENSA_PMU_PMSTAT(i));
} return 0;
}
staticint __init xtensa_pmu_init(void)
{ int ret; int irq = irq_create_mapping(NULL, XCHAL_PROFILING_INTERRUPT);
ret = cpuhp_setup_state(CPUHP_AP_PERF_XTENSA_STARTING, "perf/xtensa:starting", xtensa_pmu_setup,
NULL); if (ret) {
pr_err("xtensa_pmu: failed to register CPU-hotplug.\n"); return ret;
} #if XTENSA_FAKE_NMI
enable_irq(irq); #else
ret = request_irq(irq, xtensa_pmu_irq_handler, IRQF_PERCPU, "pmu", NULL); if (ret < 0) return ret; #endif
ret = perf_pmu_register(&xtensa_pmu, "cpu", PERF_TYPE_RAW); if (ret)
free_irq(irq, NULL);
return ret;
}
early_initcall(xtensa_pmu_init);
Messung V0.5
¤ 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.0.0Bemerkung:
(vorverarbeitet)
¤
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.