| /* SPDX-License-Identifier: GPL-2.0 */ |
| #ifndef __PERF_SAMPLE_H |
| #define __PERF_SAMPLE_H |
| |
| #include <linux/perf_event.h> |
| #include <linux/types.h> |
| |
| /* number of register is bound by the number of bits in regs_dump::mask (64) */ |
| #define PERF_SAMPLE_REGS_CACHE_SIZE (8 * sizeof(u64)) |
| |
| struct regs_dump { |
| u64 abi; |
| u64 mask; |
| u64 *regs; |
| |
| /* Cached values/mask filled by first register access. */ |
| u64 cache_regs[PERF_SAMPLE_REGS_CACHE_SIZE]; |
| u64 cache_mask; |
| }; |
| |
| struct stack_dump { |
| u16 offset; |
| u64 size; |
| char *data; |
| }; |
| |
| struct sample_read_value { |
| u64 value; |
| u64 id; /* only if PERF_FORMAT_ID */ |
| u64 lost; /* only if PERF_FORMAT_LOST */ |
| }; |
| |
| struct sample_read { |
| u64 time_enabled; |
| u64 time_running; |
| union { |
| struct { |
| u64 nr; |
| struct sample_read_value *values; |
| } group; |
| struct sample_read_value one; |
| }; |
| }; |
| |
| static inline size_t sample_read_value_size(u64 read_format) |
| { |
| /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ |
| if (read_format & PERF_FORMAT_LOST) |
| return sizeof(struct sample_read_value); |
| else |
| return offsetof(struct sample_read_value, lost); |
| } |
| |
| static inline struct sample_read_value *next_sample_read_value(struct sample_read_value *v, u64 read_format) |
| { |
| return (void *)v + sample_read_value_size(read_format); |
| } |
| |
| #define sample_read_group__for_each(v, nr, rf) \ |
| for (int __i = 0; __i < (int)nr; v = next_sample_read_value(v, rf), __i++) |
| |
| #define MAX_INSN 16 |
| |
| struct aux_sample { |
| u64 size; |
| void *data; |
| }; |
| |
| struct simd_flags { |
| u64 arch:1, /* architecture (isa) */ |
| pred:2; /* predication */ |
| }; |
| |
| /* simd architecture flags */ |
| #define SIMD_OP_FLAGS_ARCH_SVE 0x01 /* ARM SVE */ |
| |
| /* simd predicate flags */ |
| #define SIMD_OP_FLAGS_PRED_PARTIAL 0x01 /* partial predicate */ |
| #define SIMD_OP_FLAGS_PRED_EMPTY 0x02 /* empty predicate */ |
| |
| struct perf_sample { |
| u64 ip; |
| u32 pid, tid; |
| u64 time; |
| u64 addr; |
| u64 id; |
| u64 stream_id; |
| u64 period; |
| u64 weight; |
| u64 transaction; |
| u64 insn_cnt; |
| u64 cyc_cnt; |
| u32 cpu; |
| u32 raw_size; |
| u64 data_src; |
| u64 phys_addr; |
| u64 data_page_size; |
| u64 code_page_size; |
| u64 cgroup; |
| u32 flags; |
| u32 machine_pid; |
| u32 vcpu; |
| u16 insn_len; |
| u8 cpumode; |
| u16 misc; |
| u16 ins_lat; |
| union { |
| u16 p_stage_cyc; |
| u16 retire_lat; |
| }; |
| bool no_hw_idx; /* No hw_idx collected in branch_stack */ |
| char insn[MAX_INSN]; |
| void *raw_data; |
| struct ip_callchain *callchain; |
| struct branch_stack *branch_stack; |
| struct regs_dump user_regs; |
| struct regs_dump intr_regs; |
| struct stack_dump user_stack; |
| struct sample_read read; |
| struct aux_sample aux_sample; |
| struct simd_flags simd_flags; |
| }; |
| |
| /* |
| * raw_data is always 4 bytes from an 8-byte boundary, so subtract 4 to get |
| * 8-byte alignment. |
| */ |
| static inline void *perf_sample__synth_ptr(struct perf_sample *sample) |
| { |
| return sample->raw_data - 4; |
| } |
| |
| #endif /* __PERF_SAMPLE_H */ |