1*16a42573SEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*16a42573SEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/regalloc.c */
3*16a42573SEduard Zingerman 
4*16a42573SEduard Zingerman #include <linux/bpf.h>
5*16a42573SEduard Zingerman #include <bpf/bpf_helpers.h>
6*16a42573SEduard Zingerman #include "bpf_misc.h"
7*16a42573SEduard Zingerman 
8*16a42573SEduard Zingerman #define MAX_ENTRIES 11
9*16a42573SEduard Zingerman 
10*16a42573SEduard Zingerman struct test_val {
11*16a42573SEduard Zingerman 	unsigned int index;
12*16a42573SEduard Zingerman 	int foo[MAX_ENTRIES];
13*16a42573SEduard Zingerman };
14*16a42573SEduard Zingerman 
15*16a42573SEduard Zingerman struct {
16*16a42573SEduard Zingerman 	__uint(type, BPF_MAP_TYPE_HASH);
17*16a42573SEduard Zingerman 	__uint(max_entries, 1);
18*16a42573SEduard Zingerman 	__type(key, long long);
19*16a42573SEduard Zingerman 	__type(value, struct test_val);
20*16a42573SEduard Zingerman } map_hash_48b SEC(".maps");
21*16a42573SEduard Zingerman 
22*16a42573SEduard Zingerman SEC("tracepoint")
23*16a42573SEduard Zingerman __description("regalloc basic")
__flag(BPF_F_ANY_ALIGNMENT)24*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
25*16a42573SEduard Zingerman __naked void regalloc_basic(void)
26*16a42573SEduard Zingerman {
27*16a42573SEduard Zingerman 	asm volatile ("					\
28*16a42573SEduard Zingerman 	r6 = r1;					\
29*16a42573SEduard Zingerman 	r1 = 0;						\
30*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
31*16a42573SEduard Zingerman 	r2 = r10;					\
32*16a42573SEduard Zingerman 	r2 += -8;					\
33*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
34*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
35*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
36*16a42573SEduard Zingerman 	r7 = r0;					\
37*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
38*16a42573SEduard Zingerman 	r2 = r0;					\
39*16a42573SEduard Zingerman 	if r0 s> 20 goto l0_%=;				\
40*16a42573SEduard Zingerman 	if r2 s< 0 goto l0_%=;				\
41*16a42573SEduard Zingerman 	r7 += r0;					\
42*16a42573SEduard Zingerman 	r7 += r2;					\
43*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
44*16a42573SEduard Zingerman l0_%=:	exit;						\
45*16a42573SEduard Zingerman "	:
46*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
47*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
48*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
49*16a42573SEduard Zingerman 	: __clobber_all);
50*16a42573SEduard Zingerman }
51*16a42573SEduard Zingerman 
52*16a42573SEduard Zingerman SEC("tracepoint")
53*16a42573SEduard Zingerman __description("regalloc negative")
54*16a42573SEduard Zingerman __failure __msg("invalid access to map value, value_size=48 off=48 size=1")
regalloc_negative(void)55*16a42573SEduard Zingerman __naked void regalloc_negative(void)
56*16a42573SEduard Zingerman {
57*16a42573SEduard Zingerman 	asm volatile ("					\
58*16a42573SEduard Zingerman 	r6 = r1;					\
59*16a42573SEduard Zingerman 	r1 = 0;						\
60*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
61*16a42573SEduard Zingerman 	r2 = r10;					\
62*16a42573SEduard Zingerman 	r2 += -8;					\
63*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
64*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
65*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
66*16a42573SEduard Zingerman 	r7 = r0;					\
67*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
68*16a42573SEduard Zingerman 	r2 = r0;					\
69*16a42573SEduard Zingerman 	if r0 s> 24 goto l0_%=;				\
70*16a42573SEduard Zingerman 	if r2 s< 0 goto l0_%=;				\
71*16a42573SEduard Zingerman 	r7 += r0;					\
72*16a42573SEduard Zingerman 	r7 += r2;					\
73*16a42573SEduard Zingerman 	r0 = *(u8*)(r7 + 0);				\
74*16a42573SEduard Zingerman l0_%=:	exit;						\
75*16a42573SEduard Zingerman "	:
76*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
77*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
78*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
79*16a42573SEduard Zingerman 	: __clobber_all);
80*16a42573SEduard Zingerman }
81*16a42573SEduard Zingerman 
82*16a42573SEduard Zingerman SEC("tracepoint")
83*16a42573SEduard Zingerman __description("regalloc src_reg mark")
__flag(BPF_F_ANY_ALIGNMENT)84*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
85*16a42573SEduard Zingerman __naked void regalloc_src_reg_mark(void)
86*16a42573SEduard Zingerman {
87*16a42573SEduard Zingerman 	asm volatile ("					\
88*16a42573SEduard Zingerman 	r6 = r1;					\
89*16a42573SEduard Zingerman 	r1 = 0;						\
90*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
91*16a42573SEduard Zingerman 	r2 = r10;					\
92*16a42573SEduard Zingerman 	r2 += -8;					\
93*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
94*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
95*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
96*16a42573SEduard Zingerman 	r7 = r0;					\
97*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
98*16a42573SEduard Zingerman 	r2 = r0;					\
99*16a42573SEduard Zingerman 	if r0 s> 20 goto l0_%=;				\
100*16a42573SEduard Zingerman 	r3 = 0;						\
101*16a42573SEduard Zingerman 	if r3 s>= r2 goto l0_%=;			\
102*16a42573SEduard Zingerman 	r7 += r0;					\
103*16a42573SEduard Zingerman 	r7 += r2;					\
104*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
105*16a42573SEduard Zingerman l0_%=:	exit;						\
106*16a42573SEduard Zingerman "	:
107*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
108*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
109*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
110*16a42573SEduard Zingerman 	: __clobber_all);
111*16a42573SEduard Zingerman }
112*16a42573SEduard Zingerman 
113*16a42573SEduard Zingerman SEC("tracepoint")
114*16a42573SEduard Zingerman __description("regalloc src_reg negative")
115*16a42573SEduard Zingerman __failure __msg("invalid access to map value, value_size=48 off=44 size=8")
__flag(BPF_F_ANY_ALIGNMENT)116*16a42573SEduard Zingerman __flag(BPF_F_ANY_ALIGNMENT)
117*16a42573SEduard Zingerman __naked void regalloc_src_reg_negative(void)
118*16a42573SEduard Zingerman {
119*16a42573SEduard Zingerman 	asm volatile ("					\
120*16a42573SEduard Zingerman 	r6 = r1;					\
121*16a42573SEduard Zingerman 	r1 = 0;						\
122*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
123*16a42573SEduard Zingerman 	r2 = r10;					\
124*16a42573SEduard Zingerman 	r2 += -8;					\
125*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
126*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
127*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
128*16a42573SEduard Zingerman 	r7 = r0;					\
129*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
130*16a42573SEduard Zingerman 	r2 = r0;					\
131*16a42573SEduard Zingerman 	if r0 s> 22 goto l0_%=;				\
132*16a42573SEduard Zingerman 	r3 = 0;						\
133*16a42573SEduard Zingerman 	if r3 s>= r2 goto l0_%=;			\
134*16a42573SEduard Zingerman 	r7 += r0;					\
135*16a42573SEduard Zingerman 	r7 += r2;					\
136*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
137*16a42573SEduard Zingerman l0_%=:	exit;						\
138*16a42573SEduard Zingerman "	:
139*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
140*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
141*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
142*16a42573SEduard Zingerman 	: __clobber_all);
143*16a42573SEduard Zingerman }
144*16a42573SEduard Zingerman 
145*16a42573SEduard Zingerman SEC("tracepoint")
146*16a42573SEduard Zingerman __description("regalloc and spill")
__flag(BPF_F_ANY_ALIGNMENT)147*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
148*16a42573SEduard Zingerman __naked void regalloc_and_spill(void)
149*16a42573SEduard Zingerman {
150*16a42573SEduard Zingerman 	asm volatile ("					\
151*16a42573SEduard Zingerman 	r6 = r1;					\
152*16a42573SEduard Zingerman 	r1 = 0;						\
153*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
154*16a42573SEduard Zingerman 	r2 = r10;					\
155*16a42573SEduard Zingerman 	r2 += -8;					\
156*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
157*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
158*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
159*16a42573SEduard Zingerman 	r7 = r0;					\
160*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
161*16a42573SEduard Zingerman 	r2 = r0;					\
162*16a42573SEduard Zingerman 	if r0 s> 20 goto l0_%=;				\
163*16a42573SEduard Zingerman 	/* r0 has upper bound that should propagate into r2 */\
164*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
165*16a42573SEduard Zingerman 	r0 = 0;						\
166*16a42573SEduard Zingerman 	r2 = 0;				/* clear r0 and r2 */\
167*16a42573SEduard Zingerman 	r3 = *(u64*)(r10 - 8);		/* fill r3 */	\
168*16a42573SEduard Zingerman 	if r0 s>= r3 goto l0_%=;			\
169*16a42573SEduard Zingerman 	/* r3 has lower and upper bounds */		\
170*16a42573SEduard Zingerman 	r7 += r3;					\
171*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
172*16a42573SEduard Zingerman l0_%=:	exit;						\
173*16a42573SEduard Zingerman "	:
174*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
175*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
176*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
177*16a42573SEduard Zingerman 	: __clobber_all);
178*16a42573SEduard Zingerman }
179*16a42573SEduard Zingerman 
180*16a42573SEduard Zingerman SEC("tracepoint")
181*16a42573SEduard Zingerman __description("regalloc and spill negative")
182*16a42573SEduard Zingerman __failure __msg("invalid access to map value, value_size=48 off=48 size=8")
__flag(BPF_F_ANY_ALIGNMENT)183*16a42573SEduard Zingerman __flag(BPF_F_ANY_ALIGNMENT)
184*16a42573SEduard Zingerman __naked void regalloc_and_spill_negative(void)
185*16a42573SEduard Zingerman {
186*16a42573SEduard Zingerman 	asm volatile ("					\
187*16a42573SEduard Zingerman 	r6 = r1;					\
188*16a42573SEduard Zingerman 	r1 = 0;						\
189*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
190*16a42573SEduard Zingerman 	r2 = r10;					\
191*16a42573SEduard Zingerman 	r2 += -8;					\
192*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
193*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
194*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
195*16a42573SEduard Zingerman 	r7 = r0;					\
196*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
197*16a42573SEduard Zingerman 	r2 = r0;					\
198*16a42573SEduard Zingerman 	if r0 s> 48 goto l0_%=;				\
199*16a42573SEduard Zingerman 	/* r0 has upper bound that should propagate into r2 */\
200*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
201*16a42573SEduard Zingerman 	r0 = 0;						\
202*16a42573SEduard Zingerman 	r2 = 0;				/* clear r0 and r2 */\
203*16a42573SEduard Zingerman 	r3 = *(u64*)(r10 - 8);		/* fill r3 */\
204*16a42573SEduard Zingerman 	if r0 s>= r3 goto l0_%=;			\
205*16a42573SEduard Zingerman 	/* r3 has lower and upper bounds */		\
206*16a42573SEduard Zingerman 	r7 += r3;					\
207*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
208*16a42573SEduard Zingerman l0_%=:	exit;						\
209*16a42573SEduard Zingerman "	:
210*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
211*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
212*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
213*16a42573SEduard Zingerman 	: __clobber_all);
214*16a42573SEduard Zingerman }
215*16a42573SEduard Zingerman 
216*16a42573SEduard Zingerman SEC("tracepoint")
217*16a42573SEduard Zingerman __description("regalloc three regs")
__flag(BPF_F_ANY_ALIGNMENT)218*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
219*16a42573SEduard Zingerman __naked void regalloc_three_regs(void)
220*16a42573SEduard Zingerman {
221*16a42573SEduard Zingerman 	asm volatile ("					\
222*16a42573SEduard Zingerman 	r6 = r1;					\
223*16a42573SEduard Zingerman 	r1 = 0;						\
224*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
225*16a42573SEduard Zingerman 	r2 = r10;					\
226*16a42573SEduard Zingerman 	r2 += -8;					\
227*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
228*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
229*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
230*16a42573SEduard Zingerman 	r7 = r0;					\
231*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
232*16a42573SEduard Zingerman 	r2 = r0;					\
233*16a42573SEduard Zingerman 	r4 = r2;					\
234*16a42573SEduard Zingerman 	if r0 s> 12 goto l0_%=;				\
235*16a42573SEduard Zingerman 	if r2 s< 0 goto l0_%=;				\
236*16a42573SEduard Zingerman 	r7 += r0;					\
237*16a42573SEduard Zingerman 	r7 += r2;					\
238*16a42573SEduard Zingerman 	r7 += r4;					\
239*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
240*16a42573SEduard Zingerman l0_%=:	exit;						\
241*16a42573SEduard Zingerman "	:
242*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
243*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
244*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
245*16a42573SEduard Zingerman 	: __clobber_all);
246*16a42573SEduard Zingerman }
247*16a42573SEduard Zingerman 
248*16a42573SEduard Zingerman SEC("tracepoint")
249*16a42573SEduard Zingerman __description("regalloc after call")
__flag(BPF_F_ANY_ALIGNMENT)250*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
251*16a42573SEduard Zingerman __naked void regalloc_after_call(void)
252*16a42573SEduard Zingerman {
253*16a42573SEduard Zingerman 	asm volatile ("					\
254*16a42573SEduard Zingerman 	r6 = r1;					\
255*16a42573SEduard Zingerman 	r1 = 0;						\
256*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
257*16a42573SEduard Zingerman 	r2 = r10;					\
258*16a42573SEduard Zingerman 	r2 += -8;					\
259*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
260*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
261*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
262*16a42573SEduard Zingerman 	r7 = r0;					\
263*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
264*16a42573SEduard Zingerman 	r8 = r0;					\
265*16a42573SEduard Zingerman 	r9 = r0;					\
266*16a42573SEduard Zingerman 	call regalloc_after_call__1;			\
267*16a42573SEduard Zingerman 	if r8 s> 20 goto l0_%=;				\
268*16a42573SEduard Zingerman 	if r9 s< 0 goto l0_%=;				\
269*16a42573SEduard Zingerman 	r7 += r8;					\
270*16a42573SEduard Zingerman 	r7 += r9;					\
271*16a42573SEduard Zingerman 	r0 = *(u64*)(r7 + 0);				\
272*16a42573SEduard Zingerman l0_%=:	exit;						\
273*16a42573SEduard Zingerman "	:
274*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
275*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
276*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
277*16a42573SEduard Zingerman 	: __clobber_all);
278*16a42573SEduard Zingerman }
279*16a42573SEduard Zingerman 
280*16a42573SEduard Zingerman static __naked __noinline __attribute__((used))
regalloc_after_call__1(void)281*16a42573SEduard Zingerman void regalloc_after_call__1(void)
282*16a42573SEduard Zingerman {
283*16a42573SEduard Zingerman 	asm volatile ("					\
284*16a42573SEduard Zingerman 	r0 = 0;						\
285*16a42573SEduard Zingerman 	exit;						\
286*16a42573SEduard Zingerman "	::: __clobber_all);
287*16a42573SEduard Zingerman }
288*16a42573SEduard Zingerman 
289*16a42573SEduard Zingerman SEC("tracepoint")
290*16a42573SEduard Zingerman __description("regalloc in callee")
__flag(BPF_F_ANY_ALIGNMENT)291*16a42573SEduard Zingerman __success __flag(BPF_F_ANY_ALIGNMENT)
292*16a42573SEduard Zingerman __naked void regalloc_in_callee(void)
293*16a42573SEduard Zingerman {
294*16a42573SEduard Zingerman 	asm volatile ("					\
295*16a42573SEduard Zingerman 	r6 = r1;					\
296*16a42573SEduard Zingerman 	r1 = 0;						\
297*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
298*16a42573SEduard Zingerman 	r2 = r10;					\
299*16a42573SEduard Zingerman 	r2 += -8;					\
300*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
301*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
302*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
303*16a42573SEduard Zingerman 	r7 = r0;					\
304*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
305*16a42573SEduard Zingerman 	r1 = r0;					\
306*16a42573SEduard Zingerman 	r2 = r0;					\
307*16a42573SEduard Zingerman 	r3 = r7;					\
308*16a42573SEduard Zingerman 	call regalloc_in_callee__1;			\
309*16a42573SEduard Zingerman l0_%=:	exit;						\
310*16a42573SEduard Zingerman "	:
311*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
312*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
313*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
314*16a42573SEduard Zingerman 	: __clobber_all);
315*16a42573SEduard Zingerman }
316*16a42573SEduard Zingerman 
317*16a42573SEduard Zingerman static __naked __noinline __attribute__((used))
regalloc_in_callee__1(void)318*16a42573SEduard Zingerman void regalloc_in_callee__1(void)
319*16a42573SEduard Zingerman {
320*16a42573SEduard Zingerman 	asm volatile ("					\
321*16a42573SEduard Zingerman 	if r1 s> 20 goto l0_%=;				\
322*16a42573SEduard Zingerman 	if r2 s< 0 goto l0_%=;				\
323*16a42573SEduard Zingerman 	r3 += r1;					\
324*16a42573SEduard Zingerman 	r3 += r2;					\
325*16a42573SEduard Zingerman 	r0 = *(u64*)(r3 + 0);				\
326*16a42573SEduard Zingerman 	exit;						\
327*16a42573SEduard Zingerman l0_%=:	r0 = 0;						\
328*16a42573SEduard Zingerman 	exit;						\
329*16a42573SEduard Zingerman "	::: __clobber_all);
330*16a42573SEduard Zingerman }
331*16a42573SEduard Zingerman 
332*16a42573SEduard Zingerman SEC("tracepoint")
333*16a42573SEduard Zingerman __description("regalloc, spill, JEQ")
334*16a42573SEduard Zingerman __success
regalloc_spill_jeq(void)335*16a42573SEduard Zingerman __naked void regalloc_spill_jeq(void)
336*16a42573SEduard Zingerman {
337*16a42573SEduard Zingerman 	asm volatile ("					\
338*16a42573SEduard Zingerman 	r6 = r1;					\
339*16a42573SEduard Zingerman 	r1 = 0;						\
340*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r1;				\
341*16a42573SEduard Zingerman 	r2 = r10;					\
342*16a42573SEduard Zingerman 	r2 += -8;					\
343*16a42573SEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
344*16a42573SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
345*16a42573SEduard Zingerman 	*(u64*)(r10 - 8) = r0;		/* spill r0 */	\
346*16a42573SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
347*16a42573SEduard Zingerman l0_%=:	/* The verifier will walk the rest twice with r0 == 0 and r0 == map_value */\
348*16a42573SEduard Zingerman 	call %[bpf_get_prandom_u32];			\
349*16a42573SEduard Zingerman 	r2 = r0;					\
350*16a42573SEduard Zingerman 	if r2 == 20 goto l1_%=;				\
351*16a42573SEduard Zingerman l1_%=:	/* The verifier will walk the rest two more times with r0 == 20 and r0 == unknown */\
352*16a42573SEduard Zingerman 	r3 = *(u64*)(r10 - 8);		/* fill r3 with map_value */\
353*16a42573SEduard Zingerman 	if r3 == 0 goto l2_%=;		/* skip ldx if map_value == NULL */\
354*16a42573SEduard Zingerman 	/* Buggy verifier will think that r3 == 20 here */\
355*16a42573SEduard Zingerman 	r0 = *(u64*)(r3 + 0);		/* read from map_value */\
356*16a42573SEduard Zingerman l2_%=:	exit;						\
357*16a42573SEduard Zingerman "	:
358*16a42573SEduard Zingerman 	: __imm(bpf_get_prandom_u32),
359*16a42573SEduard Zingerman 	  __imm(bpf_map_lookup_elem),
360*16a42573SEduard Zingerman 	  __imm_addr(map_hash_48b)
361*16a42573SEduard Zingerman 	: __clobber_all);
362*16a42573SEduard Zingerman }
363*16a42573SEduard Zingerman 
364*16a42573SEduard Zingerman char _license[] SEC("license") = "GPL";
365