1cad9931fSMasami Hiramatsu /* SPDX-License-Identifier: GPL-2.0 */
2cad9931fSMasami Hiramatsu /* Simple ftrace probe wrapper */
3cad9931fSMasami Hiramatsu #ifndef _LINUX_FPROBE_H
4cad9931fSMasami Hiramatsu #define _LINUX_FPROBE_H
5cad9931fSMasami Hiramatsu
6cad9931fSMasami Hiramatsu #include <linux/compiler.h>
7cad9931fSMasami Hiramatsu #include <linux/ftrace.h>
8*4346ba16SMasami Hiramatsu (Google) #include <linux/rcupdate.h>
9*4346ba16SMasami Hiramatsu (Google) #include <linux/refcount.h>
10*4346ba16SMasami Hiramatsu (Google) #include <linux/slab.h>
11cad9931fSMasami Hiramatsu
1273142cabSJiri Olsa struct fprobe;
1373142cabSJiri Olsa typedef int (*fprobe_entry_cb)(struct fprobe *fp, unsigned long entry_ip,
1446bc0823SMasami Hiramatsu (Google) unsigned long ret_ip, struct ftrace_regs *regs,
1573142cabSJiri Olsa void *entry_data);
1673142cabSJiri Olsa
1773142cabSJiri Olsa typedef void (*fprobe_exit_cb)(struct fprobe *fp, unsigned long entry_ip,
18762abbc0SMasami Hiramatsu (Google) unsigned long ret_ip, struct ftrace_regs *regs,
1973142cabSJiri Olsa void *entry_data);
2073142cabSJiri Olsa
21cad9931fSMasami Hiramatsu /**
22*4346ba16SMasami Hiramatsu (Google) * struct fprobe_hlist_node - address based hash list node for fprobe.
23*4346ba16SMasami Hiramatsu (Google) *
24*4346ba16SMasami Hiramatsu (Google) * @hlist: The hlist node for address search hash table.
25*4346ba16SMasami Hiramatsu (Google) * @addr: One of the probing address of @fp.
26*4346ba16SMasami Hiramatsu (Google) * @fp: The fprobe which owns this.
27*4346ba16SMasami Hiramatsu (Google) */
28*4346ba16SMasami Hiramatsu (Google) struct fprobe_hlist_node {
29*4346ba16SMasami Hiramatsu (Google) struct hlist_node hlist;
30*4346ba16SMasami Hiramatsu (Google) unsigned long addr;
31*4346ba16SMasami Hiramatsu (Google) struct fprobe *fp;
32*4346ba16SMasami Hiramatsu (Google) };
33*4346ba16SMasami Hiramatsu (Google)
34*4346ba16SMasami Hiramatsu (Google) /**
35*4346ba16SMasami Hiramatsu (Google) * struct fprobe_hlist - hash list nodes for fprobe.
36*4346ba16SMasami Hiramatsu (Google) *
37*4346ba16SMasami Hiramatsu (Google) * @hlist: The hlist node for existence checking hash table.
38*4346ba16SMasami Hiramatsu (Google) * @rcu: rcu_head for RCU deferred release.
39*4346ba16SMasami Hiramatsu (Google) * @fp: The fprobe which owns this fprobe_hlist.
40*4346ba16SMasami Hiramatsu (Google) * @size: The size of @array.
41*4346ba16SMasami Hiramatsu (Google) * @array: The fprobe_hlist_node for each address to probe.
42*4346ba16SMasami Hiramatsu (Google) */
43*4346ba16SMasami Hiramatsu (Google) struct fprobe_hlist {
44*4346ba16SMasami Hiramatsu (Google) struct hlist_node hlist;
45*4346ba16SMasami Hiramatsu (Google) struct rcu_head rcu;
46*4346ba16SMasami Hiramatsu (Google) struct fprobe *fp;
47*4346ba16SMasami Hiramatsu (Google) int size;
48*4346ba16SMasami Hiramatsu (Google) struct fprobe_hlist_node array[] __counted_by(size);
49*4346ba16SMasami Hiramatsu (Google) };
50*4346ba16SMasami Hiramatsu (Google)
51*4346ba16SMasami Hiramatsu (Google) /**
52cad9931fSMasami Hiramatsu * struct fprobe - ftrace based probe.
53*4346ba16SMasami Hiramatsu (Google) *
54cad9931fSMasami Hiramatsu * @nmissed: The counter for missing events.
55cad9931fSMasami Hiramatsu * @flags: The status flag.
5676d0de57SMasami Hiramatsu (Google) * @entry_data_size: The private data storage size.
57cad9931fSMasami Hiramatsu * @entry_handler: The callback function for function entry.
585b0ab789SMasami Hiramatsu * @exit_handler: The callback function for function exit.
59*4346ba16SMasami Hiramatsu (Google) * @hlist_array: The fprobe_hlist for fprobe search from IP hash table.
60cad9931fSMasami Hiramatsu */
61cad9931fSMasami Hiramatsu struct fprobe {
62cad9931fSMasami Hiramatsu unsigned long nmissed;
63cad9931fSMasami Hiramatsu unsigned int flags;
6476d0de57SMasami Hiramatsu (Google) size_t entry_data_size;
655b0ab789SMasami Hiramatsu
6673142cabSJiri Olsa fprobe_entry_cb entry_handler;
6773142cabSJiri Olsa fprobe_exit_cb exit_handler;
68*4346ba16SMasami Hiramatsu (Google)
69*4346ba16SMasami Hiramatsu (Google) struct fprobe_hlist *hlist_array;
70cad9931fSMasami Hiramatsu };
71cad9931fSMasami Hiramatsu
72ab51e15dSMasami Hiramatsu /* This fprobe is soft-disabled. */
73cad9931fSMasami Hiramatsu #define FPROBE_FL_DISABLED 1
74cad9931fSMasami Hiramatsu
75ab51e15dSMasami Hiramatsu /*
76ab51e15dSMasami Hiramatsu * This fprobe handler will be shared with kprobes.
77ab51e15dSMasami Hiramatsu * This flag must be set before registering.
78ab51e15dSMasami Hiramatsu */
79ab51e15dSMasami Hiramatsu #define FPROBE_FL_KPROBE_SHARED 2
80ab51e15dSMasami Hiramatsu
fprobe_disabled(struct fprobe * fp)81cad9931fSMasami Hiramatsu static inline bool fprobe_disabled(struct fprobe *fp)
82cad9931fSMasami Hiramatsu {
83cad9931fSMasami Hiramatsu return (fp) ? fp->flags & FPROBE_FL_DISABLED : false;
84cad9931fSMasami Hiramatsu }
85cad9931fSMasami Hiramatsu
fprobe_shared_with_kprobes(struct fprobe * fp)86ab51e15dSMasami Hiramatsu static inline bool fprobe_shared_with_kprobes(struct fprobe *fp)
87ab51e15dSMasami Hiramatsu {
88ab51e15dSMasami Hiramatsu return (fp) ? fp->flags & FPROBE_FL_KPROBE_SHARED : false;
89ab51e15dSMasami Hiramatsu }
90ab51e15dSMasami Hiramatsu
91cad9931fSMasami Hiramatsu #ifdef CONFIG_FPROBE
92cad9931fSMasami Hiramatsu int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter);
93cad9931fSMasami Hiramatsu int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num);
94cad9931fSMasami Hiramatsu int register_fprobe_syms(struct fprobe *fp, const char **syms, int num);
95cad9931fSMasami Hiramatsu int unregister_fprobe(struct fprobe *fp);
96334e5519SMasami Hiramatsu (Google) bool fprobe_is_registered(struct fprobe *fp);
97cad9931fSMasami Hiramatsu #else
register_fprobe(struct fprobe * fp,const char * filter,const char * notfilter)98cad9931fSMasami Hiramatsu static inline int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter)
99cad9931fSMasami Hiramatsu {
100cad9931fSMasami Hiramatsu return -EOPNOTSUPP;
101cad9931fSMasami Hiramatsu }
register_fprobe_ips(struct fprobe * fp,unsigned long * addrs,int num)102cad9931fSMasami Hiramatsu static inline int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
103cad9931fSMasami Hiramatsu {
104cad9931fSMasami Hiramatsu return -EOPNOTSUPP;
105cad9931fSMasami Hiramatsu }
register_fprobe_syms(struct fprobe * fp,const char ** syms,int num)106cad9931fSMasami Hiramatsu static inline int register_fprobe_syms(struct fprobe *fp, const char **syms, int num)
107cad9931fSMasami Hiramatsu {
108cad9931fSMasami Hiramatsu return -EOPNOTSUPP;
109cad9931fSMasami Hiramatsu }
unregister_fprobe(struct fprobe * fp)110cad9931fSMasami Hiramatsu static inline int unregister_fprobe(struct fprobe *fp)
111cad9931fSMasami Hiramatsu {
112cad9931fSMasami Hiramatsu return -EOPNOTSUPP;
113cad9931fSMasami Hiramatsu }
fprobe_is_registered(struct fprobe * fp)114334e5519SMasami Hiramatsu (Google) static inline bool fprobe_is_registered(struct fprobe *fp)
115334e5519SMasami Hiramatsu (Google) {
116334e5519SMasami Hiramatsu (Google) return false;
117334e5519SMasami Hiramatsu (Google) }
118cad9931fSMasami Hiramatsu #endif
119cad9931fSMasami Hiramatsu
120cad9931fSMasami Hiramatsu /**
121cad9931fSMasami Hiramatsu * disable_fprobe() - Disable fprobe
122cad9931fSMasami Hiramatsu * @fp: The fprobe to be disabled.
123cad9931fSMasami Hiramatsu *
124cad9931fSMasami Hiramatsu * This will soft-disable @fp. Note that this doesn't remove the ftrace
125cad9931fSMasami Hiramatsu * hooks from the function entry.
126cad9931fSMasami Hiramatsu */
disable_fprobe(struct fprobe * fp)127cad9931fSMasami Hiramatsu static inline void disable_fprobe(struct fprobe *fp)
128cad9931fSMasami Hiramatsu {
129cad9931fSMasami Hiramatsu if (fp)
130cad9931fSMasami Hiramatsu fp->flags |= FPROBE_FL_DISABLED;
131cad9931fSMasami Hiramatsu }
132cad9931fSMasami Hiramatsu
133cad9931fSMasami Hiramatsu /**
134cad9931fSMasami Hiramatsu * enable_fprobe() - Enable fprobe
135cad9931fSMasami Hiramatsu * @fp: The fprobe to be enabled.
136cad9931fSMasami Hiramatsu *
137cad9931fSMasami Hiramatsu * This will soft-enable @fp.
138cad9931fSMasami Hiramatsu */
enable_fprobe(struct fprobe * fp)139cad9931fSMasami Hiramatsu static inline void enable_fprobe(struct fprobe *fp)
140cad9931fSMasami Hiramatsu {
141cad9931fSMasami Hiramatsu if (fp)
142cad9931fSMasami Hiramatsu fp->flags &= ~FPROBE_FL_DISABLED;
143cad9931fSMasami Hiramatsu }
144cad9931fSMasami Hiramatsu
145*4346ba16SMasami Hiramatsu (Google) /* The entry data size is 4 bits (=16) * sizeof(long) in maximum */
146*4346ba16SMasami Hiramatsu (Google) #define FPROBE_DATA_SIZE_BITS 4
147*4346ba16SMasami Hiramatsu (Google) #define MAX_FPROBE_DATA_SIZE_WORD ((1L << FPROBE_DATA_SIZE_BITS) - 1)
148*4346ba16SMasami Hiramatsu (Google) #define MAX_FPROBE_DATA_SIZE (MAX_FPROBE_DATA_SIZE_WORD * sizeof(long))
149*4346ba16SMasami Hiramatsu (Google)
150cad9931fSMasami Hiramatsu #endif
151