diff options
Diffstat (limited to 'arch/arm64/net')
-rw-r--r-- | arch/arm64/net/bpf_jit_comp.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 64a8bc12f4a2..a6905b8d12d3 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,16 +155,47 @@ 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 frame pointer */ | 192 | /* Save fp (x25) and x26. SP requires 16 bytes alignment */ |
193 | emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx); | ||
194 | |||
195 | /* Set up BPF prog stack base register (x25) */ | ||
165 | emit(A64_MOV(1, fp, A64_SP), ctx); | 196 | emit(A64_MOV(1, fp, A64_SP), ctx); |
166 | 197 | ||
167 | /* Set up BPF stack */ | 198 | /* Set up function call stack */ |
168 | emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx); | 199 | emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx); |
169 | 200 | ||
170 | /* Clear registers A and X */ | 201 | /* Clear registers A and X */ |
@@ -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); |