Lines Matching +full:spe +full:- +full:pmu

1 // SPDX-License-Identifier: GPL-2.0
3 * Arm Statistical Profiling Extensions (SPE) support
4 * Copyright (c) 2017-2018, Arm Ltd.
22 #include "../../../util/pmu.h"
27 #include "../../../util/arm-spe.h"
49 struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus; in arm_spe_find_cpus()
88 struct perf_pmu *pmu = NULL; in arm_spe_save_cpu_header() local
95 return -ENOMEM; in arm_spe_save_cpu_header()
100 data[ARM_SPE_CPU_NR_PARAMS] = ARM_SPE_CPU_PRIV_MAX - ARM_SPE_CPU_MIDR; in arm_spe_save_cpu_header()
103 /* Find the associate Arm SPE PMU for the CPU */ in arm_spe_save_cpu_header()
104 if (perf_cpu_map__has(sper->arm_spe_pmu->cpus, cpu)) in arm_spe_save_cpu_header()
105 pmu = sper->arm_spe_pmu; in arm_spe_save_cpu_header()
107 if (!pmu) { in arm_spe_save_cpu_header()
108 /* No Arm SPE PMU is found */ in arm_spe_save_cpu_header()
112 data[ARM_SPE_CPU_PMU_TYPE] = pmu->type; in arm_spe_save_cpu_header()
114 if (perf_pmu__scan_file(pmu, "caps/min_interval", "%lu", &val) != 1) in arm_spe_save_cpu_header()
132 struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; in arm_spe_info_fill()
137 if (priv_size != arm_spe_info_priv_size(itr, session->evlist)) in arm_spe_info_fill()
138 return -EINVAL; in arm_spe_info_fill()
140 if (!session->evlist->core.nr_mmaps) in arm_spe_info_fill()
141 return -EINVAL; in arm_spe_info_fill()
143 cpu_map = arm_spe_find_cpus(session->evlist); in arm_spe_info_fill()
145 return -EINVAL; in arm_spe_info_fill()
147 auxtrace_info->type = PERF_AUXTRACE_ARM_SPE; in arm_spe_info_fill()
148 auxtrace_info->priv[ARM_SPE_HEADER_VERSION] = ARM_SPE_HEADER_CURRENT_VERSION; in arm_spe_info_fill()
149 auxtrace_info->priv[ARM_SPE_HEADER_SIZE] = in arm_spe_info_fill()
150 ARM_SPE_AUXTRACE_PRIV_MAX - ARM_SPE_HEADER_VERSION; in arm_spe_info_fill()
151 auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2] = arm_spe_pmu->type; in arm_spe_info_fill()
152 auxtrace_info->priv[ARM_SPE_CPUS_NUM] = perf_cpu_map__nr(cpu_map); in arm_spe_info_fill()
157 data = &auxtrace_info->priv[offset]; in arm_spe_info_fill()
186 * No size were given to '-S' or '-m,', so go with the default in arm_spe_snapshot_resolve_auxtrace_defaults()
188 if (!opts->auxtrace_snapshot_size && !opts->auxtrace_mmap_pages) { in arm_spe_snapshot_resolve_auxtrace_defaults()
190 opts->auxtrace_mmap_pages = MiB(4) / page_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
192 opts->auxtrace_mmap_pages = KiB(128) / page_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
193 if (opts->mmap_pages == UINT_MAX) in arm_spe_snapshot_resolve_auxtrace_defaults()
194 opts->mmap_pages = KiB(256) / page_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
196 } else if (!opts->auxtrace_mmap_pages && !privileged && opts->mmap_pages == UINT_MAX) { in arm_spe_snapshot_resolve_auxtrace_defaults()
197 opts->mmap_pages = KiB(256) / page_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
201 * '-m,xyz' was specified but no snapshot size, so make the snapshot size as big as the in arm_spe_snapshot_resolve_auxtrace_defaults()
204 if (!opts->auxtrace_snapshot_size) in arm_spe_snapshot_resolve_auxtrace_defaults()
205 opts->auxtrace_snapshot_size = opts->auxtrace_mmap_pages * (size_t)page_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
208 * '-Sxyz' was specified but no auxtrace mmap area, so make the auxtrace mmap area big in arm_spe_snapshot_resolve_auxtrace_defaults()
211 if (!opts->auxtrace_mmap_pages) { in arm_spe_snapshot_resolve_auxtrace_defaults()
212 size_t sz = opts->auxtrace_snapshot_size; in arm_spe_snapshot_resolve_auxtrace_defaults()
215 opts->auxtrace_mmap_pages = roundup_pow_of_two(sz); in arm_spe_snapshot_resolve_auxtrace_defaults()
242 evsel->core.attr.freq = 0; in arm_spe_setup_evsel()
243 evsel->core.attr.sample_period = arm_spe_pmu__sample_period(evsel->pmu); in arm_spe_setup_evsel()
244 evsel->needs_auxtrace_mmap = true; in arm_spe_setup_evsel()
250 evlist__to_front(evsel->evlist, evsel); in arm_spe_setup_evsel()
253 * In the case of per-cpu mmaps, sample CPU for AUX event; in arm_spe_setup_evsel()
258 evsel__set_config_if_unset(evsel->pmu, evsel, "ts_enable", 1); in arm_spe_setup_evsel()
262 * Set this only so that perf report knows that SPE generates memory info. It has no effect in arm_spe_setup_evsel()
263 * on the opening of the event or the SPE data produced. in arm_spe_setup_evsel()
269 * inform that the resulting output's SPE samples contain physical addresses in arm_spe_setup_evsel()
272 bit = perf_pmu__format_bits(evsel->pmu, "pa_enable"); in arm_spe_setup_evsel()
273 if (evsel->core.attr.config & bit) in arm_spe_setup_evsel()
279 bool privileged = perf_event_paranoid_check(-1); in arm_spe_setup_aux_buffer()
284 if (opts->auxtrace_snapshot_mode) { in arm_spe_setup_aux_buffer()
286 * Command arguments '-Sxyz' and/or '-m,xyz' are missing, so fill those in with in arm_spe_setup_aux_buffer()
289 if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages) in arm_spe_setup_aux_buffer()
295 if (opts->auxtrace_snapshot_size > opts->auxtrace_mmap_pages * (size_t)page_size) { in arm_spe_setup_aux_buffer()
297 opts->auxtrace_snapshot_size, in arm_spe_setup_aux_buffer()
298 opts->auxtrace_mmap_pages * (size_t)page_size); in arm_spe_setup_aux_buffer()
299 return -EINVAL; in arm_spe_setup_aux_buffer()
303 * Something went wrong somewhere - this shouldn't happen. in arm_spe_setup_aux_buffer()
305 if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages) { in arm_spe_setup_aux_buffer()
307 return -EINVAL; in arm_spe_setup_aux_buffer()
311 opts->auxtrace_snapshot_size); in arm_spe_setup_aux_buffer()
314 /* We are in full trace mode but '-m,xyz' wasn't specified */ in arm_spe_setup_aux_buffer()
315 if (!opts->auxtrace_mmap_pages) { in arm_spe_setup_aux_buffer()
317 opts->auxtrace_mmap_pages = MiB(4) / page_size; in arm_spe_setup_aux_buffer()
319 opts->auxtrace_mmap_pages = KiB(128) / page_size; in arm_spe_setup_aux_buffer()
320 if (opts->mmap_pages == UINT_MAX) in arm_spe_setup_aux_buffer()
321 opts->mmap_pages = KiB(256) / page_size; in arm_spe_setup_aux_buffer()
326 if (opts->auxtrace_mmap_pages) { in arm_spe_setup_aux_buffer()
327 size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size; in arm_spe_setup_aux_buffer()
331 pr_err("Invalid mmap size for ARM SPE: must be at least %zuKiB and a power of 2\n", in arm_spe_setup_aux_buffer()
333 return -EINVAL; in arm_spe_setup_aux_buffer()
345 struct perf_cpu_map *cpus = evlist->core.user_requested_cpus; in arm_spe_setup_tracking_event()
355 tracking_evsel->core.attr.freq = 0; in arm_spe_setup_tracking_event()
356 tracking_evsel->core.attr.sample_period = 1; in arm_spe_setup_tracking_event()
358 /* In per-cpu case, always need the time of mmap events etc */ in arm_spe_setup_tracking_event()
365 tracking_evsel->core.attr.context_switch = 1; in arm_spe_setup_tracking_event()
378 struct perf_cpu_map *cpus = evlist->core.user_requested_cpus; in arm_spe_recording_options()
382 sper->evlist = evlist; in arm_spe_recording_options()
386 if (!strstarts(evsel->pmu->name, ARM_SPE_PMU_NAME)) { in arm_spe_recording_options()
388 evsel->pmu->name); in arm_spe_recording_options()
389 return -EINVAL; in arm_spe_recording_options()
391 opts->full_auxtrace = true; in arm_spe_recording_options()
395 if (!opts->full_auxtrace) in arm_spe_recording_options()
401 if (evsel->core.attr.config & in arm_spe_recording_options()
402 perf_pmu__format_bits(evsel->pmu, "discard")) in arm_spe_recording_options()
427 return -1; in arm_spe_parse_snapshot_options()
430 opts->auxtrace_snapshot_mode = true; in arm_spe_parse_snapshot_options()
431 opts->auxtrace_snapshot_size = snapshot_size; in arm_spe_parse_snapshot_options()
441 int ret = -EINVAL; in arm_spe_snapshot_start()
443 evlist__for_each_entry(ptr->evlist, evsel) { in arm_spe_snapshot_start()
458 int ret = -EINVAL; in arm_spe_snapshot_finish()
460 evlist__for_each_entry(ptr->evlist, evsel) { in arm_spe_snapshot_finish()
473 int cnt = ptr->wrapped_cnt, new_cnt, i; in arm_spe_alloc_wrapped_array()
482 * Make ptr->wrapped as big as idx. in arm_spe_alloc_wrapped_array()
489 wrapped = reallocarray(ptr->wrapped, new_cnt, sizeof(bool)); in arm_spe_alloc_wrapped_array()
491 return -ENOMEM; in arm_spe_alloc_wrapped_array()
499 ptr->wrapped_cnt = new_cnt; in arm_spe_alloc_wrapped_array()
500 ptr->wrapped = wrapped; in arm_spe_alloc_wrapped_array()
513 * Defensively handle the case where head might be continually increasing - if its value is in arm_spe_buffer_has_wrapped()
523 watermark = buf_size - 512; in arm_spe_buffer_has_wrapped()
569 if (idx >= ptr->wrapped_cnt) { in arm_spe_find_snapshot()
581 wrapped = ptr->wrapped[idx]; in arm_spe_find_snapshot()
582 if (!wrapped && arm_spe_buffer_has_wrapped(data, mm->len, *head)) { in arm_spe_find_snapshot()
584 ptr->wrapped[idx] = true; in arm_spe_find_snapshot()
588 __func__, idx, (size_t)*old, (size_t)*head, mm->len); in arm_spe_find_snapshot()
597 * *head has wrapped around - adjust *head and *old to pickup the in arm_spe_find_snapshot()
600 if (*head >= mm->len) { in arm_spe_find_snapshot()
601 *old = *head - mm->len; in arm_spe_find_snapshot()
603 *head += mm->len; in arm_spe_find_snapshot()
604 *old = *head - mm->len; in arm_spe_find_snapshot()
624 zfree(&sper->wrapped); in arm_spe_recording_free()
634 *err = -ENODEV; in arm_spe_recording_init()
640 *err = -ENOMEM; in arm_spe_recording_init()
644 sper->arm_spe_pmu = arm_spe_pmu; in arm_spe_recording_init()
645 sper->itr.snapshot_start = arm_spe_snapshot_start; in arm_spe_recording_init()
646 sper->itr.snapshot_finish = arm_spe_snapshot_finish; in arm_spe_recording_init()
647 sper->itr.find_snapshot = arm_spe_find_snapshot; in arm_spe_recording_init()
648 sper->itr.parse_snapshot_options = arm_spe_parse_snapshot_options; in arm_spe_recording_init()
649 sper->itr.recording_options = arm_spe_recording_options; in arm_spe_recording_init()
650 sper->itr.info_priv_size = arm_spe_info_priv_size; in arm_spe_recording_init()
651 sper->itr.info_fill = arm_spe_info_fill; in arm_spe_recording_init()
652 sper->itr.free = arm_spe_recording_free; in arm_spe_recording_init()
653 sper->itr.reference = arm_spe_reference; in arm_spe_recording_init()
654 sper->itr.read_finish = auxtrace_record__read_finish; in arm_spe_recording_init()
655 sper->itr.alignment = 0; in arm_spe_recording_init()
658 return &sper->itr; in arm_spe_recording_init()
664 attr->sample_period = arm_spe_pmu__sample_period(arm_spe_pmu); in arm_spe_pmu_default_config()