2 * Copyright (c) 2013 Ben Noordhuis <info@bnoordhuis.nl>
3 * Copyright (c) 2013-2015 Dmitry V. Levin <ldv@altlinux.org>
4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2015-2019 The strace developers.
8 * SPDX-License-Identifier: LGPL-2.1-or-later
13 #include "perf_event_struct.h"
14 #include "print_fields.h"
16 #include "xlat/hw_breakpoint_len.h"
17 #include "xlat/hw_breakpoint_type.h"
18 #include "xlat/perf_attr_size.h"
19 #include "xlat/perf_branch_sample_type.h"
20 #include "xlat/perf_event_open_flags.h"
21 #include "xlat/perf_event_read_format.h"
22 #include "xlat/perf_event_sample_format.h"
23 #include "xlat/perf_hw_cache_id.h"
24 #include "xlat/perf_hw_cache_op_id.h"
25 #include "xlat/perf_hw_cache_op_result_id.h"
26 #include "xlat/perf_hw_id.h"
27 #include "xlat/perf_sw_ids.h"
28 #include "xlat/perf_type_id.h"
31 struct perf_event_attr *attr;
36 free_pea_desc(void *pea_desc_ptr)
38 struct pea_desc *desc = pea_desc_ptr;
45 fetch_perf_event_attr(struct tcb *const tcp, const kernel_ulong_t addr)
47 struct pea_desc *desc;
48 struct perf_event_attr *attr;
51 if (umove(tcp, addr + offsetof(struct perf_event_attr, size), &size)) {
56 if (size > sizeof(*attr))
60 size = PERF_ATTR_SIZE_VER0;
63 * Kernel (rightfully) deems invalid attribute structures with size less
64 * than first published format size, and we do the same.
66 if (size < PERF_ATTR_SIZE_VER0) {
72 size = offsetofend(struct perf_event_attr, config);
74 /* Size should be multiple of 8, but kernel doesn't check for it */
77 attr = xzalloc(sizeof(*attr));
79 if (umoven_or_printaddr(tcp, addr, size, attr)) {
85 desc = xmalloc(sizeof(*desc));
90 set_tcb_priv_data(tcp, desc, free_pea_desc);
96 print_perf_event_attr(struct tcb *const tcp, const kernel_ulong_t addr)
98 static const char *precise_ip_desc[] = {
101 "requested to have 0 skid",
105 struct pea_desc *desc;
106 struct perf_event_attr *attr;
109 int use_new_size = 0;
112 * Amusingly, kernel accepts structures with only part of the field
113 * present, so we making check like this (instead of checking
114 * offsetofend against size) in order to print fields as kernel sees
115 * them. This also should work great on big endian architectures.
117 #define _PERF_CHECK_FIELD(_field) \
119 if (offsetof(struct perf_event_attr, _field) >= size) \
120 goto print_perf_event_attr_out; \
123 desc = get_tcb_priv_data(tcp);
128 /* The only error which expected to change size field currently */
129 if (tcp->u_error == E2BIG) {
130 if (umove(tcp, addr + offsetof(struct perf_event_attr, size),
137 PRINT_FIELD_XVAL("{", *attr, type, perf_type_id, "PERF_TYPE_???");
138 PRINT_FIELD_XVAL(", ", *attr, size, perf_attr_size,
139 "PERF_ATTR_SIZE_???");
144 if (use_new_size > 0)
145 printxval(perf_attr_size, new_size,
146 "PERF_ATTR_SIZE_???");
151 switch (attr->type) {
152 case PERF_TYPE_HARDWARE:
153 PRINT_FIELD_XVAL(", ", *attr, config, perf_hw_id,
154 "PERF_COUNT_HW_???");
156 case PERF_TYPE_SOFTWARE:
157 PRINT_FIELD_XVAL(", ", *attr, config, perf_sw_ids,
158 "PERF_COUNT_SW_???");
160 case PERF_TYPE_TRACEPOINT:
162 * "The value to use in config can be obtained from under
163 * debugfs tracing/events/../../id if ftrace is enabled
166 PRINT_FIELD_U(", ", *attr, config);
168 case PERF_TYPE_HW_CACHE:
170 * (perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
171 * (perf_hw_cache_op_result_id << 16)
173 tprints(", config=");
174 printxval(perf_hw_cache_id, attr->config & 0xFF,
175 "PERF_COUNT_HW_CACHE_???");
177 printxval(perf_hw_cache_op_id, (attr->config >> 8) & 0xFF,
178 "PERF_COUNT_HW_CACHE_OP_???");
181 * Current code (see set_ext_hw_attr in arch/x86/events/core.c,
182 * tile_map_cache_event in arch/tile/kernel/perf_event.c,
183 * arc_pmu_cache_event in arch/arc/kernel/perf_event.c,
184 * hw_perf_cache_event in arch/blackfin/kernel/perf_event.c,
185 * _hw_perf_cache_event in arch/metag/kernel/perf/perf_event.c,
186 * mipspmu_map_cache_event in arch/mips/kernel/perf_event_mipsxx.c,
187 * hw_perf_cache_event in arch/powerpc/perf/core-book3s.c,
188 * hw_perf_cache_event in arch/powerpc/perf/core-fsl-emb.c,
189 * hw_perf_cache_event in arch/sh/kernel/perf_event.c,
190 * sparc_map_cache_event in arch/sparc/kernel/perf_event.c,
191 * xtensa_pmu_cache_event in arch/xtensa/kernel/perf_event.c,
192 * armpmu_map_cache_event in drivers/perf/arm_pmu.c) assumes
193 * that cache result is 8 bits in size.
195 printxval(perf_hw_cache_op_result_id,
196 (attr->config >> 16) & 0xFF,
197 "PERF_COUNT_HW_CACHE_RESULT_???");
199 if (attr->config >> 24) {
200 tprintf("|%#" PRIx64 "<<24", attr->config >> 24);
201 tprints_comment("PERF_COUNT_HW_CACHE_???");
206 * "If type is PERF_TYPE_RAW, then a custom "raw" config
207 * value is needed. Most CPUs support events that are not
208 * covered by the "generalized" events. These are
209 * implementation defined; see your CPU manual (for example the
210 * Intel Volume 3B documentation or the AMD BIOS and Kernel
211 * Developer Guide). The libpfm4 library can be used to
212 * translate from the name in the architectural manuals
213 * to the raw hex value perf_event_open() expects in this
216 case PERF_TYPE_BREAKPOINT:
218 * "If type is PERF_TYPE_BREAKPOINT, then leave config set
219 * to zero. Its parameters are set in other places."
222 PRINT_FIELD_X(", ", *attr, config);
227 goto print_perf_event_attr_out;
230 PRINT_FIELD_U(", ", *attr, sample_freq);
232 PRINT_FIELD_U(", ", *attr, sample_period);
234 PRINT_FIELD_FLAGS(", ", *attr, sample_type, perf_event_sample_format,
236 PRINT_FIELD_FLAGS(", ", *attr, read_format, perf_event_read_format,
239 tprintf(", disabled=%u"
243 ", exclusive_user=%u"
244 ", exclude_kernel=%u"
251 ", enable_on_exec=%u"
260 attr->exclude_kernel,
267 attr->enable_on_exec,
271 tprints_comment(precise_ip_desc[attr->precise_ip]);
272 tprintf(", mmap_data=%u"
276 ", exclude_callchain_kernel=%u"
277 ", exclude_callchain_user=%u"
281 ", context_switch=%u"
282 ", write_backward=%u"
288 attr->exclude_callchain_kernel,
289 attr->exclude_callchain_user,
293 attr->context_switch,
294 attr->write_backward,
298 * Print it only in case it is non-zero, since it may contain flags we
299 * are not aware about.
301 if (attr->__reserved_1) {
302 tprintf(", __reserved_1=%#" PRIx64,
303 (uint64_t) attr->__reserved_1);
304 tprints_comment("Bits 63..29");
308 PRINT_FIELD_U(", ", *attr, wakeup_watermark);
310 PRINT_FIELD_U(", ", *attr, wakeup_events);
312 if (attr->type == PERF_TYPE_BREAKPOINT)
313 /* Any combination of R/W with X is deemed invalid */
314 PRINT_FIELD_XVAL(", ", *attr, bp_type, hw_breakpoint_type,
316 (HW_BREAKPOINT_X | HW_BREAKPOINT_RW))
317 ? "HW_BREAKPOINT_INVALID"
318 : "HW_BREAKPOINT_???");
320 if (attr->type == PERF_TYPE_BREAKPOINT)
321 PRINT_FIELD_X(", ", *attr, bp_addr);
323 PRINT_FIELD_X(", ", *attr, config1);
326 * Fields after bp_addr/config1 are optional and may not present; check
327 * against size is needed.
330 _PERF_CHECK_FIELD(bp_len);
331 if (attr->type == PERF_TYPE_BREAKPOINT)
332 PRINT_FIELD_U(", ", *attr, bp_len);
334 PRINT_FIELD_X(", ", *attr, config2);
336 _PERF_CHECK_FIELD(branch_sample_type);
337 if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK) {
338 PRINT_FIELD_FLAGS(", ", *attr, branch_sample_type,
339 perf_branch_sample_type,
340 "PERF_SAMPLE_BRANCH_???");
343 _PERF_CHECK_FIELD(sample_regs_user);
345 * "This bit mask defines the set of user CPU registers to dump on
346 * samples. The layout of the register mask is architecture-specific and
347 * described in the kernel header
348 * arch/ARCH/include/uapi/asm/perf_regs.h."
350 PRINT_FIELD_X(", ", *attr, sample_regs_user);
352 _PERF_CHECK_FIELD(sample_stack_user);
354 * "size of the user stack to dump if PERF_SAMPLE_STACK_USER is
357 if (attr->sample_type & PERF_SAMPLE_STACK_USER)
358 PRINT_FIELD_X(", ", *attr, sample_stack_user);
360 if (attr->use_clockid) {
361 _PERF_CHECK_FIELD(clockid);
362 PRINT_FIELD_XVAL(", ", *attr, clockid, clocknames, "CLOCK_???");
365 _PERF_CHECK_FIELD(sample_regs_intr);
366 PRINT_FIELD_X(", ", *attr, sample_regs_intr);
368 _PERF_CHECK_FIELD(aux_watermark);
369 PRINT_FIELD_U(", ", *attr, aux_watermark);
371 _PERF_CHECK_FIELD(sample_max_stack);
372 PRINT_FIELD_U(", ", *attr, sample_max_stack);
374 /* _PERF_CHECK_FIELD(__reserved_2);
375 PRINT_FIELD_U(", ", *attr, __reserved2); */
377 print_perf_event_attr_out:
378 if ((attr->size && (attr->size > size)) ||
379 (!attr->size && (size < PERF_ATTR_SIZE_VER0)))
385 SYS_FUNC(perf_event_open)
388 * We try to copy out the whole structure on entering in order to check
389 * size value on exiting. We do not check the rest of the fields because
390 * they shouldn't be changed, but copy the whole structure instead
391 * of just size field because they could.
394 if (!fetch_perf_event_attr(tcp, tcp->u_arg[0]))
397 print_perf_event_attr(tcp, tcp->u_arg[0]);
400 tprintf(", %d, %d, ",
402 (int) tcp->u_arg[2]);
403 printfd(tcp, tcp->u_arg[3]);
405 printflags64(perf_event_open_flags, tcp->u_arg[4], "PERF_FLAG_???");
407 return RVAL_DECODED | RVAL_FD;