~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/arm64/util/hisi-ptt.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * HiSilicon PCIe Trace and Tuning (PTT) support
  4  * Copyright (c) 2022 HiSilicon Technologies Co., Ltd.
  5  */
  6 
  7 #include <linux/kernel.h>
  8 #include <linux/types.h>
  9 #include <linux/bitops.h>
 10 #include <linux/log2.h>
 11 #include <linux/zalloc.h>
 12 #include <time.h>
 13 
 14 #include <internal/lib.h> // page_size
 15 #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"
 26 
 27 #define KiB(x) ((x) * 1024)
 28 #define MiB(x) ((x) * 1024 * 1024)
 29 
 30 struct hisi_ptt_recording {
 31         struct auxtrace_record  itr;
 32         struct perf_pmu *hisi_ptt_pmu;
 33         struct evlist *evlist;
 34 };
 35 
 36 static size_t
 37 hisi_ptt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
 38                         struct evlist *evlist __maybe_unused)
 39 {
 40         return HISI_PTT_AUXTRACE_PRIV_SIZE;
 41 }
 42 
 43 static int hisi_ptt_info_fill(struct auxtrace_record *itr,
 44                               struct perf_session *session,
 45                               struct perf_record_auxtrace_info *auxtrace_info,
 46                               size_t priv_size)
 47 {
 48         struct hisi_ptt_recording *pttr =
 49                         container_of(itr, struct hisi_ptt_recording, itr);
 50         struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu;
 51 
 52         if (priv_size != HISI_PTT_AUXTRACE_PRIV_SIZE)
 53                 return -EINVAL;
 54 
 55         if (!session->evlist->core.nr_mmaps)
 56                 return -EINVAL;
 57 
 58         auxtrace_info->type = PERF_AUXTRACE_HISI_PTT;
 59         auxtrace_info->priv[0] = hisi_ptt_pmu->type;
 60 
 61         return 0;
 62 }
 63 
 64 static int hisi_ptt_set_auxtrace_mmap_page(struct record_opts *opts)
 65 {
 66         bool privileged = perf_event_paranoid_check(-1);
 67 
 68         if (!opts->full_auxtrace)
 69                 return 0;
 70 
 71         if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
 72                 if (privileged) {
 73                         opts->auxtrace_mmap_pages = MiB(16) / page_size;
 74                 } else {
 75                         opts->auxtrace_mmap_pages = KiB(128) / page_size;
 76                         if (opts->mmap_pages == UINT_MAX)
 77                                 opts->mmap_pages = KiB(256) / page_size;
 78                 }
 79         }
 80 
 81         /* Validate auxtrace_mmap_pages */
 82         if (opts->auxtrace_mmap_pages) {
 83                 size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
 84                 size_t min_sz = KiB(8);
 85 
 86                 if (sz < min_sz || !is_power_of_2(sz)) {
 87                         pr_err("Invalid mmap size for HISI PTT: must be at least %zuKiB and a power of 2\n",
 88                                min_sz / 1024);
 89                         return -EINVAL;
 90                 }
 91         }
 92 
 93         return 0;
 94 }
 95 
 96 static int hisi_ptt_recording_options(struct auxtrace_record *itr,
 97                                       struct evlist *evlist,
 98                                       struct record_opts *opts)
 99 {
100         struct hisi_ptt_recording *pttr =
101                         container_of(itr, struct hisi_ptt_recording, itr);
102         struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu;
103         struct evsel *evsel, *hisi_ptt_evsel = NULL;
104         struct evsel *tracking_evsel;
105         int err;
106 
107         pttr->evlist = evlist;
108         evlist__for_each_entry(evlist, evsel) {
109                 if (evsel->core.attr.type == hisi_ptt_pmu->type) {
110                         if (hisi_ptt_evsel) {
111                                 pr_err("There may be only one " HISI_PTT_PMU_NAME "x event\n");
112                                 return -EINVAL;
113                         }
114                         evsel->core.attr.freq = 0;
115                         evsel->core.attr.sample_period = 1;
116                         evsel->needs_auxtrace_mmap = true;
117                         hisi_ptt_evsel = evsel;
118                         opts->full_auxtrace = true;
119                 }
120         }
121 
122         err = hisi_ptt_set_auxtrace_mmap_page(opts);
123         if (err)
124                 return err;
125         /*
126          * To obtain the auxtrace buffer file descriptor, the auxtrace event
127          * must come first.
128          */
129         evlist__to_front(evlist, hisi_ptt_evsel);
130         evsel__set_sample_bit(hisi_ptt_evsel, TIME);
131 
132         /* Add dummy event to keep tracking */
133         err = parse_event(evlist, "dummy:u");
134         if (err)
135                 return err;
136 
137         tracking_evsel = evlist__last(evlist);
138         evlist__set_tracking_event(evlist, tracking_evsel);
139 
140         tracking_evsel->core.attr.freq = 0;
141         tracking_evsel->core.attr.sample_period = 1;
142         evsel__set_sample_bit(tracking_evsel, TIME);
143 
144         return 0;
145 }
146 
147 static u64 hisi_ptt_reference(struct auxtrace_record *itr __maybe_unused)
148 {
149         return rdtsc();
150 }
151 
152 static void hisi_ptt_recording_free(struct auxtrace_record *itr)
153 {
154         struct hisi_ptt_recording *pttr =
155                         container_of(itr, struct hisi_ptt_recording, itr);
156 
157         free(pttr);
158 }
159 
160 struct auxtrace_record *hisi_ptt_recording_init(int *err,
161                                                 struct perf_pmu *hisi_ptt_pmu)
162 {
163         struct hisi_ptt_recording *pttr;
164 
165         if (!hisi_ptt_pmu) {
166                 *err = -ENODEV;
167                 return NULL;
168         }
169 
170         pttr = zalloc(sizeof(*pttr));
171         if (!pttr) {
172                 *err = -ENOMEM;
173                 return NULL;
174         }
175 
176         pttr->hisi_ptt_pmu = hisi_ptt_pmu;
177         pttr->itr.pmu = hisi_ptt_pmu;
178         pttr->itr.recording_options = hisi_ptt_recording_options;
179         pttr->itr.info_priv_size = hisi_ptt_info_priv_size;
180         pttr->itr.info_fill = hisi_ptt_info_fill;
181         pttr->itr.free = hisi_ptt_recording_free;
182         pttr->itr.reference = hisi_ptt_reference;
183         pttr->itr.read_finish = auxtrace_record__read_finish;
184         pttr->itr.alignment = 0;
185 
186         *err = 0;
187         return &pttr->itr;
188 }
189 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php