| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <asm/asm.h> |
| #include <asm/isa-rev.h> |
| #include <asm/regdef.h> |
| #include "bpf_jit.h" |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define skb a0 |
| #define offset a1 |
| #define SKF_LL_OFF (-0x200000) |
| |
| <------> |
| <------>.set noreorder |
| |
| #define is_offset_negative(TYPE) \ |
| <------> \ |
| <------>slti t0, offset, 0; \ |
| <------>bgtz t0, bpf_slow_path_##TYPE##_neg; \ |
| <------> |
| |
| #define is_offset_in_header(SIZE, TYPE) \ |
| <------> \ |
| <------>addiu $r_s0, $r_skb_hl, -SIZE; \ |
| <------>slt t0, $r_s0, offset; \ |
| <------>bgtz t0, bpf_slow_path_##TYPE; \ |
| |
| LEAF(sk_load_word) |
| <------>is_offset_negative(word) |
| FEXPORT(sk_load_word_positive) |
| <------>is_offset_in_header(4, word) |
| <------> |
| <------>PTR_ADDU t1, $r_skb_data, offset |
| <------>.set reorder |
| <------>lw $r_A, 0(t1) |
| <------>.set noreorder |
| #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| # if MIPS_ISA_REV >= 2 |
| <------>wsbh t0, $r_A |
| <------>rotr $r_A, t0, 16 |
| # else |
| <------>sll t0, $r_A, 24 |
| <------>srl t1, $r_A, 24 |
| <------>srl t2, $r_A, 8 |
| <------>or t0, t0, t1 |
| <------>andi t2, t2, 0xff00 |
| <------>andi t1, $r_A, 0xff00 |
| <------>or t0, t0, t2 |
| <------>sll t1, t1, 8 |
| <------>or $r_A, t0, t1 |
| # endif |
| #endif |
| <------>jr $r_ra |
| <------> move $r_ret, zero |
| <------>END(sk_load_word) |
| |
| LEAF(sk_load_half) |
| <------>is_offset_negative(half) |
| FEXPORT(sk_load_half_positive) |
| <------>is_offset_in_header(2, half) |
| <------> |
| <------>PTR_ADDU t1, $r_skb_data, offset |
| <------>lhu $r_A, 0(t1) |
| #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| # if MIPS_ISA_REV >= 2 |
| <------>wsbh $r_A, $r_A |
| # else |
| <------>sll t0, $r_A, 8 |
| <------>srl t1, $r_A, 8 |
| <------>andi t0, t0, 0xff00 |
| <------>or $r_A, t0, t1 |
| # endif |
| #endif |
| <------>jr $r_ra |
| <------> move $r_ret, zero |
| <------>END(sk_load_half) |
| |
| LEAF(sk_load_byte) |
| <------>is_offset_negative(byte) |
| FEXPORT(sk_load_byte_positive) |
| <------>is_offset_in_header(1, byte) |
| <------> |
| <------>PTR_ADDU t1, $r_skb_data, offset |
| <------>lbu $r_A, 0(t1) |
| <------>jr $r_ra |
| <------> move $r_ret, zero |
| <------>END(sk_load_byte) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| #define DS_OFFSET(SIZE) (4 * SZREG) |
| #else |
| #define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE)) |
| #endif |
| #define bpf_slow_path_common(SIZE) \ |
| <------> \ |
| <------>LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \ |
| <------>sltu $r_s0, offset, $r_s1; \ |
| <------>beqz $r_s0, fault; \ |
| <------> \ |
| <------> LONG_ADDIU a3, zero, SIZE; \ |
| <------>PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ |
| <------>PTR_LA t0, skb_copy_bits; \ |
| <------>PTR_S $r_ra, (5 * SZREG)($r_sp); \ |
| <------> \ |
| <------>PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \ |
| <------>jalr t0; \ |
| <------> \ |
| <------> INT_S zero, (4 * SZREG)($r_sp); \ |
| <------> |
| <------> * skb_copy_bits returns 0 on success and -EFAULT \ |
| <------> * on error. Our data live in a2. Do not bother with \ |
| <------> * our data if an error has been returned. \ |
| <------> */ \ |
| <------> \ |
| <------>PTR_L $r_ra, (5 * SZREG)($r_sp); \ |
| <------>INT_L $r_s0, (4 * SZREG)($r_sp); \ |
| <------>bltz v0, fault; \ |
| <------> PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ |
| <------>move $r_ret, zero; \ |
| |
| NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) |
| <------>bpf_slow_path_common(4) |
| #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| # if MIPS_ISA_REV >= 2 |
| <------>wsbh t0, $r_s0 |
| <------>jr $r_ra |
| <------> rotr $r_A, t0, 16 |
| # else |
| <------>sll t0, $r_s0, 24 |
| <------>srl t1, $r_s0, 24 |
| <------>srl t2, $r_s0, 8 |
| <------>or t0, t0, t1 |
| <------>andi t2, t2, 0xff00 |
| <------>andi t1, $r_s0, 0xff00 |
| <------>or t0, t0, t2 |
| <------>sll t1, t1, 8 |
| <------>jr $r_ra |
| <------> or $r_A, t0, t1 |
| # endif |
| #else |
| <------>jr $r_ra |
| <------> move $r_A, $r_s0 |
| #endif |
| |
| <------>END(bpf_slow_path_word) |
| |
| NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp) |
| <------>bpf_slow_path_common(2) |
| #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| # if MIPS_ISA_REV >= 2 |
| <------>jr $r_ra |
| <------> wsbh $r_A, $r_s0 |
| # else |
| <------>sll t0, $r_s0, 8 |
| <------>andi t1, $r_s0, 0xff00 |
| <------>andi t0, t0, 0xff00 |
| <------>srl t1, t1, 8 |
| <------>jr $r_ra |
| <------> or $r_A, t0, t1 |
| # endif |
| #else |
| <------>jr $r_ra |
| <------> move $r_A, $r_s0 |
| #endif |
| |
| <------>END(bpf_slow_path_half) |
| |
| NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp) |
| <------>bpf_slow_path_common(1) |
| <------>jr $r_ra |
| <------> move $r_A, $r_s0 |
| |
| <------>END(bpf_slow_path_byte) |
| |
| |
| |
| |
| <------>.macro bpf_is_end_of_data |
| <------>li t0, SKF_LL_OFF |
| <------> |
| <------>slt t1, offset, t0 |
| <------>bgtz t1, fault |
| <------> |
| <------>.endm |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define bpf_negative_common(SIZE) \ |
| <------>PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ |
| <------>PTR_LA t0, bpf_internal_load_pointer_neg_helper; \ |
| <------>PTR_S $r_ra, (5 * SZREG)($r_sp); \ |
| <------>jalr t0; \ |
| <------> li a2, SIZE; \ |
| <------>PTR_L $r_ra, (5 * SZREG)($r_sp); \ |
| <------> \ |
| <------>beqz v0, fault; \ |
| <------> PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ |
| <------> \ |
| <------>move $r_s0, v0; \ |
| <------> \ |
| <------>move $r_ret, zero; \ |
| |
| bpf_slow_path_word_neg: |
| <------>bpf_is_end_of_data |
| NESTED(sk_load_word_negative, (6 * SZREG), $r_sp) |
| <------>bpf_negative_common(4) |
| <------>jr $r_ra |
| <------> lw $r_A, 0($r_s0) |
| <------>END(sk_load_word_negative) |
| |
| bpf_slow_path_half_neg: |
| <------>bpf_is_end_of_data |
| NESTED(sk_load_half_negative, (6 * SZREG), $r_sp) |
| <------>bpf_negative_common(2) |
| <------>jr $r_ra |
| <------> lhu $r_A, 0($r_s0) |
| <------>END(sk_load_half_negative) |
| |
| bpf_slow_path_byte_neg: |
| <------>bpf_is_end_of_data |
| NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp) |
| <------>bpf_negative_common(1) |
| <------>jr $r_ra |
| <------> lbu $r_A, 0($r_s0) |
| <------>END(sk_load_byte_negative) |
| |
| fault: |
| <------>jr $r_ra |
| <------> addiu $r_ret, zero, 1 |
| |
| |