bpf_jit_asm.S 4.3 KB
Newer Older
1 2 3 4 5 6 7 8
#include <asm/ptrace.h>

#include "bpf_jit.h"

#ifdef CONFIG_SPARC64
#define SAVE_SZ		176
#define SCRATCH_OFF	STACK_BIAS + 128
#define BE_PTR(label)	be,pn %xcc, label
9
#define SIGN_EXTEND(reg)	sra reg, 0, reg
10 11 12 13
#else
#define SAVE_SZ		96
#define SCRATCH_OFF	72
#define BE_PTR(label)	be label
14
#define SIGN_EXTEND(reg)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#endif

#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
35
	 ld	[r_TMP], r_A
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
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
64
	 lduh	[r_TMP], r_A
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
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;				\
140
	SIGN_EXTEND(%o1);				\
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	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:
201 202 203 204 205 206
	/* 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.
	 */
207 208
	jmpl	r_saved_O7 + 8, %g0
	 clr	%o0