xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/bpf/progs/test_subprogs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #include "vmlinux.h"
2*4882a593Smuzhiyun #include <bpf/bpf_helpers.h>
3*4882a593Smuzhiyun #include <bpf/bpf_core_read.h>
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun const char LICENSE[] SEC("license") = "GPL";
6*4882a593Smuzhiyun 
sub1(int x)7*4882a593Smuzhiyun __noinline int sub1(int x)
8*4882a593Smuzhiyun {
9*4882a593Smuzhiyun 	return x + 1;
10*4882a593Smuzhiyun }
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun static __noinline int sub5(int v);
13*4882a593Smuzhiyun 
sub2(int y)14*4882a593Smuzhiyun __noinline int sub2(int y)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun 	return sub5(y + 2);
17*4882a593Smuzhiyun }
18*4882a593Smuzhiyun 
sub3(int z)19*4882a593Smuzhiyun static __noinline int sub3(int z)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	return z + 3 + sub1(4);
22*4882a593Smuzhiyun }
23*4882a593Smuzhiyun 
sub4(int w)24*4882a593Smuzhiyun static __noinline int sub4(int w)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	return w + sub3(5) + sub1(6);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* sub5() is an identitify function, just to test weirder functions layout and
30*4882a593Smuzhiyun  * call patterns
31*4882a593Smuzhiyun  */
sub5(int v)32*4882a593Smuzhiyun static __noinline int sub5(int v)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	return sub1(v) - 1; /* compensates sub1()'s + 1 */
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /* unfortunately verifier rejects `struct task_struct *t` as an unkown pointer
38*4882a593Smuzhiyun  * type, so we need to accept pointer as integer and then cast it inside the
39*4882a593Smuzhiyun  * function
40*4882a593Smuzhiyun  */
get_task_tgid(uintptr_t t)41*4882a593Smuzhiyun __noinline int get_task_tgid(uintptr_t t)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	/* this ensures that CO-RE relocs work in multi-subprogs .text */
44*4882a593Smuzhiyun 	return BPF_CORE_READ((struct task_struct *)(void *)t, tgid);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun int res1 = 0;
48*4882a593Smuzhiyun int res2 = 0;
49*4882a593Smuzhiyun int res3 = 0;
50*4882a593Smuzhiyun int res4 = 0;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun SEC("raw_tp/sys_enter")
prog1(void * ctx)53*4882a593Smuzhiyun int prog1(void *ctx)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	/* perform some CO-RE relocations to ensure they work with multi-prog
56*4882a593Smuzhiyun 	 * sections correctly
57*4882a593Smuzhiyun 	 */
58*4882a593Smuzhiyun 	struct task_struct *t = (void *)bpf_get_current_task();
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
61*4882a593Smuzhiyun 		return 1;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	res1 = sub1(1) + sub3(2); /* (1 + 1) + (2 + 3 + (4 + 1)) = 12 */
64*4882a593Smuzhiyun 	return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun SEC("raw_tp/sys_exit")
prog2(void * ctx)68*4882a593Smuzhiyun int prog2(void *ctx)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	struct task_struct *t = (void *)bpf_get_current_task();
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
73*4882a593Smuzhiyun 		return 1;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	res2 = sub2(3) + sub3(4); /* (3 + 2) + (4 + 3 + (4 + 1)) = 17 */
76*4882a593Smuzhiyun 	return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* prog3 has the same section name as prog1 */
80*4882a593Smuzhiyun SEC("raw_tp/sys_enter")
prog3(void * ctx)81*4882a593Smuzhiyun int prog3(void *ctx)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	struct task_struct *t = (void *)bpf_get_current_task();
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
86*4882a593Smuzhiyun 		return 1;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	res3 = sub3(5) + 6; /* (5 + 3 + (4 + 1)) + 6 = 19 */
89*4882a593Smuzhiyun 	return 0;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /* prog4 has the same section name as prog2 */
93*4882a593Smuzhiyun SEC("raw_tp/sys_exit")
prog4(void * ctx)94*4882a593Smuzhiyun int prog4(void *ctx)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct task_struct *t = (void *)bpf_get_current_task();
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
99*4882a593Smuzhiyun 		return 1;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	res4 = sub4(7) + sub1(8); /* (7 + (5 + 3 + (4 + 1)) + (6 + 1)) + (8 + 1) = 36 */
102*4882a593Smuzhiyun 	return 0;
103*4882a593Smuzhiyun }
104