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