1#define BTF_TYPES \
2	.btf_strings = "\0int\0i\0ctx\0callback\0main\0", \
3	.btf_types = { \
4	/* 1: int   */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \
5	/* 2: int*  */ BTF_PTR_ENC(1), \
6	/* 3: void* */ BTF_PTR_ENC(0), \
7	/* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \
8		BTF_FUNC_PROTO_ARG_ENC(7, 3), \
9	/* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \
10		BTF_FUNC_PROTO_ARG_ENC(5, 1), \
11		BTF_FUNC_PROTO_ARG_ENC(7, 2), \
12	/* 6: main      */ BTF_FUNC_ENC(20, 4), \
13	/* 7: callback  */ BTF_FUNC_ENC(11, 5), \
14	BTF_END_RAW \
15	}
16
17#define MAIN_TYPE	6
18#define CALLBACK_TYPE	7
19
20/* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF
21 * fields for pseudo calls
22 */
23#define PSEUDO_CALL_INSN() \
24	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \
25		     INSN_OFF_MASK, INSN_IMM_MASK)
26
27/* can't use BPF_FUNC_loop constant,
28 * do_mix_fixups adjusts the IMM field
29 */
30#define HELPER_CALL_INSN() \
31	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK)
32
33{
34	"inline simple bpf_loop call",
35	.insns = {
36	/* main */
37	/* force verifier state branching to verify logic on first and
38	 * subsequent bpf_loop insn processing steps
39	 */
40	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
41	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2),
42	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
43	BPF_JMP_IMM(BPF_JA, 0, 0, 1),
44	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
45
46	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
47	BPF_RAW_INSN(0, 0, 0, 0, 0),
48	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
49	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
50	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
51	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
52	BPF_EXIT_INSN(),
53	/* callback */
54	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
55	BPF_EXIT_INSN(),
56	},
57	.expected_insns = { PSEUDO_CALL_INSN() },
58	.unexpected_insns = { HELPER_CALL_INSN() },
59	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
60	.flags = F_NEEDS_JIT_ENABLED,
61	.result = ACCEPT,
62	.runs = 0,
63	.func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } },
64	.func_info_cnt = 2,
65	BTF_TYPES
66},
67{
68	"don't inline bpf_loop call, flags non-zero",
69	.insns = {
70	/* main */
71	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
72	BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0),
73	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
74	BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0),
75	BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9),
76	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
77	BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0),
78	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
79	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7),
80	BPF_RAW_INSN(0, 0, 0, 0, 0),
81	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
82	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
83	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
84	BPF_EXIT_INSN(),
85	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1),
86	BPF_JMP_IMM(BPF_JA, 0, 0, -10),
87	/* callback */
88	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
89	BPF_EXIT_INSN(),
90	},
91	.expected_insns = { HELPER_CALL_INSN() },
92	.unexpected_insns = { PSEUDO_CALL_INSN() },
93	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
94	.flags = F_NEEDS_JIT_ENABLED,
95	.result = ACCEPT,
96	.runs = 0,
97	.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
98	.func_info_cnt = 2,
99	BTF_TYPES
100},
101{
102	"don't inline bpf_loop call, callback non-constant",
103	.insns = {
104	/* main */
105	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
106	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */
107
108	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
109	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10),
110	BPF_RAW_INSN(0, 0, 0, 0, 0),
111	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
112
113	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
114	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
115	BPF_RAW_INSN(0, 0, 0, 0, 0),
116
117	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
118	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
119	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
120	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
121	BPF_EXIT_INSN(),
122	/* callback */
123	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
124	BPF_EXIT_INSN(),
125	/* callback #2 */
126	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
127	BPF_EXIT_INSN(),
128	},
129	.expected_insns = { HELPER_CALL_INSN() },
130	.unexpected_insns = { PSEUDO_CALL_INSN() },
131	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
132	.flags = F_NEEDS_JIT_ENABLED,
133	.result = ACCEPT,
134	.runs = 0,
135	.func_info = {
136		{ 0, MAIN_TYPE },
137		{ 14, CALLBACK_TYPE },
138		{ 16, CALLBACK_TYPE }
139	},
140	.func_info_cnt = 3,
141	BTF_TYPES
142},
143{
144	"bpf_loop_inline and a dead func",
145	.insns = {
146	/* main */
147
148	/* A reference to callback #1 to make verifier count it as a func.
149	 * This reference is overwritten below and callback #1 is dead.
150	 */
151	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9),
152	BPF_RAW_INSN(0, 0, 0, 0, 0),
153	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
154	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
155	BPF_RAW_INSN(0, 0, 0, 0, 0),
156	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
157	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
158	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
159	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
160	BPF_EXIT_INSN(),
161	/* callback */
162	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
163	BPF_EXIT_INSN(),
164	/* callback #2 */
165	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
166	BPF_EXIT_INSN(),
167	},
168	.expected_insns = { PSEUDO_CALL_INSN() },
169	.unexpected_insns = { HELPER_CALL_INSN() },
170	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
171	.flags = F_NEEDS_JIT_ENABLED,
172	.result = ACCEPT,
173	.runs = 0,
174	.func_info = {
175		{ 0, MAIN_TYPE },
176		{ 10, CALLBACK_TYPE },
177		{ 12, CALLBACK_TYPE }
178	},
179	.func_info_cnt = 3,
180	BTF_TYPES
181},
182{
183	"bpf_loop_inline stack locations for loop vars",
184	.insns = {
185	/* main */
186	BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
187	/* bpf_loop call #1 */
188	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
189	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22),
190	BPF_RAW_INSN(0, 0, 0, 0, 0),
191	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
192	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
193	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
194	/* bpf_loop call #2 */
195	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
196	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16),
197	BPF_RAW_INSN(0, 0, 0, 0, 0),
198	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
199	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
200	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
201	/* call func and exit */
202	BPF_CALL_REL(2),
203	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
204	BPF_EXIT_INSN(),
205	/* func */
206	BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
207	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
208	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
209	BPF_RAW_INSN(0, 0, 0, 0, 0),
210	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
211	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
212	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
213	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
214	BPF_EXIT_INSN(),
215	/* callback */
216	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
217	BPF_EXIT_INSN(),
218	},
219	.expected_insns = {
220	BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
221	SKIP_INSNS(),
222	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
223	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
224	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
225	SKIP_INSNS(),
226	/* offsets are the same as in the first call */
227	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
228	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
229	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
230	SKIP_INSNS(),
231	BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
232	SKIP_INSNS(),
233	/* offsets differ from main because of different offset
234	 * in BPF_ST_MEM instruction
235	 */
236	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56),
237	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48),
238	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40),
239	},
240	.unexpected_insns = { HELPER_CALL_INSN() },
241	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
242	.flags = F_NEEDS_JIT_ENABLED,
243	.result = ACCEPT,
244	.func_info = {
245		{ 0, MAIN_TYPE },
246		{ 16, MAIN_TYPE },
247		{ 25, CALLBACK_TYPE },
248	},
249	.func_info_cnt = 3,
250	BTF_TYPES
251},
252{
253	"inline bpf_loop call in a big program",
254	.insns = {},
255	.fill_helper = bpf_fill_big_prog_with_loop_1,
256	.expected_insns = { PSEUDO_CALL_INSN() },
257	.unexpected_insns = { HELPER_CALL_INSN() },
258	.result = ACCEPT,
259	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
260	.flags = F_NEEDS_JIT_ENABLED,
261	.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
262	.func_info_cnt = 2,
263	BTF_TYPES
264},
265
266#undef HELPER_CALL_INSN
267#undef PSEUDO_CALL_INSN
268#undef CALLBACK_TYPE
269#undef MAIN_TYPE
270#undef BTF_TYPES
271