cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

callchain.h (8470B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef __PERF_CALLCHAIN_H
      3#define __PERF_CALLCHAIN_H
      4
      5#include <linux/list.h>
      6#include <linux/rbtree.h>
      7#include "map_symbol.h"
      8#include "branch.h"
      9
     10struct addr_location;
     11struct evsel;
     12struct ip_callchain;
     13struct map;
     14struct perf_sample;
     15struct thread;
     16struct hists;
     17
     18#define HELP_PAD "\t\t\t\t"
     19
     20#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
     21
     22# define RECORD_MODE_HELP  HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
     23
     24#define RECORD_SIZE_HELP						\
     25	HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
     26	HELP_PAD "\t\tdefault: 8192 (bytes)\n"
     27
     28#define CALLCHAIN_RECORD_HELP  CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
     29
     30#define CALLCHAIN_REPORT_HELP						\
     31	HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|folded|none)\n" \
     32	HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
     33	HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
     34	HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
     35	HELP_PAD "sort_key:\tcall graph sort key (function|address)\n"	\
     36	HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
     37	HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
     38
     39enum perf_call_graph_mode {
     40	CALLCHAIN_NONE,
     41	CALLCHAIN_FP,
     42	CALLCHAIN_DWARF,
     43	CALLCHAIN_LBR,
     44	CALLCHAIN_MAX
     45};
     46
     47enum chain_mode {
     48	CHAIN_NONE,
     49	CHAIN_FLAT,
     50	CHAIN_GRAPH_ABS,
     51	CHAIN_GRAPH_REL,
     52	CHAIN_FOLDED,
     53};
     54
     55enum chain_order {
     56	ORDER_CALLER,
     57	ORDER_CALLEE
     58};
     59
     60struct callchain_node {
     61	struct callchain_node	*parent;
     62	struct list_head	val;
     63	struct list_head	parent_val;
     64	struct rb_node		rb_node_in; /* to insert nodes in an rbtree */
     65	struct rb_node		rb_node;    /* to sort nodes in an output tree */
     66	struct rb_root		rb_root_in; /* input tree of children */
     67	struct rb_root		rb_root;    /* sorted output tree of children */
     68	unsigned int		val_nr;
     69	unsigned int		count;
     70	unsigned int		children_count;
     71	u64			hit;
     72	u64			children_hit;
     73};
     74
     75struct callchain_root {
     76	u64			max_depth;
     77	struct callchain_node	node;
     78};
     79
     80struct callchain_param;
     81
     82typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
     83				 u64, struct callchain_param *);
     84
     85enum chain_key {
     86	CCKEY_FUNCTION,
     87	CCKEY_ADDRESS,
     88	CCKEY_SRCLINE
     89};
     90
     91enum chain_value {
     92	CCVAL_PERCENT,
     93	CCVAL_PERIOD,
     94	CCVAL_COUNT,
     95};
     96
     97extern bool dwarf_callchain_users;
     98
     99struct callchain_param {
    100	bool			enabled;
    101	enum perf_call_graph_mode record_mode;
    102	u32			dump_size;
    103	enum chain_mode 	mode;
    104	u16			max_stack;
    105	u32			print_limit;
    106	double			min_percent;
    107	sort_chain_func_t	sort;
    108	enum chain_order	order;
    109	bool			order_set;
    110	enum chain_key		key;
    111	bool			branch_callstack;
    112	enum chain_value	value;
    113};
    114
    115extern struct callchain_param callchain_param;
    116extern struct callchain_param callchain_param_default;
    117
    118struct callchain_list {
    119	u64			ip;
    120	struct map_symbol	ms;
    121	struct /* for TUI */ {
    122		bool		unfolded;
    123		bool		has_children;
    124	};
    125	u64			branch_count;
    126	u64			from_count;
    127	u64			predicted_count;
    128	u64			abort_count;
    129	u64			cycles_count;
    130	u64			iter_count;
    131	u64			iter_cycles;
    132	struct branch_type_stat brtype_stat;
    133	const char		*srcline;
    134	struct list_head	list;
    135};
    136
    137/*
    138 * A callchain cursor is a single linked list that
    139 * let one feed a callchain progressively.
    140 * It keeps persistent allocated entries to minimize
    141 * allocations.
    142 */
    143struct callchain_cursor_node {
    144	u64				ip;
    145	struct map_symbol		ms;
    146	const char			*srcline;
    147	/* Indicate valid cursor node for LBR stitch */
    148	bool				valid;
    149
    150	bool				branch;
    151	struct branch_flags		branch_flags;
    152	u64				branch_from;
    153	int				nr_loop_iter;
    154	u64				iter_cycles;
    155	struct callchain_cursor_node	*next;
    156};
    157
    158struct stitch_list {
    159	struct list_head		node;
    160	struct callchain_cursor_node	cursor;
    161};
    162
    163struct callchain_cursor {
    164	u64				nr;
    165	struct callchain_cursor_node	*first;
    166	struct callchain_cursor_node	**last;
    167	u64				pos;
    168	struct callchain_cursor_node	*curr;
    169};
    170
    171extern __thread struct callchain_cursor callchain_cursor;
    172
    173static inline void callchain_init(struct callchain_root *root)
    174{
    175	INIT_LIST_HEAD(&root->node.val);
    176	INIT_LIST_HEAD(&root->node.parent_val);
    177
    178	root->node.parent = NULL;
    179	root->node.hit = 0;
    180	root->node.children_hit = 0;
    181	root->node.rb_root_in = RB_ROOT;
    182	root->max_depth = 0;
    183}
    184
    185static inline u64 callchain_cumul_hits(struct callchain_node *node)
    186{
    187	return node->hit + node->children_hit;
    188}
    189
    190static inline unsigned callchain_cumul_counts(struct callchain_node *node)
    191{
    192	return node->count + node->children_count;
    193}
    194
    195int callchain_register_param(struct callchain_param *param);
    196int callchain_append(struct callchain_root *root,
    197		     struct callchain_cursor *cursor,
    198		     u64 period);
    199
    200int callchain_merge(struct callchain_cursor *cursor,
    201		    struct callchain_root *dst, struct callchain_root *src);
    202
    203void callchain_cursor_reset(struct callchain_cursor *cursor);
    204
    205int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
    206			    struct map_symbol *ms,
    207			    bool branch, struct branch_flags *flags,
    208			    int nr_loop_iter, u64 iter_cycles, u64 branch_from,
    209			    const char *srcline);
    210
    211/* Close a cursor writing session. Initialize for the reader */
    212static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
    213{
    214	cursor->curr = cursor->first;
    215	cursor->pos = 0;
    216}
    217
    218/* Cursor reading iteration helpers */
    219static inline struct callchain_cursor_node *
    220callchain_cursor_current(struct callchain_cursor *cursor)
    221{
    222	if (cursor->pos == cursor->nr)
    223		return NULL;
    224
    225	return cursor->curr;
    226}
    227
    228static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
    229{
    230	cursor->curr = cursor->curr->next;
    231	cursor->pos++;
    232}
    233
    234int callchain_cursor__copy(struct callchain_cursor *dst,
    235			   struct callchain_cursor *src);
    236
    237struct option;
    238struct hist_entry;
    239
    240int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
    241int record_callchain_opt(const struct option *opt, const char *arg, int unset);
    242
    243struct record_opts;
    244
    245int record_opts__parse_callchain(struct record_opts *record,
    246				 struct callchain_param *callchain,
    247				 const char *arg, bool unset);
    248
    249int sample__resolve_callchain(struct perf_sample *sample,
    250			      struct callchain_cursor *cursor, struct symbol **parent,
    251			      struct evsel *evsel, struct addr_location *al,
    252			      int max_stack);
    253int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
    254int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
    255			bool hide_unresolved);
    256
    257extern const char record_callchain_help[];
    258int parse_callchain_record(const char *arg, struct callchain_param *param);
    259int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
    260int parse_callchain_report_opt(const char *arg);
    261int parse_callchain_top_opt(const char *arg);
    262int perf_callchain_config(const char *var, const char *value);
    263
    264static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
    265					     struct callchain_cursor *src)
    266{
    267	*dest = *src;
    268
    269	dest->first = src->curr;
    270	dest->nr -= src->pos;
    271}
    272
    273#ifdef HAVE_SKIP_CALLCHAIN_IDX
    274int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
    275#else
    276static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
    277			struct ip_callchain *chain __maybe_unused)
    278{
    279	return -1;
    280}
    281#endif
    282
    283void arch__add_leaf_frame_record_opts(struct record_opts *opts);
    284
    285char *callchain_list__sym_name(struct callchain_list *cl,
    286			       char *bf, size_t bfsize, bool show_dso);
    287char *callchain_node__scnprintf_value(struct callchain_node *node,
    288				      char *bf, size_t bfsize, u64 total);
    289int callchain_node__fprintf_value(struct callchain_node *node,
    290				  FILE *fp, u64 total);
    291
    292int callchain_list_counts__printf_value(struct callchain_list *clist,
    293					FILE *fp, char *bf, int bfsize);
    294
    295void free_callchain(struct callchain_root *root);
    296void decay_callchain(struct callchain_root *root);
    297int callchain_node__make_parent_list(struct callchain_node *node);
    298
    299int callchain_branch_counts(struct callchain_root *root,
    300			    u64 *branch_count, u64 *predicted_count,
    301			    u64 *abort_count, u64 *cycles_count);
    302
    303void callchain_param_setup(u64 sample_type, const char *arch);
    304
    305bool callchain_cnode_matched(struct callchain_node *base_cnode,
    306			     struct callchain_node *pair_cnode);
    307
    308u64 callchain_total_hits(struct hists *hists);
    309
    310s64 callchain_avg_cycles(struct callchain_node *cnode);
    311
    312#endif	/* __PERF_CALLCHAIN_H */