162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#include <asm/ptrace.h>
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "bpf_jit_32.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#define SAVE_SZ		96
762306a36Sopenharmony_ci#define SCRATCH_OFF	72
862306a36Sopenharmony_ci#define BE_PTR(label)	be label
962306a36Sopenharmony_ci#define SIGN_EXTEND(reg)
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define SKF_MAX_NEG_OFF	(-0x200000) /* SKF_LL_OFF from filter.h */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	.text
1462306a36Sopenharmony_ci	.globl	bpf_jit_load_word
1562306a36Sopenharmony_cibpf_jit_load_word:
1662306a36Sopenharmony_ci	cmp	r_OFF, 0
1762306a36Sopenharmony_ci	bl	bpf_slow_path_word_neg
1862306a36Sopenharmony_ci	 nop
1962306a36Sopenharmony_ci	.globl	bpf_jit_load_word_positive_offset
2062306a36Sopenharmony_cibpf_jit_load_word_positive_offset:
2162306a36Sopenharmony_ci	sub	r_HEADLEN, r_OFF, r_TMP
2262306a36Sopenharmony_ci	cmp	r_TMP, 3
2362306a36Sopenharmony_ci	ble	bpf_slow_path_word
2462306a36Sopenharmony_ci	 add	r_SKB_DATA, r_OFF, r_TMP
2562306a36Sopenharmony_ci	andcc	r_TMP, 3, %g0
2662306a36Sopenharmony_ci	bne	load_word_unaligned
2762306a36Sopenharmony_ci	 nop
2862306a36Sopenharmony_ci	retl
2962306a36Sopenharmony_ci	 ld	[r_TMP], r_A
3062306a36Sopenharmony_ciload_word_unaligned:
3162306a36Sopenharmony_ci	ldub	[r_TMP + 0x0], r_OFF
3262306a36Sopenharmony_ci	ldub	[r_TMP + 0x1], r_TMP2
3362306a36Sopenharmony_ci	sll	r_OFF, 8, r_OFF
3462306a36Sopenharmony_ci	or	r_OFF, r_TMP2, r_OFF
3562306a36Sopenharmony_ci	ldub	[r_TMP + 0x2], r_TMP2
3662306a36Sopenharmony_ci	sll	r_OFF, 8, r_OFF
3762306a36Sopenharmony_ci	or	r_OFF, r_TMP2, r_OFF
3862306a36Sopenharmony_ci	ldub	[r_TMP + 0x3], r_TMP2
3962306a36Sopenharmony_ci	sll	r_OFF, 8, r_OFF
4062306a36Sopenharmony_ci	retl
4162306a36Sopenharmony_ci	 or	r_OFF, r_TMP2, r_A
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	.globl	bpf_jit_load_half
4462306a36Sopenharmony_cibpf_jit_load_half:
4562306a36Sopenharmony_ci	cmp	r_OFF, 0
4662306a36Sopenharmony_ci	bl	bpf_slow_path_half_neg
4762306a36Sopenharmony_ci	 nop
4862306a36Sopenharmony_ci	.globl	bpf_jit_load_half_positive_offset
4962306a36Sopenharmony_cibpf_jit_load_half_positive_offset:
5062306a36Sopenharmony_ci	sub	r_HEADLEN, r_OFF, r_TMP
5162306a36Sopenharmony_ci	cmp	r_TMP, 1
5262306a36Sopenharmony_ci	ble	bpf_slow_path_half
5362306a36Sopenharmony_ci	 add	r_SKB_DATA, r_OFF, r_TMP
5462306a36Sopenharmony_ci	andcc	r_TMP, 1, %g0
5562306a36Sopenharmony_ci	bne	load_half_unaligned
5662306a36Sopenharmony_ci	 nop
5762306a36Sopenharmony_ci	retl
5862306a36Sopenharmony_ci	 lduh	[r_TMP], r_A
5962306a36Sopenharmony_ciload_half_unaligned:
6062306a36Sopenharmony_ci	ldub	[r_TMP + 0x0], r_OFF
6162306a36Sopenharmony_ci	ldub	[r_TMP + 0x1], r_TMP2
6262306a36Sopenharmony_ci	sll	r_OFF, 8, r_OFF
6362306a36Sopenharmony_ci	retl
6462306a36Sopenharmony_ci	 or	r_OFF, r_TMP2, r_A
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	.globl	bpf_jit_load_byte
6762306a36Sopenharmony_cibpf_jit_load_byte:
6862306a36Sopenharmony_ci	cmp	r_OFF, 0
6962306a36Sopenharmony_ci	bl	bpf_slow_path_byte_neg
7062306a36Sopenharmony_ci	 nop
7162306a36Sopenharmony_ci	.globl	bpf_jit_load_byte_positive_offset
7262306a36Sopenharmony_cibpf_jit_load_byte_positive_offset:
7362306a36Sopenharmony_ci	cmp	r_OFF, r_HEADLEN
7462306a36Sopenharmony_ci	bge	bpf_slow_path_byte
7562306a36Sopenharmony_ci	 nop
7662306a36Sopenharmony_ci	retl
7762306a36Sopenharmony_ci	 ldub	[r_SKB_DATA + r_OFF], r_A
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	.globl	bpf_jit_load_byte_msh
8062306a36Sopenharmony_cibpf_jit_load_byte_msh:
8162306a36Sopenharmony_ci	cmp	r_OFF, 0
8262306a36Sopenharmony_ci	bl	bpf_slow_path_byte_msh_neg
8362306a36Sopenharmony_ci	 nop
8462306a36Sopenharmony_ci	.globl	bpf_jit_load_byte_msh_positive_offset
8562306a36Sopenharmony_cibpf_jit_load_byte_msh_positive_offset:
8662306a36Sopenharmony_ci	cmp	r_OFF, r_HEADLEN
8762306a36Sopenharmony_ci	bge	bpf_slow_path_byte_msh
8862306a36Sopenharmony_ci	 nop
8962306a36Sopenharmony_ci	ldub	[r_SKB_DATA + r_OFF], r_OFF
9062306a36Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
9162306a36Sopenharmony_ci	retl
9262306a36Sopenharmony_ci	 sll	r_OFF, 2, r_X
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define bpf_slow_path_common(LEN)	\
9562306a36Sopenharmony_ci	save	%sp, -SAVE_SZ, %sp;	\
9662306a36Sopenharmony_ci	mov	%i0, %o0;		\
9762306a36Sopenharmony_ci	mov	r_OFF, %o1;		\
9862306a36Sopenharmony_ci	add	%fp, SCRATCH_OFF, %o2;	\
9962306a36Sopenharmony_ci	call	skb_copy_bits;		\
10062306a36Sopenharmony_ci	 mov	(LEN), %o3;		\
10162306a36Sopenharmony_ci	cmp	%o0, 0;			\
10262306a36Sopenharmony_ci	restore;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cibpf_slow_path_word:
10562306a36Sopenharmony_ci	bpf_slow_path_common(4)
10662306a36Sopenharmony_ci	bl	bpf_error
10762306a36Sopenharmony_ci	 ld	[%sp + SCRATCH_OFF], r_A
10862306a36Sopenharmony_ci	retl
10962306a36Sopenharmony_ci	 nop
11062306a36Sopenharmony_cibpf_slow_path_half:
11162306a36Sopenharmony_ci	bpf_slow_path_common(2)
11262306a36Sopenharmony_ci	bl	bpf_error
11362306a36Sopenharmony_ci	 lduh	[%sp + SCRATCH_OFF], r_A
11462306a36Sopenharmony_ci	retl
11562306a36Sopenharmony_ci	 nop
11662306a36Sopenharmony_cibpf_slow_path_byte:
11762306a36Sopenharmony_ci	bpf_slow_path_common(1)
11862306a36Sopenharmony_ci	bl	bpf_error
11962306a36Sopenharmony_ci	 ldub	[%sp + SCRATCH_OFF], r_A
12062306a36Sopenharmony_ci	retl
12162306a36Sopenharmony_ci	 nop
12262306a36Sopenharmony_cibpf_slow_path_byte_msh:
12362306a36Sopenharmony_ci	bpf_slow_path_common(1)
12462306a36Sopenharmony_ci	bl	bpf_error
12562306a36Sopenharmony_ci	 ldub	[%sp + SCRATCH_OFF], r_A
12662306a36Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
12762306a36Sopenharmony_ci	retl
12862306a36Sopenharmony_ci	 sll	r_OFF, 2, r_X
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#define bpf_negative_common(LEN)			\
13162306a36Sopenharmony_ci	save	%sp, -SAVE_SZ, %sp;			\
13262306a36Sopenharmony_ci	mov	%i0, %o0;				\
13362306a36Sopenharmony_ci	mov	r_OFF, %o1;				\
13462306a36Sopenharmony_ci	SIGN_EXTEND(%o1);				\
13562306a36Sopenharmony_ci	call	bpf_internal_load_pointer_neg_helper;	\
13662306a36Sopenharmony_ci	 mov	(LEN), %o2;				\
13762306a36Sopenharmony_ci	mov	%o0, r_TMP;				\
13862306a36Sopenharmony_ci	cmp	%o0, 0;					\
13962306a36Sopenharmony_ci	BE_PTR(bpf_error);				\
14062306a36Sopenharmony_ci	 restore;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cibpf_slow_path_word_neg:
14362306a36Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
14462306a36Sopenharmony_ci	cmp	r_OFF, r_TMP
14562306a36Sopenharmony_ci	bl	bpf_error
14662306a36Sopenharmony_ci	 nop
14762306a36Sopenharmony_ci	.globl	bpf_jit_load_word_negative_offset
14862306a36Sopenharmony_cibpf_jit_load_word_negative_offset:
14962306a36Sopenharmony_ci	bpf_negative_common(4)
15062306a36Sopenharmony_ci	andcc	r_TMP, 3, %g0
15162306a36Sopenharmony_ci	bne	load_word_unaligned
15262306a36Sopenharmony_ci	 nop
15362306a36Sopenharmony_ci	retl
15462306a36Sopenharmony_ci	 ld	[r_TMP], r_A
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cibpf_slow_path_half_neg:
15762306a36Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
15862306a36Sopenharmony_ci	cmp	r_OFF, r_TMP
15962306a36Sopenharmony_ci	bl	bpf_error
16062306a36Sopenharmony_ci	 nop
16162306a36Sopenharmony_ci	.globl	bpf_jit_load_half_negative_offset
16262306a36Sopenharmony_cibpf_jit_load_half_negative_offset:
16362306a36Sopenharmony_ci	bpf_negative_common(2)
16462306a36Sopenharmony_ci	andcc	r_TMP, 1, %g0
16562306a36Sopenharmony_ci	bne	load_half_unaligned
16662306a36Sopenharmony_ci	 nop
16762306a36Sopenharmony_ci	retl
16862306a36Sopenharmony_ci	 lduh	[r_TMP], r_A
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cibpf_slow_path_byte_neg:
17162306a36Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
17262306a36Sopenharmony_ci	cmp	r_OFF, r_TMP
17362306a36Sopenharmony_ci	bl	bpf_error
17462306a36Sopenharmony_ci	 nop
17562306a36Sopenharmony_ci	.globl	bpf_jit_load_byte_negative_offset
17662306a36Sopenharmony_cibpf_jit_load_byte_negative_offset:
17762306a36Sopenharmony_ci	bpf_negative_common(1)
17862306a36Sopenharmony_ci	retl
17962306a36Sopenharmony_ci	 ldub	[r_TMP], r_A
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cibpf_slow_path_byte_msh_neg:
18262306a36Sopenharmony_ci	sethi	%hi(SKF_MAX_NEG_OFF), r_TMP
18362306a36Sopenharmony_ci	cmp	r_OFF, r_TMP
18462306a36Sopenharmony_ci	bl	bpf_error
18562306a36Sopenharmony_ci	 nop
18662306a36Sopenharmony_ci	.globl	bpf_jit_load_byte_msh_negative_offset
18762306a36Sopenharmony_cibpf_jit_load_byte_msh_negative_offset:
18862306a36Sopenharmony_ci	bpf_negative_common(1)
18962306a36Sopenharmony_ci	ldub	[r_TMP], r_OFF
19062306a36Sopenharmony_ci	and	r_OFF, 0xf, r_OFF
19162306a36Sopenharmony_ci	retl
19262306a36Sopenharmony_ci	 sll	r_OFF, 2, r_X
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cibpf_error:
19562306a36Sopenharmony_ci	/* Make the JIT program return zero.  The JIT epilogue
19662306a36Sopenharmony_ci	 * stores away the original %o7 into r_saved_O7.  The
19762306a36Sopenharmony_ci	 * normal leaf function return is to use "retl" which
19862306a36Sopenharmony_ci	 * would evalute to "jmpl %o7 + 8, %g0" but we want to
19962306a36Sopenharmony_ci	 * use the saved value thus the sequence you see here.
20062306a36Sopenharmony_ci	 */
20162306a36Sopenharmony_ci	jmpl	r_saved_O7 + 8, %g0
20262306a36Sopenharmony_ci	 clr	%o0
203