1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include "bpf_misc.h"
6
7 struct timer_value {
8 struct bpf_timer timer;
9 };
10
11 struct {
12 __uint(type, BPF_MAP_TYPE_ARRAY);
13 __uint(max_entries, 1);
14 __type(key, __u32);
15 __type(value, struct timer_value);
16 } timer_map SEC(".maps");
17
18 SEC("?raw_tp")
19 __success __log_level(4)
20 __msg("subprog 0 (stats_main_only) main insns_self 2 insns_total 2 stack 0")
21 __msg("processed 2 insns")
stats_main_only(void)22 __naked int stats_main_only(void)
23 {
24 asm volatile (
25 "r0 = 0;"
26 "exit;"
27 );
28 }
29
30 __naked __noinline __used
stats_chain_leaf(void)31 static int stats_chain_leaf(void)
32 {
33 asm volatile (
34 "r0 = 0;"
35 "exit;"
36 );
37 }
38
39 __naked __noinline __used
stats_chain_parent(void)40 static int stats_chain_parent(void)
41 {
42 asm volatile (
43 "call stats_chain_leaf;"
44 "exit;"
45 );
46 }
47
48 SEC("?raw_tp")
49 __success __log_level(4)
50 /*
51 * self: 2 + 2 + 2 = 6
52 * totals: leaf 2, parent 2 + 2 = 4, main 2 + 4 = 6
53 */
54 __msg("subprog 0 (stats_static_chain) main insns_self 2 insns_total 6 stack 0")
55 __msg("subprog {{[0-9]+}} (stats_chain_parent) static insns_self 2 insns_total 4 stack 0")
56 __msg("subprog {{[0-9]+}} (stats_chain_leaf) static insns_self 2 insns_total 2 stack 0")
57 __msg("processed 6 insns")
stats_static_chain(void)58 __naked int stats_static_chain(void)
59 {
60 asm volatile (
61 "call stats_chain_parent;"
62 "exit;"
63 );
64 }
65
66 __naked __noinline __used
stats_shared_leaf(void)67 static int stats_shared_leaf(void)
68 {
69 asm volatile (
70 "r0 = 0;"
71 "exit;"
72 );
73 }
74
75 __naked __noinline __used
stats_global_root(void)76 int stats_global_root(void)
77 {
78 asm volatile (
79 "call stats_shared_leaf;"
80 "exit;"
81 );
82 }
83
84 SEC("?raw_tp")
85 __success __log_level(4)
86 /*
87 * stats_shared_leaf is explored once under each independent root.
88 * self: main 3 + leaf 4 + global 2 = 9
89 * root totals: main 5 + global 4 = 9
90 */
91 __msg("subprog 0 (stats_shared_roots) main insns_self 3 insns_total 5 stack 0")
92 __msg("subprog {{[0-9]+}} (stats_shared_leaf) static insns_self 4 insns_total 4 stack 0")
93 __msg("subprog {{[0-9]+}} (stats_global_root) global insns_self 2 insns_total 4 stack 0")
94 __msg("processed 9 insns")
stats_shared_roots(void)95 __naked int stats_shared_roots(void)
96 {
97 asm volatile (
98 "call stats_shared_leaf;"
99 "call stats_global_root;"
100 "exit;"
101 );
102 }
103
104 __noinline __used
stats_async_leaf(void * map,__u32 * key,struct bpf_timer * timer)105 static int stats_async_leaf(void *map, __u32 *key, struct bpf_timer *timer)
106 {
107 return 0;
108 }
109
110 __noinline __used
stats_async_schedule(struct bpf_map * map,__u32 * key,struct timer_value * value,void * ctx)111 static __u64 stats_async_schedule(struct bpf_map *map, __u32 *key,
112 struct timer_value *value, void *ctx)
113 {
114 asm volatile (
115 "r1 = %[timer];"
116 "r2 = %[stats_async_leaf];"
117 "call %[bpf_timer_set_callback];"
118 :
119 : [timer] "r" (value),
120 __imm_ptr(stats_async_leaf),
121 __imm(bpf_timer_set_callback)
122 : __clobber_common
123 );
124 return 0;
125 }
126
127 SEC("?raw_tp")
128 __success __log_level(4)
129 /*
130 * self: 9 + 7 + 2 = 18
131 * totals: leaf 2, scheduler 7, main root 18
132 */
133 __msg("subprog 0 (stats_async_direct) main insns_self 9 insns_total 18 stack 0")
134 __msg("subprog {{[0-9]+}} (stats_async_schedule) static insns_self 7 insns_total 7 stack 0")
135 __msg("subprog {{[0-9]+}} (stats_async_leaf) static insns_self 2 insns_total 2 stack 0")
136 __msg("processed 18 insns")
stats_async_direct(void)137 __naked int stats_async_direct(void)
138 {
139 asm volatile (
140 "r1 = %[timer_map] ll;"
141 "r2 = %[stats_async_schedule];"
142 "r3 = 0;"
143 "r4 = 0;"
144 "call %[bpf_for_each_map_elem];"
145 "r0 = 0;"
146 "exit;"
147 :
148 : __imm_addr(timer_map),
149 __imm_ptr(stats_async_schedule),
150 __imm(bpf_for_each_map_elem)
151 : __clobber_common
152 );
153 }
154
155 __noinline __used
stats_async_nested_leaf(void * map,__u32 * key,struct bpf_timer * timer)156 static int stats_async_nested_leaf(void *map, __u32 *key, struct bpf_timer *timer)
157 {
158 return 0;
159 }
160
161 __noinline __used
stats_async_outer(void * map,__u32 * key,struct bpf_timer * timer)162 static int stats_async_outer(void *map, __u32 *key, struct bpf_timer *timer)
163 {
164 asm volatile (
165 "r1 = %[timer];"
166 "r2 = %[stats_async_nested_leaf];"
167 "call %[bpf_timer_set_callback];"
168 :
169 : [timer] "r" (timer),
170 __imm_ptr(stats_async_nested_leaf),
171 __imm(bpf_timer_set_callback)
172 : __clobber_common
173 );
174 return 0;
175 }
176
177 __noinline __used
stats_async_nested_schedule(struct bpf_map * map,__u32 * key,struct timer_value * value,void * ctx)178 static __u64 stats_async_nested_schedule(struct bpf_map *map, __u32 *key,
179 struct timer_value *value, void *ctx)
180 {
181 asm volatile (
182 "r1 = %[timer];"
183 "r2 = %[stats_async_outer];"
184 "call %[bpf_timer_set_callback];"
185 :
186 : [timer] "r" (value),
187 __imm_ptr(stats_async_outer),
188 __imm(bpf_timer_set_callback)
189 : __clobber_common
190 );
191 return 0;
192 }
193
194 SEC("?raw_tp")
195 __success __log_level(4)
196 /*
197 * self: 9 + 7 + 7 + 2 = 25
198 * totals: leaf 2, outer 7, scheduler 7, main root 25
199 */
200 __msg("subprog 0 (stats_async_nested) main insns_self 9 insns_total 25 stack 0")
201 __msg("subprog {{[0-9]+}} (stats_async_nested_schedule) static insns_self 7 insns_total 7 stack 0")
202 __msg("subprog {{[0-9]+}} (stats_async_outer) static insns_self 7 insns_total 7 stack 0")
203 __msg("subprog {{[0-9]+}} (stats_async_nested_leaf) static insns_self 2 insns_total 2 stack 0")
204 __msg("processed 25 insns")
stats_async_nested(void)205 __naked int stats_async_nested(void)
206 {
207 asm volatile (
208 "r1 = %[timer_map] ll;"
209 "r2 = %[stats_async_nested_schedule];"
210 "r3 = 0;"
211 "r4 = 0;"
212 "call %[bpf_for_each_map_elem];"
213 "r0 = 0;"
214 "exit;"
215 :
216 : __imm_addr(timer_map),
217 __imm_ptr(stats_async_nested_schedule),
218 __imm(bpf_for_each_map_elem)
219 : __clobber_common
220 );
221 }
222
223 char _license[] SEC("license") = "GPL";
224