1f02ec3ffSYonghong Song // SPDX-License-Identifier: GPL-2.0
2f02ec3ffSYonghong Song 
3f02ec3ffSYonghong Song #include <linux/bpf.h>
4f02ec3ffSYonghong Song #include <bpf/bpf_helpers.h>
5f02ec3ffSYonghong Song #include "bpf_misc.h"
6f02ec3ffSYonghong Song 
7*0209fd51SPu Lehui #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
8*0209fd51SPu Lehui      (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && __clang_major__ >= 18
9f02ec3ffSYonghong Song 
10f02ec3ffSYonghong Song SEC("socket")
11f02ec3ffSYonghong Song __description("MOV32SX, S8")
12f02ec3ffSYonghong Song __success __success_unpriv __retval(0x23)
mov32sx_s8(void)13f02ec3ffSYonghong Song __naked void mov32sx_s8(void)
14f02ec3ffSYonghong Song {
15f02ec3ffSYonghong Song 	asm volatile ("					\
16f02ec3ffSYonghong Song 	w0 = 0xff23;					\
17f02ec3ffSYonghong Song 	w0 = (s8)w0;					\
18f02ec3ffSYonghong Song 	exit;						\
19f02ec3ffSYonghong Song "	::: __clobber_all);
20f02ec3ffSYonghong Song }
21f02ec3ffSYonghong Song 
22f02ec3ffSYonghong Song SEC("socket")
23f02ec3ffSYonghong Song __description("MOV32SX, S16")
24f02ec3ffSYonghong Song __success __success_unpriv __retval(0xFFFFff23)
mov32sx_s16(void)25f02ec3ffSYonghong Song __naked void mov32sx_s16(void)
26f02ec3ffSYonghong Song {
27f02ec3ffSYonghong Song 	asm volatile ("					\
28f02ec3ffSYonghong Song 	w0 = 0xff23;					\
29f02ec3ffSYonghong Song 	w0 = (s16)w0;					\
30f02ec3ffSYonghong Song 	exit;						\
31f02ec3ffSYonghong Song "	::: __clobber_all);
32f02ec3ffSYonghong Song }
33f02ec3ffSYonghong Song 
34f02ec3ffSYonghong Song SEC("socket")
35f02ec3ffSYonghong Song __description("MOV64SX, S8")
36f02ec3ffSYonghong Song __success __success_unpriv __retval(-2)
mov64sx_s8(void)37f02ec3ffSYonghong Song __naked void mov64sx_s8(void)
38f02ec3ffSYonghong Song {
39f02ec3ffSYonghong Song 	asm volatile ("					\
40f02ec3ffSYonghong Song 	r0 = 0x1fe;					\
41f02ec3ffSYonghong Song 	r0 = (s8)r0;					\
42f02ec3ffSYonghong Song 	exit;						\
43f02ec3ffSYonghong Song "	::: __clobber_all);
44f02ec3ffSYonghong Song }
45f02ec3ffSYonghong Song 
46f02ec3ffSYonghong Song SEC("socket")
47f02ec3ffSYonghong Song __description("MOV64SX, S16")
48f02ec3ffSYonghong Song __success __success_unpriv __retval(0xf23)
mov64sx_s16(void)49f02ec3ffSYonghong Song __naked void mov64sx_s16(void)
50f02ec3ffSYonghong Song {
51f02ec3ffSYonghong Song 	asm volatile ("					\
52f02ec3ffSYonghong Song 	r0 = 0xf0f23;					\
53f02ec3ffSYonghong Song 	r0 = (s16)r0;					\
54f02ec3ffSYonghong Song 	exit;						\
55f02ec3ffSYonghong Song "	::: __clobber_all);
56f02ec3ffSYonghong Song }
57f02ec3ffSYonghong Song 
58f02ec3ffSYonghong Song SEC("socket")
59f02ec3ffSYonghong Song __description("MOV64SX, S32")
60f02ec3ffSYonghong Song __success __success_unpriv __retval(-1)
mov64sx_s32(void)61f02ec3ffSYonghong Song __naked void mov64sx_s32(void)
62f02ec3ffSYonghong Song {
63f02ec3ffSYonghong Song 	asm volatile ("					\
64f02ec3ffSYonghong Song 	r0 = 0xfffffffe;				\
65f02ec3ffSYonghong Song 	r0 = (s32)r0;					\
66f02ec3ffSYonghong Song 	r0 >>= 1;					\
67f02ec3ffSYonghong Song 	exit;						\
68f02ec3ffSYonghong Song "	::: __clobber_all);
69f02ec3ffSYonghong Song }
70f02ec3ffSYonghong Song 
71f02ec3ffSYonghong Song SEC("socket")
72f02ec3ffSYonghong Song __description("MOV32SX, S8, range_check")
73f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov32sx_s8_range(void)74f02ec3ffSYonghong Song __naked void mov32sx_s8_range(void)
75f02ec3ffSYonghong Song {
76f02ec3ffSYonghong Song 	asm volatile ("					\
77f02ec3ffSYonghong Song 	call %[bpf_get_prandom_u32];			\
78f02ec3ffSYonghong Song 	w1 = (s8)w0;					\
79f02ec3ffSYonghong Song 	/* w1 with s8 range */				\
80f02ec3ffSYonghong Song 	if w1 s> 0x7f goto l0_%=;			\
81f02ec3ffSYonghong Song 	if w1 s< -0x80 goto l0_%=;			\
82f02ec3ffSYonghong Song 	r0 = 1;						\
83f02ec3ffSYonghong Song l1_%=:							\
84f02ec3ffSYonghong Song 	exit;						\
85f02ec3ffSYonghong Song l0_%=:							\
86f02ec3ffSYonghong Song 	r0 = 2;						\
87f02ec3ffSYonghong Song 	goto l1_%=;					\
88f02ec3ffSYonghong Song "	:
89f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
90f02ec3ffSYonghong Song 	: __clobber_all);
91f02ec3ffSYonghong Song }
92f02ec3ffSYonghong Song 
93f02ec3ffSYonghong Song SEC("socket")
94f02ec3ffSYonghong Song __description("MOV32SX, S16, range_check")
95f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov32sx_s16_range(void)96f02ec3ffSYonghong Song __naked void mov32sx_s16_range(void)
97f02ec3ffSYonghong Song {
98f02ec3ffSYonghong Song 	asm volatile ("					\
99f02ec3ffSYonghong Song 	call %[bpf_get_prandom_u32];			\
100f02ec3ffSYonghong Song 	w1 = (s16)w0;					\
101f02ec3ffSYonghong Song 	/* w1 with s16 range */				\
102f02ec3ffSYonghong Song 	if w1 s> 0x7fff goto l0_%=;			\
103f02ec3ffSYonghong Song 	if w1 s< -0x80ff goto l0_%=;			\
104f02ec3ffSYonghong Song 	r0 = 1;						\
105f02ec3ffSYonghong Song l1_%=:							\
106f02ec3ffSYonghong Song 	exit;						\
107f02ec3ffSYonghong Song l0_%=:							\
108f02ec3ffSYonghong Song 	r0 = 2;						\
109f02ec3ffSYonghong Song 	goto l1_%=;					\
110f02ec3ffSYonghong Song "	:
111f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
112f02ec3ffSYonghong Song 	: __clobber_all);
113f02ec3ffSYonghong Song }
114f02ec3ffSYonghong Song 
115f02ec3ffSYonghong Song SEC("socket")
116f02ec3ffSYonghong Song __description("MOV32SX, S16, range_check 2")
117f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov32sx_s16_range_2(void)118f02ec3ffSYonghong Song __naked void mov32sx_s16_range_2(void)
119f02ec3ffSYonghong Song {
120f02ec3ffSYonghong Song 	asm volatile ("					\
121f02ec3ffSYonghong Song 	r1 = 65535;					\
122f02ec3ffSYonghong Song 	w2 = (s16)w1;					\
123f02ec3ffSYonghong Song 	r2 >>= 1;					\
124f02ec3ffSYonghong Song 	if r2 != 0x7fffFFFF goto l0_%=;			\
125f02ec3ffSYonghong Song 	r0 = 1;						\
126f02ec3ffSYonghong Song l1_%=:							\
127f02ec3ffSYonghong Song 	exit;						\
128f02ec3ffSYonghong Song l0_%=:							\
129f02ec3ffSYonghong Song 	r0 = 0;						\
130f02ec3ffSYonghong Song 	goto l1_%=;					\
131f02ec3ffSYonghong Song "	:
132f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
133f02ec3ffSYonghong Song 	: __clobber_all);
134f02ec3ffSYonghong Song }
135f02ec3ffSYonghong Song 
136f02ec3ffSYonghong Song SEC("socket")
137f02ec3ffSYonghong Song __description("MOV64SX, S8, range_check")
138f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov64sx_s8_range(void)139f02ec3ffSYonghong Song __naked void mov64sx_s8_range(void)
140f02ec3ffSYonghong Song {
141f02ec3ffSYonghong Song 	asm volatile ("					\
142f02ec3ffSYonghong Song 	call %[bpf_get_prandom_u32];			\
143f02ec3ffSYonghong Song 	r1 = (s8)r0;					\
144f02ec3ffSYonghong Song 	/* r1 with s8 range */				\
145f02ec3ffSYonghong Song 	if r1 s> 0x7f goto l0_%=;			\
146f02ec3ffSYonghong Song 	if r1 s< -0x80 goto l0_%=;			\
147f02ec3ffSYonghong Song 	r0 = 1;						\
148f02ec3ffSYonghong Song l1_%=:							\
149f02ec3ffSYonghong Song 	exit;						\
150f02ec3ffSYonghong Song l0_%=:							\
151f02ec3ffSYonghong Song 	r0 = 2;						\
152f02ec3ffSYonghong Song 	goto l1_%=;					\
153f02ec3ffSYonghong Song "	:
154f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
155f02ec3ffSYonghong Song 	: __clobber_all);
156f02ec3ffSYonghong Song }
157f02ec3ffSYonghong Song 
158f02ec3ffSYonghong Song SEC("socket")
159f02ec3ffSYonghong Song __description("MOV64SX, S16, range_check")
160f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov64sx_s16_range(void)161f02ec3ffSYonghong Song __naked void mov64sx_s16_range(void)
162f02ec3ffSYonghong Song {
163f02ec3ffSYonghong Song 	asm volatile ("					\
164f02ec3ffSYonghong Song 	call %[bpf_get_prandom_u32];			\
165f02ec3ffSYonghong Song 	r1 = (s16)r0;					\
166f02ec3ffSYonghong Song 	/* r1 with s16 range */				\
167f02ec3ffSYonghong Song 	if r1 s> 0x7fff goto l0_%=;			\
168f02ec3ffSYonghong Song 	if r1 s< -0x8000 goto l0_%=;			\
169f02ec3ffSYonghong Song 	r0 = 1;						\
170f02ec3ffSYonghong Song l1_%=:							\
171f02ec3ffSYonghong Song 	exit;						\
172f02ec3ffSYonghong Song l0_%=:							\
173f02ec3ffSYonghong Song 	r0 = 2;						\
174f02ec3ffSYonghong Song 	goto l1_%=;					\
175f02ec3ffSYonghong Song "	:
176f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
177f02ec3ffSYonghong Song 	: __clobber_all);
178f02ec3ffSYonghong Song }
179f02ec3ffSYonghong Song 
180f02ec3ffSYonghong Song SEC("socket")
181f02ec3ffSYonghong Song __description("MOV64SX, S32, range_check")
182f02ec3ffSYonghong Song __success __success_unpriv __retval(1)
mov64sx_s32_range(void)183f02ec3ffSYonghong Song __naked void mov64sx_s32_range(void)
184f02ec3ffSYonghong Song {
185f02ec3ffSYonghong Song 	asm volatile ("					\
186f02ec3ffSYonghong Song 	call %[bpf_get_prandom_u32];			\
187f02ec3ffSYonghong Song 	r1 = (s32)r0;					\
188f02ec3ffSYonghong Song 	/* r1 with s32 range */				\
189f02ec3ffSYonghong Song 	if r1 s> 0x7fffffff goto l0_%=;			\
190f02ec3ffSYonghong Song 	if r1 s< -0x80000000 goto l0_%=;		\
191f02ec3ffSYonghong Song 	r0 = 1;						\
192f02ec3ffSYonghong Song l1_%=:							\
193f02ec3ffSYonghong Song 	exit;						\
194f02ec3ffSYonghong Song l0_%=:							\
195f02ec3ffSYonghong Song 	r0 = 2;						\
196f02ec3ffSYonghong Song 	goto l1_%=;					\
197f02ec3ffSYonghong Song "	:
198f02ec3ffSYonghong Song 	: __imm(bpf_get_prandom_u32)
199f02ec3ffSYonghong Song 	: __clobber_all);
200f02ec3ffSYonghong Song }
201f02ec3ffSYonghong Song 
202a5c0a42bSYonghong Song SEC("socket")
203a5c0a42bSYonghong Song __description("MOV64SX, S16, R10 Sign Extension")
204a5c0a42bSYonghong Song __failure __msg("R1 type=scalar expected=fp, pkt, pkt_meta, map_key, map_value, mem, ringbuf_mem, buf, trusted_ptr_")
205a5c0a42bSYonghong Song __failure_unpriv __msg_unpriv("R10 sign-extension part of pointer")
mov64sx_s16_r10(void)206a5c0a42bSYonghong Song __naked void mov64sx_s16_r10(void)
207a5c0a42bSYonghong Song {
208a5c0a42bSYonghong Song 	asm volatile ("					\
209a5c0a42bSYonghong Song 	r1 = 553656332;					\
210a5c0a42bSYonghong Song 	*(u32 *)(r10 - 8) = r1; 			\
211a5c0a42bSYonghong Song 	r1 = (s16)r10;					\
212a5c0a42bSYonghong Song 	r1 += -8;					\
213a5c0a42bSYonghong Song 	r2 = 3;						\
214a5c0a42bSYonghong Song 	if r2 <= r1 goto l0_%=;				\
215a5c0a42bSYonghong Song l0_%=:							\
216a5c0a42bSYonghong Song 	call %[bpf_trace_printk];			\
217a5c0a42bSYonghong Song 	r0 = 0;						\
218a5c0a42bSYonghong Song 	exit;						\
219a5c0a42bSYonghong Song "	:
220a5c0a42bSYonghong Song 	: __imm(bpf_trace_printk)
221a5c0a42bSYonghong Song 	: __clobber_all);
222a5c0a42bSYonghong Song }
223a5c0a42bSYonghong Song 
224f02ec3ffSYonghong Song #else
225f02ec3ffSYonghong Song 
226f02ec3ffSYonghong Song SEC("socket")
227f02ec3ffSYonghong Song __description("cpuv4 is not supported by compiler or jit, use a dummy test")
228f02ec3ffSYonghong Song __success
dummy_test(void)229f02ec3ffSYonghong Song int dummy_test(void)
230f02ec3ffSYonghong Song {
231f02ec3ffSYonghong Song 	return 0;
232f02ec3ffSYonghong Song }
233f02ec3ffSYonghong Song 
234f02ec3ffSYonghong Song #endif
235f02ec3ffSYonghong Song 
236f02ec3ffSYonghong Song char _license[] SEC("license") = "GPL";
237