18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "bpf_jit_32.h"
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#define SAVE_SZ		96
78c2ecf20Sopenharmony_ci#define SCRATCH_OFF	72
88c2ecf20Sopenharmony_ci#define BE_PTR(label)	be label
98c2ecf20Sopenharmony_ci#define SIGN_EXTEND(reg)
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define SKF_MAX_NEG_OFF	(-0x200000) /* SKF_LL_OFF from filter.h */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	.text
148c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_word
158c2ecf20Sopenharmony_cibpf_jit_load_word:
168c2ecf20Sopenharmony_ci	cmp	r_OFF, 0
178c2ecf20Sopenharmony_ci	bl	bpf_slow_path_word_neg
188c2ecf20Sopenharmony_ci	 nop
198c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_word_positive_offset
208c2ecf20Sopenharmony_cibpf_jit_load_word_positive_offset:
218c2ecf20Sopenharmony_ci	sub	r_HEADLEN, r_OFF, r_TMP
228c2ecf20Sopenharmony_ci	cmp	r_TMP, 3
238c2ecf20Sopenharmony_ci	ble	bpf_slow_path_word
248c2ecf20Sopenharmony_ci	 add	r_SKB_DATA, r_OFF, r_TMP
258c2ecf20Sopenharmony_ci	andcc	r_TMP, 3, %g0
268c2ecf20Sopenharmony_ci	bne	load_word_unaligned
278c2ecf20Sopenharmony_ci	 nop
288c2ecf20Sopenharmony_ci	retl
298c2ecf20Sopenharmony_ci	 ld	[r_TMP], r_A
308c2ecf20Sopenharmony_ciload_word_unaligned:
318c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x0], r_OFF
328c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x1], r_TMP2
338c2ecf20Sopenharmony_ci	sll	r_OFF, 8, r_OFF
348c2ecf20Sopenharmony_ci	or	r_OFF, r_TMP2, r_OFF
358c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x2], r_TMP2
368c2ecf20Sopenharmony_ci	sll	r_OFF, 8, r_OFF
378c2ecf20Sopenharmony_ci	or	r_OFF, r_TMP2, r_OFF
388c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x3], r_TMP2
398c2ecf20Sopenharmony_ci	sll	r_OFF, 8, r_OFF
408c2ecf20Sopenharmony_ci	retl
418c2ecf20Sopenharmony_ci	 or	r_OFF, r_TMP2, r_A
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_half
448c2ecf20Sopenharmony_cibpf_jit_load_half:
458c2ecf20Sopenharmony_ci	cmp	r_OFF, 0
468c2ecf20Sopenharmony_ci	bl	bpf_slow_path_half_neg
478c2ecf20Sopenharmony_ci	 nop
488c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_half_positive_offset
498c2ecf20Sopenharmony_cibpf_jit_load_half_positive_offset:
508c2ecf20Sopenharmony_ci	sub	r_HEADLEN, r_OFF, r_TMP
518c2ecf20Sopenharmony_ci	cmp	r_TMP, 1
528c2ecf20Sopenharmony_ci	ble	bpf_slow_path_half
538c2ecf20Sopenharmony_ci	 add	r_SKB_DATA, r_OFF, r_TMP
548c2ecf20Sopenharmony_ci	andcc	r_TMP, 1, %g0
558c2ecf20Sopenharmony_ci	bne	load_half_unaligned
568c2ecf20Sopenharmony_ci	 nop
578c2ecf20Sopenharmony_ci	retl
588c2ecf20Sopenharmony_ci	 lduh	[r_TMP], r_A
598c2ecf20Sopenharmony_ciload_half_unaligned:
608c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x0], r_OFF
618c2ecf20Sopenharmony_ci	ldub	[r_TMP + 0x1], r_TMP2
628c2ecf20Sopenharmony_ci	sll	r_OFF, 8, r_OFF
638c2ecf20Sopenharmony_ci	retl
648c2ecf20Sopenharmony_ci	 or	r_OFF, r_TMP2, r_A
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte
678c2ecf20Sopenharmony_cibpf_jit_load_byte:
688c2ecf20Sopenharmony_ci	cmp	r_OFF, 0
698c2ecf20Sopenharmony_ci	bl	bpf_slow_path_byte_neg
708c2ecf20Sopenharmony_ci	 nop
718c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte_positive_offset
728c2ecf20Sopenharmony_cibpf_jit_load_byte_positive_offset:
738c2ecf20Sopenharmony_ci	cmp	r_OFF, r_HEADLEN
748c2ecf20Sopenharmony_ci	bge	bpf_slow_path_byte
758c2ecf20Sopenharmony_ci	 nop
768c2ecf20Sopenharmony_ci	retl
778c2ecf20Sopenharmony_ci	 ldub	[r_SKB_DATA + r_OFF], r_A
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte_msh
808c2ecf20Sopenharmony_cibpf_jit_load_byte_msh:
818c2ecf20Sopenharmony_ci	cmp	r_OFF, 0
828c2ecf20Sopenharmony_ci	bl	bpf_slow_path_byte_msh_neg
838c2ecf20Sopenharmony_ci	 nop
848c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte_msh_positive_offset
858c2ecf20Sopenharmony_cibpf_jit_load_byte_msh_positive_offset:
868c2ecf20Sopenharmony_ci	cmp	r_OFF, r_HEADLEN
878c2ecf20Sopenharmony_ci	bge	bpf_slow_path_byte_msh
888c2ecf20Sopenharmony_ci	 nop
898c2ecf20Sopenharmony_ci	ldub	[r_SKB_DATA + r_OFF], r_OFF
908c2ecf20Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
918c2ecf20Sopenharmony_ci	retl
928c2ecf20Sopenharmony_ci	 sll	r_OFF, 2, r_X
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define bpf_slow_path_common(LEN)	\
958c2ecf20Sopenharmony_ci	save	%sp, -SAVE_SZ, %sp;	\
968c2ecf20Sopenharmony_ci	mov	%i0, %o0;		\
978c2ecf20Sopenharmony_ci	mov	r_OFF, %o1;		\
988c2ecf20Sopenharmony_ci	add	%fp, SCRATCH_OFF, %o2;	\
998c2ecf20Sopenharmony_ci	call	skb_copy_bits;		\
1008c2ecf20Sopenharmony_ci	 mov	(LEN), %o3;		\
1018c2ecf20Sopenharmony_ci	cmp	%o0, 0;			\
1028c2ecf20Sopenharmony_ci	restore;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cibpf_slow_path_word:
1058c2ecf20Sopenharmony_ci	bpf_slow_path_common(4)
1068c2ecf20Sopenharmony_ci	bl	bpf_error
1078c2ecf20Sopenharmony_ci	 ld	[%sp + SCRATCH_OFF], r_A
1088c2ecf20Sopenharmony_ci	retl
1098c2ecf20Sopenharmony_ci	 nop
1108c2ecf20Sopenharmony_cibpf_slow_path_half:
1118c2ecf20Sopenharmony_ci	bpf_slow_path_common(2)
1128c2ecf20Sopenharmony_ci	bl	bpf_error
1138c2ecf20Sopenharmony_ci	 lduh	[%sp + SCRATCH_OFF], r_A
1148c2ecf20Sopenharmony_ci	retl
1158c2ecf20Sopenharmony_ci	 nop
1168c2ecf20Sopenharmony_cibpf_slow_path_byte:
1178c2ecf20Sopenharmony_ci	bpf_slow_path_common(1)
1188c2ecf20Sopenharmony_ci	bl	bpf_error
1198c2ecf20Sopenharmony_ci	 ldub	[%sp + SCRATCH_OFF], r_A
1208c2ecf20Sopenharmony_ci	retl
1218c2ecf20Sopenharmony_ci	 nop
1228c2ecf20Sopenharmony_cibpf_slow_path_byte_msh:
1238c2ecf20Sopenharmony_ci	bpf_slow_path_common(1)
1248c2ecf20Sopenharmony_ci	bl	bpf_error
1258c2ecf20Sopenharmony_ci	 ldub	[%sp + SCRATCH_OFF], r_A
1268c2ecf20Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
1278c2ecf20Sopenharmony_ci	retl
1288c2ecf20Sopenharmony_ci	 sll	r_OFF, 2, r_X
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci#define bpf_negative_common(LEN)			\
1318c2ecf20Sopenharmony_ci	save	%sp, -SAVE_SZ, %sp;			\
1328c2ecf20Sopenharmony_ci	mov	%i0, %o0;				\
1338c2ecf20Sopenharmony_ci	mov	r_OFF, %o1;				\
1348c2ecf20Sopenharmony_ci	SIGN_EXTEND(%o1);				\
1358c2ecf20Sopenharmony_ci	call	bpf_internal_load_pointer_neg_helper;	\
1368c2ecf20Sopenharmony_ci	 mov	(LEN), %o2;				\
1378c2ecf20Sopenharmony_ci	mov	%o0, r_TMP;				\
1388c2ecf20Sopenharmony_ci	cmp	%o0, 0;					\
1398c2ecf20Sopenharmony_ci	BE_PTR(bpf_error);				\
1408c2ecf20Sopenharmony_ci	 restore;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cibpf_slow_path_word_neg:
1438c2ecf20Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
1448c2ecf20Sopenharmony_ci	cmp	r_OFF, r_TMP
1458c2ecf20Sopenharmony_ci	bl	bpf_error
1468c2ecf20Sopenharmony_ci	 nop
1478c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_word_negative_offset
1488c2ecf20Sopenharmony_cibpf_jit_load_word_negative_offset:
1498c2ecf20Sopenharmony_ci	bpf_negative_common(4)
1508c2ecf20Sopenharmony_ci	andcc	r_TMP, 3, %g0
1518c2ecf20Sopenharmony_ci	bne	load_word_unaligned
1528c2ecf20Sopenharmony_ci	 nop
1538c2ecf20Sopenharmony_ci	retl
1548c2ecf20Sopenharmony_ci	 ld	[r_TMP], r_A
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cibpf_slow_path_half_neg:
1578c2ecf20Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
1588c2ecf20Sopenharmony_ci	cmp	r_OFF, r_TMP
1598c2ecf20Sopenharmony_ci	bl	bpf_error
1608c2ecf20Sopenharmony_ci	 nop
1618c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_half_negative_offset
1628c2ecf20Sopenharmony_cibpf_jit_load_half_negative_offset:
1638c2ecf20Sopenharmony_ci	bpf_negative_common(2)
1648c2ecf20Sopenharmony_ci	andcc	r_TMP, 1, %g0
1658c2ecf20Sopenharmony_ci	bne	load_half_unaligned
1668c2ecf20Sopenharmony_ci	 nop
1678c2ecf20Sopenharmony_ci	retl
1688c2ecf20Sopenharmony_ci	 lduh	[r_TMP], r_A
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cibpf_slow_path_byte_neg:
1718c2ecf20Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
1728c2ecf20Sopenharmony_ci	cmp	r_OFF, r_TMP
1738c2ecf20Sopenharmony_ci	bl	bpf_error
1748c2ecf20Sopenharmony_ci	 nop
1758c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte_negative_offset
1768c2ecf20Sopenharmony_cibpf_jit_load_byte_negative_offset:
1778c2ecf20Sopenharmony_ci	bpf_negative_common(1)
1788c2ecf20Sopenharmony_ci	retl
1798c2ecf20Sopenharmony_ci	 ldub	[r_TMP], r_A
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cibpf_slow_path_byte_msh_neg:
1828c2ecf20Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
1838c2ecf20Sopenharmony_ci	cmp	r_OFF, r_TMP
1848c2ecf20Sopenharmony_ci	bl	bpf_error
1858c2ecf20Sopenharmony_ci	 nop
1868c2ecf20Sopenharmony_ci	.globl	bpf_jit_load_byte_msh_negative_offset
1878c2ecf20Sopenharmony_cibpf_jit_load_byte_msh_negative_offset:
1888c2ecf20Sopenharmony_ci	bpf_negative_common(1)
1898c2ecf20Sopenharmony_ci	ldub	[r_TMP], r_OFF
1908c2ecf20Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
1918c2ecf20Sopenharmony_ci	retl
1928c2ecf20Sopenharmony_ci	 sll	r_OFF, 2, r_X
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cibpf_error:
1958c2ecf20Sopenharmony_ci	/* Make the JIT program return zero.  The JIT epilogue
1968c2ecf20Sopenharmony_ci	 * stores away the original %o7 into r_saved_O7.  The
1978c2ecf20Sopenharmony_ci	 * normal leaf function return is to use "retl" which
1988c2ecf20Sopenharmony_ci	 * would evalute to "jmpl %o7 + 8, %g0" but we want to
1998c2ecf20Sopenharmony_ci	 * use the saved value thus the sequence you see here.
2008c2ecf20Sopenharmony_ci	 */
2018c2ecf20Sopenharmony_ci	jmpl	r_saved_O7 + 8, %g0
2028c2ecf20Sopenharmony_ci	 clr	%o0
203