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 
10 SEC("socket")
11 __description("LDSX, S8")
12 __success __success_unpriv __retval(-2)
ldsx_s8(void)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 
23 SEC("socket")
24 __description("LDSX, S16")
25 __success __success_unpriv __retval(-2)
ldsx_s16(void)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 
36 SEC("socket")
37 __description("LDSX, S32")
38 __success __success_unpriv __retval(-1)
ldsx_s32(void)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 
50 SEC("socket")
51 __description("LDSX, S8 range checking, privileged")
52 __log_level(2) __success __retval(1)
53 __msg("R1_w=scalar(smin=-128,smax=127)")
ldsx_s8_range_priv(void)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;						\
64 l1_%=:							\
65 	exit;						\
66 l0_%=:							\
67 	r0 = 2;						\
68 	goto l1_%=;					\
69 "	:
70 	: __imm(bpf_get_prandom_u32)
71 	: __clobber_all);
72 }
73 
74 SEC("socket")
75 __description("LDSX, S16 range checking")
76 __success __success_unpriv __retval(1)
ldsx_s16_range(void)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;						\
87 l1_%=:							\
88 	exit;						\
89 l0_%=:							\
90 	r0 = 2;						\
91 	goto l1_%=;					\
92 "	:
93 	: __imm(bpf_get_prandom_u32)
94 	: __clobber_all);
95 }
96 
97 SEC("socket")
98 __description("LDSX, S32 range checking")
99 __success __success_unpriv __retval(1)
ldsx_s32_range(void)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;						\
110 l1_%=:							\
111 	exit;						\
112 l0_%=:							\
113 	r0 = 2;						\
114 	goto l1_%=;					\
115 "	:
116 	: __imm(bpf_get_prandom_u32)
117 	: __clobber_all);
118 }
119 
120 #else
121 
122 SEC("socket")
123 __description("cpuv4 is not supported by compiler or jit, use a dummy test")
124 __success
dummy_test(void)125 int dummy_test(void)
126 {
127 	return 0;
128 }
129 
130 #endif
131 
132 char _license[] SEC("license") = "GPL";
133