Path: blob/master/tools/perf/arch/arm64/util/hisi-ptt.c
52262 views
// SPDX-License-Identifier: GPL-2.01/*2* HiSilicon PCIe Trace and Tuning (PTT) support3* Copyright (c) 2022 HiSilicon Technologies Co., Ltd.4*/56#include <linux/kernel.h>7#include <linux/types.h>8#include <linux/bitops.h>9#include <linux/log2.h>10#include <linux/zalloc.h>11#include <errno.h>12#include <time.h>1314#include <internal/lib.h> // page_size15#include "../../../util/auxtrace.h"16#include "../../../util/cpumap.h"17#include "../../../util/debug.h"18#include "../../../util/event.h"19#include "../../../util/evlist.h"20#include "../../../util/evsel.h"21#include "../../../util/hisi-ptt.h"22#include "../../../util/pmu.h"23#include "../../../util/record.h"24#include "../../../util/session.h"25#include "../../../util/tsc.h"2627#define KiB(x) ((x) * 1024)28#define MiB(x) ((x) * 1024 * 1024)2930struct hisi_ptt_recording {31struct auxtrace_record itr;32struct perf_pmu *hisi_ptt_pmu;33struct evlist *evlist;34};3536static size_t37hisi_ptt_info_priv_size(struct auxtrace_record *itr __maybe_unused,38struct evlist *evlist __maybe_unused)39{40return HISI_PTT_AUXTRACE_PRIV_SIZE;41}4243static int hisi_ptt_info_fill(struct auxtrace_record *itr,44struct perf_session *session,45struct perf_record_auxtrace_info *auxtrace_info,46size_t priv_size)47{48struct hisi_ptt_recording *pttr =49container_of(itr, struct hisi_ptt_recording, itr);50struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu;5152if (priv_size != HISI_PTT_AUXTRACE_PRIV_SIZE)53return -EINVAL;5455if (!session->evlist->core.nr_mmaps)56return -EINVAL;5758auxtrace_info->type = PERF_AUXTRACE_HISI_PTT;59auxtrace_info->priv[0] = hisi_ptt_pmu->type;6061return 0;62}6364static int hisi_ptt_set_auxtrace_mmap_page(struct record_opts *opts)65{66bool privileged = perf_event_paranoid_check(-1);6768if (!opts->full_auxtrace)69return 0;7071if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {72if (privileged) {73opts->auxtrace_mmap_pages = MiB(16) / page_size;74} else {75opts->auxtrace_mmap_pages = KiB(128) / page_size;76if (opts->mmap_pages == UINT_MAX)77opts->mmap_pages = KiB(256) / page_size;78}79}8081/* Validate auxtrace_mmap_pages */82if (opts->auxtrace_mmap_pages) {83size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;84size_t min_sz = KiB(8);8586if (sz < min_sz || !is_power_of_2(sz)) {87pr_err("Invalid mmap size for HISI PTT: must be at least %zuKiB and a power of 2\n",88min_sz / 1024);89return -EINVAL;90}91}9293return 0;94}9596static int hisi_ptt_recording_options(struct auxtrace_record *itr,97struct evlist *evlist,98struct record_opts *opts)99{100struct hisi_ptt_recording *pttr =101container_of(itr, struct hisi_ptt_recording, itr);102struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu;103struct evsel *evsel, *hisi_ptt_evsel = NULL;104struct evsel *tracking_evsel;105int err;106107pttr->evlist = evlist;108evlist__for_each_entry(evlist, evsel) {109if (evsel->core.attr.type == hisi_ptt_pmu->type) {110if (hisi_ptt_evsel) {111pr_err("There may be only one " HISI_PTT_PMU_NAME "x event\n");112return -EINVAL;113}114evsel->core.attr.freq = 0;115evsel->core.attr.sample_period = 1;116evsel->needs_auxtrace_mmap = true;117hisi_ptt_evsel = evsel;118opts->full_auxtrace = true;119}120}121122err = hisi_ptt_set_auxtrace_mmap_page(opts);123if (err)124return err;125/*126* To obtain the auxtrace buffer file descriptor, the auxtrace event127* must come first.128*/129evlist__to_front(evlist, hisi_ptt_evsel);130evsel__set_sample_bit(hisi_ptt_evsel, TIME);131132/* Add dummy event to keep tracking */133err = parse_event(evlist, "dummy:u");134if (err)135return err;136137tracking_evsel = evlist__last(evlist);138evlist__set_tracking_event(evlist, tracking_evsel);139140tracking_evsel->core.attr.freq = 0;141tracking_evsel->core.attr.sample_period = 1;142evsel__set_sample_bit(tracking_evsel, TIME);143144return 0;145}146147static u64 hisi_ptt_reference(struct auxtrace_record *itr __maybe_unused)148{149return rdtsc();150}151152static void hisi_ptt_recording_free(struct auxtrace_record *itr)153{154struct hisi_ptt_recording *pttr =155container_of(itr, struct hisi_ptt_recording, itr);156157free(pttr);158}159160struct auxtrace_record *hisi_ptt_recording_init(int *err,161struct perf_pmu *hisi_ptt_pmu)162{163struct hisi_ptt_recording *pttr;164165if (!hisi_ptt_pmu) {166*err = -ENODEV;167return NULL;168}169170pttr = zalloc(sizeof(*pttr));171if (!pttr) {172*err = -ENOMEM;173return NULL;174}175176pttr->hisi_ptt_pmu = hisi_ptt_pmu;177pttr->itr.recording_options = hisi_ptt_recording_options;178pttr->itr.info_priv_size = hisi_ptt_info_priv_size;179pttr->itr.info_fill = hisi_ptt_info_fill;180pttr->itr.free = hisi_ptt_recording_free;181pttr->itr.reference = hisi_ptt_reference;182pttr->itr.read_finish = auxtrace_record__read_finish;183pttr->itr.alignment = 0;184185*err = 0;186return &pttr->itr;187}188189190