xref: /linux/tools/testing/selftests/bpf/progs/verifier_zext.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1*8b365b3cSEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*8b365b3cSEduard Zingerman 
3*8b365b3cSEduard Zingerman #include <linux/bpf.h>
4*8b365b3cSEduard Zingerman #include <bpf/bpf_helpers.h>
5*8b365b3cSEduard Zingerman #include "../../../include/linux/filter.h"
6*8b365b3cSEduard Zingerman #include <bpf_arena_common.h>
7*8b365b3cSEduard Zingerman #include <bpf/bpf_core_read.h>
8*8b365b3cSEduard Zingerman #include "bpf_misc.h"
9*8b365b3cSEduard Zingerman 
10*8b365b3cSEduard Zingerman struct {
11*8b365b3cSEduard Zingerman 	__uint(type, BPF_MAP_TYPE_ARENA);
12*8b365b3cSEduard Zingerman 	__uint(map_flags, BPF_F_MMAPABLE | BPF_F_NO_USER_CONV);
13*8b365b3cSEduard Zingerman 	__uint(max_entries, 1);
14*8b365b3cSEduard Zingerman } arena SEC(".maps");
15*8b365b3cSEduard Zingerman 
16*8b365b3cSEduard Zingerman extern long bpf_kfunc_call_test4(signed char a, short b, int c, long d) __ksym;
17*8b365b3cSEduard Zingerman 
18*8b365b3cSEduard Zingerman /* to retain debug info for BTF generation */
__kfunc_btf_root(void)19*8b365b3cSEduard Zingerman void __kfunc_btf_root(void)
20*8b365b3cSEduard Zingerman {
21*8b365b3cSEduard Zingerman 	bpf_kfunc_call_test4(0, 0, 0, 0);
22*8b365b3cSEduard Zingerman 	bpf_arena_alloc_pages(0, 0, 0, 0, 0);
23*8b365b3cSEduard Zingerman 	bpf_rdonly_cast(0, 0);
24*8b365b3cSEduard Zingerman }
25*8b365b3cSEduard Zingerman 
26*8b365b3cSEduard Zingerman SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)27*8b365b3cSEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
28*8b365b3cSEduard Zingerman __flag(BPF_F_TEST_RND_HI32)
29*8b365b3cSEduard Zingerman __success __retval(0)
30*8b365b3cSEduard Zingerman __naked void zext_lost_across_checkpoint(void)
31*8b365b3cSEduard Zingerman {
32*8b365b3cSEduard Zingerman 	asm volatile ("									\
33*8b365b3cSEduard Zingerman 	call %[bpf_ktime_get_ns];							\
34*8b365b3cSEduard Zingerman 	r8 = r0;									\
35*8b365b3cSEduard Zingerman 	r6 = 0xdeadbeefcafebabe ll;	/* inject some value for r6's upper half */	\
36*8b365b3cSEduard Zingerman 	if r8 != 0 goto 1f;		/* fall-through cached first, branch pruned */	\
37*8b365b3cSEduard Zingerman 	r6 = 32;			/* full 64-bit def */				\
38*8b365b3cSEduard Zingerman 	goto 2f;									\
39*8b365b3cSEduard Zingerman 1:	w6 = 32;			/* 32-bit def, zext mark lost */		\
40*8b365b3cSEduard Zingerman 2:	r0 = r6;			/* buggy verifier believed upper 32 bits are 0 */ \
41*8b365b3cSEduard Zingerman 					/* and thus did not zero extended w6 = 32. */	\
42*8b365b3cSEduard Zingerman 	r0 >>= 32;									\
43*8b365b3cSEduard Zingerman 	exit;										\
44*8b365b3cSEduard Zingerman "	:
45*8b365b3cSEduard Zingerman 	: __imm(bpf_ktime_get_ns)
46*8b365b3cSEduard Zingerman 	: __clobber_all);
47*8b365b3cSEduard Zingerman }
48*8b365b3cSEduard Zingerman 
49*8b365b3cSEduard Zingerman /* 32-bit ALU result read as 64-bit -> zext */
50*8b365b3cSEduard Zingerman SEC("socket")
51*8b365b3cSEduard Zingerman __success __log_level(2)
52*8b365b3cSEduard Zingerman __msg("w1 = w0{{ +}}; zext")
zext_alu32_hi_used(void)53*8b365b3cSEduard Zingerman __naked void zext_alu32_hi_used(void)
54*8b365b3cSEduard Zingerman {
55*8b365b3cSEduard Zingerman 	asm volatile ("					\
56*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
57*8b365b3cSEduard Zingerman 	w1 = w0;					\
58*8b365b3cSEduard Zingerman 	r0 = r1;					\
59*8b365b3cSEduard Zingerman 	exit;						\
60*8b365b3cSEduard Zingerman "	:
61*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
62*8b365b3cSEduard Zingerman 	: __clobber_all);
63*8b365b3cSEduard Zingerman }
64*8b365b3cSEduard Zingerman 
65*8b365b3cSEduard Zingerman /* 32-bit ALU result read only as 32-bit -> no zext */
66*8b365b3cSEduard Zingerman SEC("socket")
67*8b365b3cSEduard Zingerman __success __log_level(2)
68*8b365b3cSEduard Zingerman __not_msg("; zext")
no_zext_alu32_hi_unused(void)69*8b365b3cSEduard Zingerman __naked void no_zext_alu32_hi_unused(void)
70*8b365b3cSEduard Zingerman {
71*8b365b3cSEduard Zingerman 	asm volatile ("					\
72*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
73*8b365b3cSEduard Zingerman 	w1 = w0;		/* MOV */		\
74*8b365b3cSEduard Zingerman 	w2 = w1;					\
75*8b365b3cSEduard Zingerman 	w2 += w1;		/* ALU32, BPF_X */	\
76*8b365b3cSEduard Zingerman 	w2 += 1;		/* ALU32, BPF_K */	\
77*8b365b3cSEduard Zingerman 	w2 = w2;		/* keep w2 alive for previous instruction */ \
78*8b365b3cSEduard Zingerman 	r0 = 0;						\
79*8b365b3cSEduard Zingerman 	exit;						\
80*8b365b3cSEduard Zingerman "	:
81*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
82*8b365b3cSEduard Zingerman 	: __clobber_all);
83*8b365b3cSEduard Zingerman }
84*8b365b3cSEduard Zingerman 
85*8b365b3cSEduard Zingerman /* 64-bit definition is never zero extended */
86*8b365b3cSEduard Zingerman SEC("socket")
87*8b365b3cSEduard Zingerman __success __log_level(2)
88*8b365b3cSEduard Zingerman __not_msg("r1 = r0{{.*}}; zext")
no_zext_mov64(void)89*8b365b3cSEduard Zingerman __naked void no_zext_mov64(void)
90*8b365b3cSEduard Zingerman {
91*8b365b3cSEduard Zingerman 	asm volatile ("					\
92*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
93*8b365b3cSEduard Zingerman 	r1 = r0;					\
94*8b365b3cSEduard Zingerman 	r0 = r1;					\
95*8b365b3cSEduard Zingerman 	exit;						\
96*8b365b3cSEduard Zingerman "	:
97*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
98*8b365b3cSEduard Zingerman 	: __clobber_all);
99*8b365b3cSEduard Zingerman }
100*8b365b3cSEduard Zingerman 
101*8b365b3cSEduard Zingerman /* Narrow load result read as 64-bit -> zext */
102*8b365b3cSEduard Zingerman SEC("socket")
103*8b365b3cSEduard Zingerman __success __log_level(2)
104*8b365b3cSEduard Zingerman __msg("r1 = *(u32 *)(r10 -8){{ +}}; zext")
zext_narrow_load_hi_used(void)105*8b365b3cSEduard Zingerman __naked void zext_narrow_load_hi_used(void)
106*8b365b3cSEduard Zingerman {
107*8b365b3cSEduard Zingerman 	asm volatile ("					\
108*8b365b3cSEduard Zingerman 	r0 = 0;						\
109*8b365b3cSEduard Zingerman 	*(u64 *)(r10 - 8) = r0;				\
110*8b365b3cSEduard Zingerman 	r1 = *(u32 *)(r10 - 8);				\
111*8b365b3cSEduard Zingerman 	r0 = r1;					\
112*8b365b3cSEduard Zingerman 	exit;						\
113*8b365b3cSEduard Zingerman "	::: __clobber_all);
114*8b365b3cSEduard Zingerman }
115*8b365b3cSEduard Zingerman 
116*8b365b3cSEduard Zingerman /* 32-bit atomic fetch result read as 64-bit -> zext */
117*8b365b3cSEduard Zingerman SEC("socket")
118*8b365b3cSEduard Zingerman __success __log_level(2)
119*8b365b3cSEduard Zingerman __msg("r1 = atomic_fetch_add((u32 *)(r10 -8), r1){{ +}}; zext")
zext_atomic_fetch32_hi_used(void)120*8b365b3cSEduard Zingerman __naked void zext_atomic_fetch32_hi_used(void)
121*8b365b3cSEduard Zingerman {
122*8b365b3cSEduard Zingerman 	asm volatile ("					\
123*8b365b3cSEduard Zingerman 	r1 = 0;						\
124*8b365b3cSEduard Zingerman 	*(u64 *)(r10 - 8) = r1;				\
125*8b365b3cSEduard Zingerman 	w1 = 1;						\
126*8b365b3cSEduard Zingerman 	.8byte %[fetch_add32];				\
127*8b365b3cSEduard Zingerman 	r0 = r1;					\
128*8b365b3cSEduard Zingerman 	exit;						\
129*8b365b3cSEduard Zingerman "	:
130*8b365b3cSEduard Zingerman 	: __imm_insn(fetch_add32,
131*8b365b3cSEduard Zingerman 		     BPF_ATOMIC_OP(BPF_W, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8))
132*8b365b3cSEduard Zingerman 	: __clobber_all);
133*8b365b3cSEduard Zingerman }
134*8b365b3cSEduard Zingerman 
135*8b365b3cSEduard Zingerman /* 32-bit atomic cmpxchg result (r0) read as 64-bit -> zext */
136*8b365b3cSEduard Zingerman SEC("socket")
137*8b365b3cSEduard Zingerman __success __log_level(2)
138*8b365b3cSEduard Zingerman __msg("r0 = atomic_cmpxchg((u32 *)(r10 -8), r0, r1){{ +}}; zext")
zext_cmpxchg32_hi_used(void)139*8b365b3cSEduard Zingerman __naked void zext_cmpxchg32_hi_used(void)
140*8b365b3cSEduard Zingerman {
141*8b365b3cSEduard Zingerman 	asm volatile ("					\
142*8b365b3cSEduard Zingerman 	r1 = 0;						\
143*8b365b3cSEduard Zingerman 	*(u64 *)(r10 - 8) = r1;				\
144*8b365b3cSEduard Zingerman 	w0 = 0;						\
145*8b365b3cSEduard Zingerman 	w1 = 1;						\
146*8b365b3cSEduard Zingerman 	.8byte %[cmpxchg32];				\
147*8b365b3cSEduard Zingerman 	r2 = r0;					\
148*8b365b3cSEduard Zingerman 	r0 = r2;					\
149*8b365b3cSEduard Zingerman 	exit;						\
150*8b365b3cSEduard Zingerman "	:
151*8b365b3cSEduard Zingerman 	: __imm_insn(cmpxchg32,
152*8b365b3cSEduard Zingerman 		     BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8))
153*8b365b3cSEduard Zingerman 	: __clobber_all);
154*8b365b3cSEduard Zingerman }
155*8b365b3cSEduard Zingerman 
156*8b365b3cSEduard Zingerman /* 32-bit def before a branch, upper half used on one branch -> zext */
157*8b365b3cSEduard Zingerman SEC("socket")
158*8b365b3cSEduard Zingerman __success __log_level(2)
159*8b365b3cSEduard Zingerman __msg("w6 = 32{{ +}}; zext")
zext_cfg_hi_used_one_branch(void)160*8b365b3cSEduard Zingerman __naked void zext_cfg_hi_used_one_branch(void)
161*8b365b3cSEduard Zingerman {
162*8b365b3cSEduard Zingerman 	asm volatile ("					\
163*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
164*8b365b3cSEduard Zingerman 	w6 = 32;					\
165*8b365b3cSEduard Zingerman 	if r0 == 0 goto 1f;				\
166*8b365b3cSEduard Zingerman 	r0 = r6;					\
167*8b365b3cSEduard Zingerman 	exit;						\
168*8b365b3cSEduard Zingerman 1:	r0 = 0;						\
169*8b365b3cSEduard Zingerman 	exit;						\
170*8b365b3cSEduard Zingerman "	:
171*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
172*8b365b3cSEduard Zingerman 	: __clobber_all);
173*8b365b3cSEduard Zingerman }
174*8b365b3cSEduard Zingerman 
175*8b365b3cSEduard Zingerman /* r1's upper half is dead, so 'w1 = 1' must NOT be marked for zero extension. */
176*8b365b3cSEduard Zingerman SEC("socket")
177*8b365b3cSEduard Zingerman __success __log_level(2)
178*8b365b3cSEduard Zingerman __not_msg("w1 = 1{{.*}}; zext")
no_zext_other_reg_hi_used(void)179*8b365b3cSEduard Zingerman __naked void no_zext_other_reg_hi_used(void)
180*8b365b3cSEduard Zingerman {
181*8b365b3cSEduard Zingerman 	asm volatile ("					\
182*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
183*8b365b3cSEduard Zingerman 	r6 = r0;					\
184*8b365b3cSEduard Zingerman 	r6 <<= 32;					\
185*8b365b3cSEduard Zingerman 	w1 = 1;						\
186*8b365b3cSEduard Zingerman 	r0 = r6;					\
187*8b365b3cSEduard Zingerman 	exit;						\
188*8b365b3cSEduard Zingerman "	:
189*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
190*8b365b3cSEduard Zingerman 	: __clobber_all);
191*8b365b3cSEduard Zingerman }
192*8b365b3cSEduard Zingerman 
193*8b365b3cSEduard Zingerman /* LD_ABS defines r0; when r0 is read as 64-bit it must be zero extended */
194*8b365b3cSEduard Zingerman SEC("socket")
195*8b365b3cSEduard Zingerman __success __log_level(2)
196*8b365b3cSEduard Zingerman __msg("r0 = *(u8 *)skb[0]{{.*}}; zext")
zext_ld_abs_hi_used(void)197*8b365b3cSEduard Zingerman __naked void zext_ld_abs_hi_used(void)
198*8b365b3cSEduard Zingerman {
199*8b365b3cSEduard Zingerman 	asm volatile ("					\
200*8b365b3cSEduard Zingerman 	r6 = r1;					\
201*8b365b3cSEduard Zingerman 	r0 = *(u8 *)skb[0];				\
202*8b365b3cSEduard Zingerman 	r7 = r0;					\
203*8b365b3cSEduard Zingerman 	r0 = r7;					\
204*8b365b3cSEduard Zingerman 	exit;						\
205*8b365b3cSEduard Zingerman "	::: __clobber_all);
206*8b365b3cSEduard Zingerman }
207*8b365b3cSEduard Zingerman 
208*8b365b3cSEduard Zingerman /* Helper parameters are read as 64-bit (call_use_mask() fallback) */
209*8b365b3cSEduard Zingerman SEC("socket")
210*8b365b3cSEduard Zingerman __success __log_level(2)
211*8b365b3cSEduard Zingerman __msg("w2 = 1{{ +}}; zext")
helper_param_read_as_64bit(void)212*8b365b3cSEduard Zingerman __naked void helper_param_read_as_64bit(void)
213*8b365b3cSEduard Zingerman {
214*8b365b3cSEduard Zingerman 	asm volatile ("					\
215*8b365b3cSEduard Zingerman 	r1 = r10;					\
216*8b365b3cSEduard Zingerman 	r1 += -8;					\
217*8b365b3cSEduard Zingerman 	w2 = 1;						\
218*8b365b3cSEduard Zingerman 	call %[bpf_trace_printk];			\
219*8b365b3cSEduard Zingerman 	r0 = 0;						\
220*8b365b3cSEduard Zingerman 	exit;						\
221*8b365b3cSEduard Zingerman "	:
222*8b365b3cSEduard Zingerman 	: __imm(bpf_trace_printk)
223*8b365b3cSEduard Zingerman 	: __clobber_all);
224*8b365b3cSEduard Zingerman }
225*8b365b3cSEduard Zingerman 
subprog_reads_arg_as_64bit(void)226*8b365b3cSEduard Zingerman static __used __naked int subprog_reads_arg_as_64bit(void)
227*8b365b3cSEduard Zingerman {
228*8b365b3cSEduard Zingerman 	asm volatile ("					\
229*8b365b3cSEduard Zingerman 	r0 = r1;					\
230*8b365b3cSEduard Zingerman 	exit;						\
231*8b365b3cSEduard Zingerman "	::: __clobber_all);
232*8b365b3cSEduard Zingerman }
233*8b365b3cSEduard Zingerman 
234*8b365b3cSEduard Zingerman /* subprogram parameters are conservatively read as 64-bit */
235*8b365b3cSEduard Zingerman SEC("socket")
236*8b365b3cSEduard Zingerman __success __log_level(2)
237*8b365b3cSEduard Zingerman __msg("w1 = w0{{ +}}; zext")
subprog_param_read_as_64bit(void)238*8b365b3cSEduard Zingerman __naked void subprog_param_read_as_64bit(void)
239*8b365b3cSEduard Zingerman {
240*8b365b3cSEduard Zingerman 	asm volatile ("					\
241*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
242*8b365b3cSEduard Zingerman 	w1 = w0;					\
243*8b365b3cSEduard Zingerman 	call subprog_reads_arg_as_64bit;		\
244*8b365b3cSEduard Zingerman 	r0 = 0;						\
245*8b365b3cSEduard Zingerman 	exit;						\
246*8b365b3cSEduard Zingerman "	:
247*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
248*8b365b3cSEduard Zingerman 	: __clobber_all);
249*8b365b3cSEduard Zingerman }
250*8b365b3cSEduard Zingerman 
251*8b365b3cSEduard Zingerman /* kfunc parameters are zero extended */
252*8b365b3cSEduard Zingerman SEC("tc")
253*8b365b3cSEduard Zingerman __success __log_level(2)
254*8b365b3cSEduard Zingerman __msg("w1 = 1{{ +}}; zext")
255*8b365b3cSEduard Zingerman __msg("w2 = 1{{ +}}; zext")
256*8b365b3cSEduard Zingerman __msg("w3 = 1{{ +}}; zext")
257*8b365b3cSEduard Zingerman __msg("w4 = 1{{ +}}; zext")
kfunc_param_read_per_btf(void)258*8b365b3cSEduard Zingerman __naked void kfunc_param_read_per_btf(void)
259*8b365b3cSEduard Zingerman {
260*8b365b3cSEduard Zingerman 	asm volatile ("					\
261*8b365b3cSEduard Zingerman 	w1 = 1;						\
262*8b365b3cSEduard Zingerman 	w2 = 1;						\
263*8b365b3cSEduard Zingerman 	w3 = 1;						\
264*8b365b3cSEduard Zingerman 	w4 = 1;						\
265*8b365b3cSEduard Zingerman 	call bpf_kfunc_call_test4;			\
266*8b365b3cSEduard Zingerman 	r0 = 0;						\
267*8b365b3cSEduard Zingerman 	exit;						\
268*8b365b3cSEduard Zingerman "	::: __clobber_all);
269*8b365b3cSEduard Zingerman }
270*8b365b3cSEduard Zingerman 
271*8b365b3cSEduard Zingerman SEC("socket")
272*8b365b3cSEduard Zingerman __success __log_level(2)
273*8b365b3cSEduard Zingerman __not_msg("; zext")
alu32_and_32bit_conditional(void)274*8b365b3cSEduard Zingerman __naked void alu32_and_32bit_conditional(void)
275*8b365b3cSEduard Zingerman {
276*8b365b3cSEduard Zingerman 	asm volatile ("					\
277*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
278*8b365b3cSEduard Zingerman 	w1 = w0;					\
279*8b365b3cSEduard Zingerman 	if w1 > 42 goto 1f;		/* BPF_K */	\
280*8b365b3cSEduard Zingerman 	w2 = 28;					\
281*8b365b3cSEduard Zingerman 	if w2 > w1 goto 1f;		/* BPF_X */	\
282*8b365b3cSEduard Zingerman 	r0 = 0;						\
283*8b365b3cSEduard Zingerman 1:	exit;						\
284*8b365b3cSEduard Zingerman "	:
285*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
286*8b365b3cSEduard Zingerman 	: __clobber_all);
287*8b365b3cSEduard Zingerman }
288*8b365b3cSEduard Zingerman 
289*8b365b3cSEduard Zingerman SEC("socket")
290*8b365b3cSEduard Zingerman __success __log_level(2)
291*8b365b3cSEduard Zingerman __msg("w1 = w0{{ +}}; zext")
alu32_and_64bit_conditional(void)292*8b365b3cSEduard Zingerman __naked void alu32_and_64bit_conditional(void)
293*8b365b3cSEduard Zingerman {
294*8b365b3cSEduard Zingerman 	asm volatile ("					\
295*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
296*8b365b3cSEduard Zingerman 	w1 = w0;					\
297*8b365b3cSEduard Zingerman 	if r1 > 42 goto 1f;		/* BPF_K */	\
298*8b365b3cSEduard Zingerman 	r2 = 28;					\
299*8b365b3cSEduard Zingerman 	if r2 > r1 goto 1f;		/* BPF_X */	\
300*8b365b3cSEduard Zingerman 	r0 = 0;						\
301*8b365b3cSEduard Zingerman 1:	exit;						\
302*8b365b3cSEduard Zingerman "	:
303*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
304*8b365b3cSEduard Zingerman 	: __clobber_all);
305*8b365b3cSEduard Zingerman }
306*8b365b3cSEduard Zingerman 
307*8b365b3cSEduard Zingerman SEC("socket")
308*8b365b3cSEduard Zingerman __success __log_level(2)
309*8b365b3cSEduard Zingerman __not_msg("; zext")
alu64_and_conditionals(void)310*8b365b3cSEduard Zingerman __naked void alu64_and_conditionals(void)
311*8b365b3cSEduard Zingerman {
312*8b365b3cSEduard Zingerman 	asm volatile ("					\
313*8b365b3cSEduard Zingerman 	call %[bpf_get_prandom_u32];			\
314*8b365b3cSEduard Zingerman 	r1 = r0;					\
315*8b365b3cSEduard Zingerman 	if w1 > 42 goto 1f;		/* BPF_K */	\
316*8b365b3cSEduard Zingerman 	if r1 > 42 goto 1f;		/* BPF_K */	\
317*8b365b3cSEduard Zingerman 	r2 = 28;					\
318*8b365b3cSEduard Zingerman 	if w2 > w1 goto 1f;		/* BPF_X */	\
319*8b365b3cSEduard Zingerman 	if r2 > r1 goto 1f;		/* BPF_X */	\
320*8b365b3cSEduard Zingerman 	r0 = 0;						\
321*8b365b3cSEduard Zingerman 1:	exit;						\
322*8b365b3cSEduard Zingerman "	:
323*8b365b3cSEduard Zingerman 	: __imm(bpf_get_prandom_u32)
324*8b365b3cSEduard Zingerman 	: __clobber_all);
325*8b365b3cSEduard Zingerman }
326*8b365b3cSEduard Zingerman 
327*8b365b3cSEduard Zingerman #ifdef __BPF_FEATURE_ADDR_SPACE_CAST
328*8b365b3cSEduard Zingerman 
329*8b365b3cSEduard Zingerman SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
330*8b365b3cSEduard Zingerman __arch_s390x
331*8b365b3cSEduard Zingerman __xlated("7: w1 = w0")
332*8b365b3cSEduard Zingerman __xlated("8: w1 = w1")
333*8b365b3cSEduard Zingerman __xlated("9: w1 += 8")
334*8b365b3cSEduard Zingerman __xlated("10: w1 = w1")
335*8b365b3cSEduard Zingerman __xlated("11: w2 = w1")
336*8b365b3cSEduard Zingerman __xlated("12: w2 = w2")
337*8b365b3cSEduard Zingerman __xlated("13: *(u64 *)(r1 +0) = r2")
arena_ptr(void)338*8b365b3cSEduard Zingerman __naked void arena_ptr(void)
339*8b365b3cSEduard Zingerman {
340*8b365b3cSEduard Zingerman 	asm volatile ("					\
341*8b365b3cSEduard Zingerman 	r1 = %[arena] ll;				\
342*8b365b3cSEduard Zingerman 	r2 = 0;						\
343*8b365b3cSEduard Zingerman 	r3 = 1;						\
344*8b365b3cSEduard Zingerman 	r4 = 0;						\
345*8b365b3cSEduard Zingerman 	r5 = 0;						\
346*8b365b3cSEduard Zingerman 	call %[bpf_arena_alloc_pages];			\
347*8b365b3cSEduard Zingerman 	r1 = addr_space_cast(r0, 0, 1);		/* needs zext */ \
348*8b365b3cSEduard Zingerman 	r1 += 8;				/* needs zext */ \
349*8b365b3cSEduard Zingerman 	r2 = addr_space_cast(r1, 1, 0);		/* needs zext because of BPF_F_NO_USER_CONV */ \
350*8b365b3cSEduard Zingerman 	*(u64 *)(r1 +0) = r2;				\
351*8b365b3cSEduard Zingerman 	r0 = 0;						\
352*8b365b3cSEduard Zingerman 	exit;						\
353*8b365b3cSEduard Zingerman "	:
354*8b365b3cSEduard Zingerman 	: __imm(bpf_arena_alloc_pages),
355*8b365b3cSEduard Zingerman 	  __imm_addr(arena)
356*8b365b3cSEduard Zingerman 	: __clobber_all);
357*8b365b3cSEduard Zingerman }
358*8b365b3cSEduard Zingerman 
359*8b365b3cSEduard Zingerman #endif
360*8b365b3cSEduard Zingerman 
361*8b365b3cSEduard Zingerman /* Check if probe mem loads keep their zero extension. */
362*8b365b3cSEduard Zingerman SEC("socket")
363*8b365b3cSEduard Zingerman __success __log_level(2)
364*8b365b3cSEduard Zingerman __arch_s390x
365*8b365b3cSEduard Zingerman __xlated("3: r1 = *(u64 *)(r0 +0)")
366*8b365b3cSEduard Zingerman __xlated("4: r2 = *(u32 *)(r0 +0)")
367*8b365b3cSEduard Zingerman __xlated("5: w2 = w2")
368*8b365b3cSEduard Zingerman __xlated("6: r3 = *(u16 *)(r0 +0)")
369*8b365b3cSEduard Zingerman __xlated("7: w3 = w3")
370*8b365b3cSEduard Zingerman __xlated("8: r4 = *(u8 *)(r0 +0)")
371*8b365b3cSEduard Zingerman __xlated("9: w4 = w4")
probe_mem(void)372*8b365b3cSEduard Zingerman __naked void probe_mem(void)
373*8b365b3cSEduard Zingerman {
374*8b365b3cSEduard Zingerman 	asm volatile ("					\
375*8b365b3cSEduard Zingerman 	r1 = 0;						\
376*8b365b3cSEduard Zingerman 	r2 = 0;						\
377*8b365b3cSEduard Zingerman 	call %[bpf_rdonly_cast];			\
378*8b365b3cSEduard Zingerman 	r1 = *(u64 *)(r0 + 0);	/* BPF_PROBE_MEM */	\
379*8b365b3cSEduard Zingerman 	r2 = *(u32 *)(r0 + 0);	/* BPF_PROBE_MEM */	\
380*8b365b3cSEduard Zingerman 	r3 = *(u16 *)(r0 + 0);	/* BPF_PROBE_MEM */	\
381*8b365b3cSEduard Zingerman 	r4 = *(u8 *)(r0 + 0);	/* BPF_PROBE_MEM */	\
382*8b365b3cSEduard Zingerman 	r0 = r1;		/* make the registers used */ \
383*8b365b3cSEduard Zingerman 	r0 += r2;					\
384*8b365b3cSEduard Zingerman 	r0 += r3;					\
385*8b365b3cSEduard Zingerman 	r0 += r4;					\
386*8b365b3cSEduard Zingerman 1:	exit;						\
387*8b365b3cSEduard Zingerman "	:
388*8b365b3cSEduard Zingerman 	: __imm(bpf_rdonly_cast)
389*8b365b3cSEduard Zingerman 	: __clobber_all);
390*8b365b3cSEduard Zingerman }
391*8b365b3cSEduard Zingerman 
392*8b365b3cSEduard Zingerman char _license[] SEC("license") = "GPL";
393