aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/net
diff options
context:
space:
mode:
authorYang Shi <yang.shi@linaro.org>2015-11-16 17:35:35 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-17 14:44:39 -0500
commitec0738db8d7a9bd6653d9f9d81b201a519144d63 (patch)
treeab7bd5c2ac7e695b3c463ee4fb21a816be409d50 /arch/arm64/net
parente639b8d8a7a728f0b05ef2df6cb6b45dc3d4e556 (diff)
arm64: bpf: make BPF prologue and epilogue align with ARM64 AAPCS
Save and restore FP/LR in BPF prog prologue and epilogue, save SP to FP in prologue in order to get the correct stack backtrace. However, ARM64 JIT used FP (x29) as eBPF fp register, FP is subjected to change during function call so it may cause the BPF prog stack base address change too. Use x25 to replace FP as BPF stack base register (fp). Since x25 is callee saved register, so it will keep intact during function call. It is initialized in BPF prog prologue when BPF prog is started to run everytime. Save and restore x25/x26 in BPF prologue and epilogue to keep them intact for the outside of BPF. Actually, x26 is unnecessary, but SP requires 16 bytes alignment. So, the BPF stack layout looks like: high original A64_SP => 0:+-----+ BPF prologue |FP/LR| current A64_FP => -16:+-----+ | ... | callee saved registers +-----+ | | x25/x26 BPF fp register => -80:+-----+ | | | ... | BPF prog stack | | | | current A64_SP => +-----+ | | | ... | Function call stack | | +-----+ low CC: Zi Shen Lim <zlim.lnx@gmail.com> CC: Xi Wang <xi.wang@gmail.com> Signed-off-by: Yang Shi <yang.shi@linaro.org> Acked-by: Zi Shen Lim <zlim.lnx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/arm64/net')
-rw-r--r--arch/arm64/net/bpf_jit_comp.c44
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);