203 lines
4.2 KiB
ArmAsm
203 lines
4.2 KiB
ArmAsm
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
#include <asm/ptrace.h>
|
||
|
|
||
|
#include "bpf_jit_32.h"
|
||
|
|
||
|
#define SAVE_SZ 96
|
||
|
#define SCRATCH_OFF 72
|
||
|
#define BE_PTR(label) be label
|
||
|
#define SIGN_EXTEND(reg)
|
||
|
|
||
|
#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
|
||
|
|
||
|
.text
|
||
|
.globl bpf_jit_load_word
|
||
|
bpf_jit_load_word:
|
||
|
cmp r_OFF, 0
|
||
|
bl bpf_slow_path_word_neg
|
||
|
nop
|
||
|
.globl bpf_jit_load_word_positive_offset
|
||
|
bpf_jit_load_word_positive_offset:
|
||
|
sub r_HEADLEN, r_OFF, r_TMP
|
||
|
cmp r_TMP, 3
|
||
|
ble bpf_slow_path_word
|
||
|
add r_SKB_DATA, r_OFF, r_TMP
|
||
|
andcc r_TMP, 3, %g0
|
||
|
bne load_word_unaligned
|
||
|
nop
|
||
|
retl
|
||
|
ld [r_TMP], r_A
|
||
|
load_word_unaligned:
|
||
|
ldub [r_TMP + 0x0], r_OFF
|
||
|
ldub [r_TMP + 0x1], r_TMP2
|
||
|
sll r_OFF, 8, r_OFF
|
||
|
or r_OFF, r_TMP2, r_OFF
|
||
|
ldub [r_TMP + 0x2], r_TMP2
|
||
|
sll r_OFF, 8, r_OFF
|
||
|
or r_OFF, r_TMP2, r_OFF
|
||
|
ldub [r_TMP + 0x3], r_TMP2
|
||
|
sll r_OFF, 8, r_OFF
|
||
|
retl
|
||
|
or r_OFF, r_TMP2, r_A
|
||
|
|
||
|
.globl bpf_jit_load_half
|
||
|
bpf_jit_load_half:
|
||
|
cmp r_OFF, 0
|
||
|
bl bpf_slow_path_half_neg
|
||
|
nop
|
||
|
.globl bpf_jit_load_half_positive_offset
|
||
|
bpf_jit_load_half_positive_offset:
|
||
|
sub r_HEADLEN, r_OFF, r_TMP
|
||
|
cmp r_TMP, 1
|
||
|
ble bpf_slow_path_half
|
||
|
add r_SKB_DATA, r_OFF, r_TMP
|
||
|
andcc r_TMP, 1, %g0
|
||
|
bne load_half_unaligned
|
||
|
nop
|
||
|
retl
|
||
|
lduh [r_TMP], r_A
|
||
|
load_half_unaligned:
|
||
|
ldub [r_TMP + 0x0], r_OFF
|
||
|
ldub [r_TMP + 0x1], r_TMP2
|
||
|
sll r_OFF, 8, r_OFF
|
||
|
retl
|
||
|
or r_OFF, r_TMP2, r_A
|
||
|
|
||
|
.globl bpf_jit_load_byte
|
||
|
bpf_jit_load_byte:
|
||
|
cmp r_OFF, 0
|
||
|
bl bpf_slow_path_byte_neg
|
||
|
nop
|
||
|
.globl bpf_jit_load_byte_positive_offset
|
||
|
bpf_jit_load_byte_positive_offset:
|
||
|
cmp r_OFF, r_HEADLEN
|
||
|
bge bpf_slow_path_byte
|
||
|
nop
|
||
|
retl
|
||
|
ldub [r_SKB_DATA + r_OFF], r_A
|
||
|
|
||
|
.globl bpf_jit_load_byte_msh
|
||
|
bpf_jit_load_byte_msh:
|
||
|
cmp r_OFF, 0
|
||
|
bl bpf_slow_path_byte_msh_neg
|
||
|
nop
|
||
|
.globl bpf_jit_load_byte_msh_positive_offset
|
||
|
bpf_jit_load_byte_msh_positive_offset:
|
||
|
cmp r_OFF, r_HEADLEN
|
||
|
bge bpf_slow_path_byte_msh
|
||
|
nop
|
||
|
ldub [r_SKB_DATA + r_OFF], r_OFF
|
||
|
and r_OFF, 0xf, r_OFF
|
||
|
retl
|
||
|
sll r_OFF, 2, r_X
|
||
|
|
||
|
#define bpf_slow_path_common(LEN) \
|
||
|
save %sp, -SAVE_SZ, %sp; \
|
||
|
mov %i0, %o0; \
|
||
|
mov r_OFF, %o1; \
|
||
|
add %fp, SCRATCH_OFF, %o2; \
|
||
|
call skb_copy_bits; \
|
||
|
mov (LEN), %o3; \
|
||
|
cmp %o0, 0; \
|
||
|
restore;
|
||
|
|
||
|
bpf_slow_path_word:
|
||
|
bpf_slow_path_common(4)
|
||
|
bl bpf_error
|
||
|
ld [%sp + SCRATCH_OFF], r_A
|
||
|
retl
|
||
|
nop
|
||
|
bpf_slow_path_half:
|
||
|
bpf_slow_path_common(2)
|
||
|
bl bpf_error
|
||
|
lduh [%sp + SCRATCH_OFF], r_A
|
||
|
retl
|
||
|
nop
|
||
|
bpf_slow_path_byte:
|
||
|
bpf_slow_path_common(1)
|
||
|
bl bpf_error
|
||
|
ldub [%sp + SCRATCH_OFF], r_A
|
||
|
retl
|
||
|
nop
|
||
|
bpf_slow_path_byte_msh:
|
||
|
bpf_slow_path_common(1)
|
||
|
bl bpf_error
|
||
|
ldub [%sp + SCRATCH_OFF], r_A
|
||
|
and r_OFF, 0xf, r_OFF
|
||
|
retl
|
||
|
sll r_OFF, 2, r_X
|
||
|
|
||
|
#define bpf_negative_common(LEN) \
|
||
|
save %sp, -SAVE_SZ, %sp; \
|
||
|
mov %i0, %o0; \
|
||
|
mov r_OFF, %o1; \
|
||
|
SIGN_EXTEND(%o1); \
|
||
|
call bpf_internal_load_pointer_neg_helper; \
|
||
|
mov (LEN), %o2; \
|
||
|
mov %o0, r_TMP; \
|
||
|
cmp %o0, 0; \
|
||
|
BE_PTR(bpf_error); \
|
||
|
restore;
|
||
|
|
||
|
bpf_slow_path_word_neg:
|
||
|
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||
|
cmp r_OFF, r_TMP
|
||
|
bl bpf_error
|
||
|
nop
|
||
|
.globl bpf_jit_load_word_negative_offset
|
||
|
bpf_jit_load_word_negative_offset:
|
||
|
bpf_negative_common(4)
|
||
|
andcc r_TMP, 3, %g0
|
||
|
bne load_word_unaligned
|
||
|
nop
|
||
|
retl
|
||
|
ld [r_TMP], r_A
|
||
|
|
||
|
bpf_slow_path_half_neg:
|
||
|
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||
|
cmp r_OFF, r_TMP
|
||
|
bl bpf_error
|
||
|
nop
|
||
|
.globl bpf_jit_load_half_negative_offset
|
||
|
bpf_jit_load_half_negative_offset:
|
||
|
bpf_negative_common(2)
|
||
|
andcc r_TMP, 1, %g0
|
||
|
bne load_half_unaligned
|
||
|
nop
|
||
|
retl
|
||
|
lduh [r_TMP], r_A
|
||
|
|
||
|
bpf_slow_path_byte_neg:
|
||
|
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||
|
cmp r_OFF, r_TMP
|
||
|
bl bpf_error
|
||
|
nop
|
||
|
.globl bpf_jit_load_byte_negative_offset
|
||
|
bpf_jit_load_byte_negative_offset:
|
||
|
bpf_negative_common(1)
|
||
|
retl
|
||
|
ldub [r_TMP], r_A
|
||
|
|
||
|
bpf_slow_path_byte_msh_neg:
|
||
|
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||
|
cmp r_OFF, r_TMP
|
||
|
bl bpf_error
|
||
|
nop
|
||
|
.globl bpf_jit_load_byte_msh_negative_offset
|
||
|
bpf_jit_load_byte_msh_negative_offset:
|
||
|
bpf_negative_common(1)
|
||
|
ldub [r_TMP], r_OFF
|
||
|
and r_OFF, 0xf, r_OFF
|
||
|
retl
|
||
|
sll r_OFF, 2, r_X
|
||
|
|
||
|
bpf_error:
|
||
|
/* Make the JIT program return zero. The JIT epilogue
|
||
|
* stores away the original %o7 into r_saved_O7. The
|
||
|
* normal leaf function return is to use "retl" which
|
||
|
* would evalute to "jmpl %o7 + 8, %g0" but we want to
|
||
|
* use the saved value thus the sequence you see here.
|
||
|
*/
|
||
|
jmpl r_saved_O7 + 8, %g0
|
||
|
clr %o0
|