1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun#include <asm/ptrace.h> 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun#include "bpf_jit_32.h" 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun#define SAVE_SZ 96 7*4882a593Smuzhiyun#define SCRATCH_OFF 72 8*4882a593Smuzhiyun#define BE_PTR(label) be label 9*4882a593Smuzhiyun#define SIGN_EXTEND(reg) 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun .text 14*4882a593Smuzhiyun .globl bpf_jit_load_word 15*4882a593Smuzhiyunbpf_jit_load_word: 16*4882a593Smuzhiyun cmp r_OFF, 0 17*4882a593Smuzhiyun bl bpf_slow_path_word_neg 18*4882a593Smuzhiyun nop 19*4882a593Smuzhiyun .globl bpf_jit_load_word_positive_offset 20*4882a593Smuzhiyunbpf_jit_load_word_positive_offset: 21*4882a593Smuzhiyun sub r_HEADLEN, r_OFF, r_TMP 22*4882a593Smuzhiyun cmp r_TMP, 3 23*4882a593Smuzhiyun ble bpf_slow_path_word 24*4882a593Smuzhiyun add r_SKB_DATA, r_OFF, r_TMP 25*4882a593Smuzhiyun andcc r_TMP, 3, %g0 26*4882a593Smuzhiyun bne load_word_unaligned 27*4882a593Smuzhiyun nop 28*4882a593Smuzhiyun retl 29*4882a593Smuzhiyun ld [r_TMP], r_A 30*4882a593Smuzhiyunload_word_unaligned: 31*4882a593Smuzhiyun ldub [r_TMP + 0x0], r_OFF 32*4882a593Smuzhiyun ldub [r_TMP + 0x1], r_TMP2 33*4882a593Smuzhiyun sll r_OFF, 8, r_OFF 34*4882a593Smuzhiyun or r_OFF, r_TMP2, r_OFF 35*4882a593Smuzhiyun ldub [r_TMP + 0x2], r_TMP2 36*4882a593Smuzhiyun sll r_OFF, 8, r_OFF 37*4882a593Smuzhiyun or r_OFF, r_TMP2, r_OFF 38*4882a593Smuzhiyun ldub [r_TMP + 0x3], r_TMP2 39*4882a593Smuzhiyun sll r_OFF, 8, r_OFF 40*4882a593Smuzhiyun retl 41*4882a593Smuzhiyun or r_OFF, r_TMP2, r_A 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun .globl bpf_jit_load_half 44*4882a593Smuzhiyunbpf_jit_load_half: 45*4882a593Smuzhiyun cmp r_OFF, 0 46*4882a593Smuzhiyun bl bpf_slow_path_half_neg 47*4882a593Smuzhiyun nop 48*4882a593Smuzhiyun .globl bpf_jit_load_half_positive_offset 49*4882a593Smuzhiyunbpf_jit_load_half_positive_offset: 50*4882a593Smuzhiyun sub r_HEADLEN, r_OFF, r_TMP 51*4882a593Smuzhiyun cmp r_TMP, 1 52*4882a593Smuzhiyun ble bpf_slow_path_half 53*4882a593Smuzhiyun add r_SKB_DATA, r_OFF, r_TMP 54*4882a593Smuzhiyun andcc r_TMP, 1, %g0 55*4882a593Smuzhiyun bne load_half_unaligned 56*4882a593Smuzhiyun nop 57*4882a593Smuzhiyun retl 58*4882a593Smuzhiyun lduh [r_TMP], r_A 59*4882a593Smuzhiyunload_half_unaligned: 60*4882a593Smuzhiyun ldub [r_TMP + 0x0], r_OFF 61*4882a593Smuzhiyun ldub [r_TMP + 0x1], r_TMP2 62*4882a593Smuzhiyun sll r_OFF, 8, r_OFF 63*4882a593Smuzhiyun retl 64*4882a593Smuzhiyun or r_OFF, r_TMP2, r_A 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun .globl bpf_jit_load_byte 67*4882a593Smuzhiyunbpf_jit_load_byte: 68*4882a593Smuzhiyun cmp r_OFF, 0 69*4882a593Smuzhiyun bl bpf_slow_path_byte_neg 70*4882a593Smuzhiyun nop 71*4882a593Smuzhiyun .globl bpf_jit_load_byte_positive_offset 72*4882a593Smuzhiyunbpf_jit_load_byte_positive_offset: 73*4882a593Smuzhiyun cmp r_OFF, r_HEADLEN 74*4882a593Smuzhiyun bge bpf_slow_path_byte 75*4882a593Smuzhiyun nop 76*4882a593Smuzhiyun retl 77*4882a593Smuzhiyun ldub [r_SKB_DATA + r_OFF], r_A 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun .globl bpf_jit_load_byte_msh 80*4882a593Smuzhiyunbpf_jit_load_byte_msh: 81*4882a593Smuzhiyun cmp r_OFF, 0 82*4882a593Smuzhiyun bl bpf_slow_path_byte_msh_neg 83*4882a593Smuzhiyun nop 84*4882a593Smuzhiyun .globl bpf_jit_load_byte_msh_positive_offset 85*4882a593Smuzhiyunbpf_jit_load_byte_msh_positive_offset: 86*4882a593Smuzhiyun cmp r_OFF, r_HEADLEN 87*4882a593Smuzhiyun bge bpf_slow_path_byte_msh 88*4882a593Smuzhiyun nop 89*4882a593Smuzhiyun ldub [r_SKB_DATA + r_OFF], r_OFF 90*4882a593Smuzhiyun and r_OFF, 0xf, r_OFF 91*4882a593Smuzhiyun retl 92*4882a593Smuzhiyun sll r_OFF, 2, r_X 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun#define bpf_slow_path_common(LEN) \ 95*4882a593Smuzhiyun save %sp, -SAVE_SZ, %sp; \ 96*4882a593Smuzhiyun mov %i0, %o0; \ 97*4882a593Smuzhiyun mov r_OFF, %o1; \ 98*4882a593Smuzhiyun add %fp, SCRATCH_OFF, %o2; \ 99*4882a593Smuzhiyun call skb_copy_bits; \ 100*4882a593Smuzhiyun mov (LEN), %o3; \ 101*4882a593Smuzhiyun cmp %o0, 0; \ 102*4882a593Smuzhiyun restore; 103*4882a593Smuzhiyun 104*4882a593Smuzhiyunbpf_slow_path_word: 105*4882a593Smuzhiyun bpf_slow_path_common(4) 106*4882a593Smuzhiyun bl bpf_error 107*4882a593Smuzhiyun ld [%sp + SCRATCH_OFF], r_A 108*4882a593Smuzhiyun retl 109*4882a593Smuzhiyun nop 110*4882a593Smuzhiyunbpf_slow_path_half: 111*4882a593Smuzhiyun bpf_slow_path_common(2) 112*4882a593Smuzhiyun bl bpf_error 113*4882a593Smuzhiyun lduh [%sp + SCRATCH_OFF], r_A 114*4882a593Smuzhiyun retl 115*4882a593Smuzhiyun nop 116*4882a593Smuzhiyunbpf_slow_path_byte: 117*4882a593Smuzhiyun bpf_slow_path_common(1) 118*4882a593Smuzhiyun bl bpf_error 119*4882a593Smuzhiyun ldub [%sp + SCRATCH_OFF], r_A 120*4882a593Smuzhiyun retl 121*4882a593Smuzhiyun nop 122*4882a593Smuzhiyunbpf_slow_path_byte_msh: 123*4882a593Smuzhiyun bpf_slow_path_common(1) 124*4882a593Smuzhiyun bl bpf_error 125*4882a593Smuzhiyun ldub [%sp + SCRATCH_OFF], r_A 126*4882a593Smuzhiyun and r_OFF, 0xf, r_OFF 127*4882a593Smuzhiyun retl 128*4882a593Smuzhiyun sll r_OFF, 2, r_X 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun#define bpf_negative_common(LEN) \ 131*4882a593Smuzhiyun save %sp, -SAVE_SZ, %sp; \ 132*4882a593Smuzhiyun mov %i0, %o0; \ 133*4882a593Smuzhiyun mov r_OFF, %o1; \ 134*4882a593Smuzhiyun SIGN_EXTEND(%o1); \ 135*4882a593Smuzhiyun call bpf_internal_load_pointer_neg_helper; \ 136*4882a593Smuzhiyun mov (LEN), %o2; \ 137*4882a593Smuzhiyun mov %o0, r_TMP; \ 138*4882a593Smuzhiyun cmp %o0, 0; \ 139*4882a593Smuzhiyun BE_PTR(bpf_error); \ 140*4882a593Smuzhiyun restore; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyunbpf_slow_path_word_neg: 143*4882a593Smuzhiyun sethi %hi(SKF_MAX_NEG_OFF), r_TMP 144*4882a593Smuzhiyun cmp r_OFF, r_TMP 145*4882a593Smuzhiyun bl bpf_error 146*4882a593Smuzhiyun nop 147*4882a593Smuzhiyun .globl bpf_jit_load_word_negative_offset 148*4882a593Smuzhiyunbpf_jit_load_word_negative_offset: 149*4882a593Smuzhiyun bpf_negative_common(4) 150*4882a593Smuzhiyun andcc r_TMP, 3, %g0 151*4882a593Smuzhiyun bne load_word_unaligned 152*4882a593Smuzhiyun nop 153*4882a593Smuzhiyun retl 154*4882a593Smuzhiyun ld [r_TMP], r_A 155*4882a593Smuzhiyun 156*4882a593Smuzhiyunbpf_slow_path_half_neg: 157*4882a593Smuzhiyun sethi %hi(SKF_MAX_NEG_OFF), r_TMP 158*4882a593Smuzhiyun cmp r_OFF, r_TMP 159*4882a593Smuzhiyun bl bpf_error 160*4882a593Smuzhiyun nop 161*4882a593Smuzhiyun .globl bpf_jit_load_half_negative_offset 162*4882a593Smuzhiyunbpf_jit_load_half_negative_offset: 163*4882a593Smuzhiyun bpf_negative_common(2) 164*4882a593Smuzhiyun andcc r_TMP, 1, %g0 165*4882a593Smuzhiyun bne load_half_unaligned 166*4882a593Smuzhiyun nop 167*4882a593Smuzhiyun retl 168*4882a593Smuzhiyun lduh [r_TMP], r_A 169*4882a593Smuzhiyun 170*4882a593Smuzhiyunbpf_slow_path_byte_neg: 171*4882a593Smuzhiyun sethi %hi(SKF_MAX_NEG_OFF), r_TMP 172*4882a593Smuzhiyun cmp r_OFF, r_TMP 173*4882a593Smuzhiyun bl bpf_error 174*4882a593Smuzhiyun nop 175*4882a593Smuzhiyun .globl bpf_jit_load_byte_negative_offset 176*4882a593Smuzhiyunbpf_jit_load_byte_negative_offset: 177*4882a593Smuzhiyun bpf_negative_common(1) 178*4882a593Smuzhiyun retl 179*4882a593Smuzhiyun ldub [r_TMP], r_A 180*4882a593Smuzhiyun 181*4882a593Smuzhiyunbpf_slow_path_byte_msh_neg: 182*4882a593Smuzhiyun sethi %hi(SKF_MAX_NEG_OFF), r_TMP 183*4882a593Smuzhiyun cmp r_OFF, r_TMP 184*4882a593Smuzhiyun bl bpf_error 185*4882a593Smuzhiyun nop 186*4882a593Smuzhiyun .globl bpf_jit_load_byte_msh_negative_offset 187*4882a593Smuzhiyunbpf_jit_load_byte_msh_negative_offset: 188*4882a593Smuzhiyun bpf_negative_common(1) 189*4882a593Smuzhiyun ldub [r_TMP], r_OFF 190*4882a593Smuzhiyun and r_OFF, 0xf, r_OFF 191*4882a593Smuzhiyun retl 192*4882a593Smuzhiyun sll r_OFF, 2, r_X 193*4882a593Smuzhiyun 194*4882a593Smuzhiyunbpf_error: 195*4882a593Smuzhiyun /* Make the JIT program return zero. The JIT epilogue 196*4882a593Smuzhiyun * stores away the original %o7 into r_saved_O7. The 197*4882a593Smuzhiyun * normal leaf function return is to use "retl" which 198*4882a593Smuzhiyun * would evalute to "jmpl %o7 + 8, %g0" but we want to 199*4882a593Smuzhiyun * use the saved value thus the sequence you see here. 200*4882a593Smuzhiyun */ 201*4882a593Smuzhiyun jmpl r_saved_O7 + 8, %g0 202*4882a593Smuzhiyun clr %o0 203