1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/bpf.h>
4#include <bpf/bpf_helpers.h>
5#include "bpf_misc.h"
6
7#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
8     (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && __clang_major__ >= 18
9
10SEC("socket")
11__description("LDSX, S8")
12__success __success_unpriv __retval(-2)
13__naked void ldsx_s8(void)
14{
15	asm volatile ("					\
16	r1 = 0x3fe;					\
17	*(u64 *)(r10 - 8) = r1;				\
18	r0 = *(s8 *)(r10 - 8);				\
19	exit;						\
20"	::: __clobber_all);
21}
22
23SEC("socket")
24__description("LDSX, S16")
25__success __success_unpriv __retval(-2)
26__naked void ldsx_s16(void)
27{
28	asm volatile ("					\
29	r1 = 0x3fffe;					\
30	*(u64 *)(r10 - 8) = r1;				\
31	r0 = *(s16 *)(r10 - 8);				\
32	exit;						\
33"	::: __clobber_all);
34}
35
36SEC("socket")
37__description("LDSX, S32")
38__success __success_unpriv __retval(-1)
39__naked void ldsx_s32(void)
40{
41	asm volatile ("					\
42	r1 = 0xfffffffe;				\
43	*(u64 *)(r10 - 8) = r1;				\
44	r0 = *(s32 *)(r10 - 8);				\
45	r0 >>= 1;					\
46	exit;						\
47"	::: __clobber_all);
48}
49
50SEC("socket")
51__description("LDSX, S8 range checking, privileged")
52__log_level(2) __success __retval(1)
53__msg("R1_w=scalar(smin=-128,smax=127)")
54__naked void ldsx_s8_range_priv(void)
55{
56	asm volatile ("					\
57	call %[bpf_get_prandom_u32];			\
58	*(u64 *)(r10 - 8) = r0;				\
59	r1 = *(s8 *)(r10 - 8);				\
60	/* r1 with s8 range */				\
61	if r1 s> 0x7f goto l0_%=;			\
62	if r1 s< -0x80 goto l0_%=;			\
63	r0 = 1;						\
64l1_%=:							\
65	exit;						\
66l0_%=:							\
67	r0 = 2;						\
68	goto l1_%=;					\
69"	:
70	: __imm(bpf_get_prandom_u32)
71	: __clobber_all);
72}
73
74SEC("socket")
75__description("LDSX, S16 range checking")
76__success __success_unpriv __retval(1)
77__naked void ldsx_s16_range(void)
78{
79	asm volatile ("					\
80	call %[bpf_get_prandom_u32];			\
81	*(u64 *)(r10 - 8) = r0;				\
82	r1 = *(s16 *)(r10 - 8);				\
83	/* r1 with s16 range */				\
84	if r1 s> 0x7fff goto l0_%=;			\
85	if r1 s< -0x8000 goto l0_%=;			\
86	r0 = 1;						\
87l1_%=:							\
88	exit;						\
89l0_%=:							\
90	r0 = 2;						\
91	goto l1_%=;					\
92"	:
93	: __imm(bpf_get_prandom_u32)
94	: __clobber_all);
95}
96
97SEC("socket")
98__description("LDSX, S32 range checking")
99__success __success_unpriv __retval(1)
100__naked void ldsx_s32_range(void)
101{
102	asm volatile ("					\
103	call %[bpf_get_prandom_u32];			\
104	*(u64 *)(r10 - 8) = r0;				\
105	r1 = *(s32 *)(r10 - 8);				\
106	/* r1 with s16 range */				\
107	if r1 s> 0x7fffFFFF goto l0_%=;			\
108	if r1 s< -0x80000000 goto l0_%=;		\
109	r0 = 1;						\
110l1_%=:							\
111	exit;						\
112l0_%=:							\
113	r0 = 2;						\
114	goto l1_%=;					\
115"	:
116	: __imm(bpf_get_prandom_u32)
117	: __clobber_all);
118}
119
120#else
121
122SEC("socket")
123__description("cpuv4 is not supported by compiler or jit, use a dummy test")
124__success
125int dummy_test(void)
126{
127	return 0;
128}
129
130#endif
131
132char _license[] SEC("license") = "GPL";
133