diff options
Diffstat (limited to 'arch/arm64/net/bpf_jit_comp.c')
-rw-r--r-- | arch/arm64/net/bpf_jit_comp.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index cf3c7d4a1b58..d6a53ef2350b 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c | |||
@@ -50,7 +50,7 @@ static const int bpf2a64[] = { | |||
50 | [BPF_REG_8] = A64_R(21), | 50 | [BPF_REG_8] = A64_R(21), |
51 | [BPF_REG_9] = A64_R(22), | 51 | [BPF_REG_9] = A64_R(22), |
52 | /* read-only frame pointer to access stack */ | 52 | /* read-only frame pointer to access stack */ |
53 | [BPF_REG_FP] = A64_FP, | 53 | [BPF_REG_FP] = A64_R(25), |
54 | /* temporary register for internal BPF JIT */ | 54 | /* temporary register for internal BPF JIT */ |
55 | [TMP_REG_1] = A64_R(23), | 55 | [TMP_REG_1] = A64_R(23), |
56 | [TMP_REG_2] = A64_R(24), | 56 | [TMP_REG_2] = A64_R(24), |
@@ -155,18 +155,49 @@ static void build_prologue(struct jit_ctx *ctx) | |||
155 | stack_size += 4; /* extra for skb_copy_bits buffer */ | 155 | stack_size += 4; /* extra for skb_copy_bits buffer */ |
156 | stack_size = STACK_ALIGN(stack_size); | 156 | stack_size = STACK_ALIGN(stack_size); |
157 | 157 | ||
158 | /* | ||
159 | * BPF prog stack layout | ||
160 | * | ||
161 | * high | ||
162 | * original A64_SP => 0:+-----+ BPF prologue | ||
163 | * |FP/LR| | ||
164 | * current A64_FP => -16:+-----+ | ||
165 | * | ... | callee saved registers | ||
166 | * +-----+ | ||
167 | * | | x25/x26 | ||
168 | * BPF fp register => -80:+-----+ | ||
169 | * | | | ||
170 | * | ... | BPF prog stack | ||
171 | * | | | ||
172 | * | | | ||
173 | * current A64_SP => +-----+ | ||
174 | * | | | ||
175 | * | ... | Function call stack | ||
176 | * | | | ||
177 | * +-----+ | ||
178 | * low | ||
179 | * | ||
180 | */ | ||
181 | |||
182 | /* Save FP and LR registers to stay align with ARM64 AAPCS */ | ||
183 | emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx); | ||
184 | emit(A64_MOV(1, A64_FP, A64_SP), ctx); | ||
185 | |||
158 | /* Save callee-saved register */ | 186 | /* Save callee-saved register */ |
159 | emit(A64_PUSH(r6, r7, A64_SP), ctx); | 187 | emit(A64_PUSH(r6, r7, A64_SP), ctx); |
160 | emit(A64_PUSH(r8, r9, A64_SP), ctx); | 188 | emit(A64_PUSH(r8, r9, A64_SP), ctx); |
161 | if (ctx->tmp_used) | 189 | if (ctx->tmp_used) |
162 | emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx); | 190 | emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx); |
163 | 191 | ||
164 | /* Set up BPF stack */ | 192 | /* Save fp (x25) and x26. SP requires 16 bytes alignment */ |
165 | emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx); | 193 | emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx); |
166 | 194 | ||
167 | /* Set up frame pointer */ | 195 | /* Set up BPF prog stack base register (x25) */ |
168 | emit(A64_MOV(1, fp, A64_SP), ctx); | 196 | emit(A64_MOV(1, fp, A64_SP), ctx); |
169 | 197 | ||
198 | /* Set up function call stack */ | ||
199 | emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx); | ||
200 | |||
170 | /* Clear registers A and X */ | 201 | /* Clear registers A and X */ |
171 | emit_a64_mov_i64(ra, 0, ctx); | 202 | emit_a64_mov_i64(ra, 0, ctx); |
172 | emit_a64_mov_i64(rx, 0, ctx); | 203 | emit_a64_mov_i64(rx, 0, ctx); |
@@ -190,14 +221,17 @@ static void build_epilogue(struct jit_ctx *ctx) | |||
190 | /* We're done with BPF stack */ | 221 | /* We're done with BPF stack */ |
191 | emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx); | 222 | emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx); |
192 | 223 | ||
224 | /* Restore fs (x25) and x26 */ | ||
225 | emit(A64_POP(fp, A64_R(26), A64_SP), ctx); | ||
226 | |||
193 | /* Restore callee-saved register */ | 227 | /* Restore callee-saved register */ |
194 | if (ctx->tmp_used) | 228 | if (ctx->tmp_used) |
195 | emit(A64_POP(tmp1, tmp2, A64_SP), ctx); | 229 | emit(A64_POP(tmp1, tmp2, A64_SP), ctx); |
196 | emit(A64_POP(r8, r9, A64_SP), ctx); | 230 | emit(A64_POP(r8, r9, A64_SP), ctx); |
197 | emit(A64_POP(r6, r7, A64_SP), ctx); | 231 | emit(A64_POP(r6, r7, A64_SP), ctx); |
198 | 232 | ||
199 | /* Restore frame pointer */ | 233 | /* Restore FP/LR registers */ |
200 | emit(A64_MOV(1, fp, A64_SP), ctx); | 234 | emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); |
201 | 235 | ||
202 | /* Set return value */ | 236 | /* Set return value */ |
203 | emit(A64_MOV(1, A64_R(0), r0), ctx); | 237 | emit(A64_MOV(1, A64_R(0), r0), ctx); |
@@ -758,7 +792,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
758 | if (bpf_jit_enable > 1) | 792 | if (bpf_jit_enable > 1) |
759 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); | 793 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); |
760 | 794 | ||
761 | bpf_flush_icache(ctx.image, ctx.image + ctx.idx); | 795 | bpf_flush_icache(header, ctx.image + ctx.idx); |
762 | 796 | ||
763 | set_memory_ro((unsigned long)header, header->pages); | 797 | set_memory_ro((unsigned long)header, header->pages); |
764 | prog->bpf_func = (void *)ctx.image; | 798 | prog->bpf_func = (void *)ctx.image; |