blob: 645653e1931e4b5cd962d690dd7d2caa42954353 [file] [log] [blame]
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001/*
Shubham Bansal39c13c22017-08-22 12:02:33 +05302 * Just-In-Time compiler for eBPF filters on 32bit ARM
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01003 *
Shubham Bansal39c13c22017-08-22 12:02:33 +05304 * Copyright (c) 2017 Shubham Bansal <illusionist.neo@gmail.com>
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01005 * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; version 2 of the License.
10 */
11
Shubham Bansal39c13c22017-08-22 12:02:33 +053012#include <linux/bpf.h>
Mircea Gherzanddecdfc2012-03-16 13:37:12 +010013#include <linux/bitops.h>
14#include <linux/compiler.h>
15#include <linux/errno.h>
16#include <linux/filter.h>
Mircea Gherzanddecdfc2012-03-16 13:37:12 +010017#include <linux/netdevice.h>
18#include <linux/string.h>
19#include <linux/slab.h>
Daniel Borkmannbf0098f2012-11-07 15:31:02 +000020#include <linux/if_vlan.h>
Daniel Borkmanne8b56d52014-09-19 14:56:57 +020021
Mircea Gherzanddecdfc2012-03-16 13:37:12 +010022#include <asm/cacheflush.h>
23#include <asm/hwcap.h>
Ben Dooks34607432013-07-24 15:44:56 +010024#include <asm/opcodes.h>
Mircea Gherzanddecdfc2012-03-16 13:37:12 +010025
26#include "bpf_jit_32.h"
27
Russell King70ec3a62018-01-13 21:26:14 +000028/*
Russell King0005e552018-01-13 22:51:27 +000029 * eBPF prog stack layout:
Russell King70ec3a62018-01-13 21:26:14 +000030 *
31 * high
Russell King0005e552018-01-13 22:51:27 +000032 * original ARM_SP => +-----+
33 * | | callee saved registers
34 * +-----+ <= (BPF_FP + SCRATCH_SIZE)
Russell King70ec3a62018-01-13 21:26:14 +000035 * | ... | eBPF JIT scratch space
Russell King0005e552018-01-13 22:51:27 +000036 * eBPF fp register => +-----+
37 * (BPF_FP) | ... | eBPF prog stack
Russell King70ec3a62018-01-13 21:26:14 +000038 * +-----+
39 * |RSVD | JIT scratchpad
Russell King0005e552018-01-13 22:51:27 +000040 * current ARM_SP => +-----+ <= (BPF_FP - STACK_SIZE + SCRATCH_SIZE)
Russell King70ec3a62018-01-13 21:26:14 +000041 * | |
42 * | ... | Function call stack
43 * | |
44 * +-----+
45 * low
Russell King0005e552018-01-13 22:51:27 +000046 *
47 * The callee saved registers depends on whether frame pointers are enabled.
48 * With frame pointers (to be compliant with the ABI):
49 *
50 * high
51 * original ARM_SP => +------------------+ \
52 * | pc | |
53 * current ARM_FP => +------------------+ } callee saved registers
54 * |r4-r8,r10,fp,ip,lr| |
55 * +------------------+ /
56 * low
57 *
58 * Without frame pointers:
59 *
60 * high
61 * original ARM_SP => +------------------+
Russell King02088d92018-01-13 22:38:18 +000062 * | r4-r8,r10,fp,lr | callee saved registers
63 * current ARM_FP => +------------------+
Russell King0005e552018-01-13 22:51:27 +000064 * low
Russell King02088d92018-01-13 22:38:18 +000065 *
66 * When popping registers off the stack at the end of a BPF function, we
67 * reference them via the current ARM_FP register.
Russell King70ec3a62018-01-13 21:26:14 +000068 */
Russell King02088d92018-01-13 22:38:18 +000069#define CALLEE_MASK (1 << ARM_R4 | 1 << ARM_R5 | 1 << ARM_R6 | \
70 1 << ARM_R7 | 1 << ARM_R8 | 1 << ARM_R10 | \
71 1 << ARM_FP)
72#define CALLEE_PUSH_MASK (CALLEE_MASK | 1 << ARM_LR)
73#define CALLEE_POP_MASK (CALLEE_MASK | 1 << ARM_PC)
Russell King70ec3a62018-01-13 21:26:14 +000074
Russell Kingd449ceb2018-07-11 10:31:31 +010075enum {
76 /* Stack layout - these are offsets from (top of stack - 4) */
77 BPF_R2_HI,
78 BPF_R2_LO,
79 BPF_R3_HI,
80 BPF_R3_LO,
81 BPF_R4_HI,
82 BPF_R4_LO,
83 BPF_R5_HI,
84 BPF_R5_LO,
85 BPF_R7_HI,
86 BPF_R7_LO,
87 BPF_R8_HI,
88 BPF_R8_LO,
89 BPF_R9_HI,
90 BPF_R9_LO,
91 BPF_FP_HI,
92 BPF_FP_LO,
93 BPF_TC_HI,
94 BPF_TC_LO,
95 BPF_AX_HI,
96 BPF_AX_LO,
97 /* Stack space for BPF_REG_2, BPF_REG_3, BPF_REG_4,
98 * BPF_REG_5, BPF_REG_7, BPF_REG_8, BPF_REG_9,
99 * BPF_REG_FP and Tail call counts.
100 */
101 BPF_JIT_SCRATCH_REGS,
102};
103
Russell King1c35ba12018-07-11 10:31:41 +0100104/*
105 * Negative "register" values indicate the register is stored on the stack
106 * and are the offset from the top of the eBPF JIT scratch space.
107 */
108#define STACK_OFFSET(k) (-4 - (k) * 4)
Russell Kingd449ceb2018-07-11 10:31:31 +0100109#define SCRATCH_SIZE (BPF_JIT_SCRATCH_REGS * 4)
110
Russell King96cced42018-07-11 10:32:02 +0100111#ifdef CONFIG_FRAME_POINTER
112#define EBPF_SCRATCH_TO_ARM_FP(x) ((x) - 4 * hweight16(CALLEE_PUSH_MASK) - 4)
113#else
114#define EBPF_SCRATCH_TO_ARM_FP(x) (x)
115#endif
116
Shubham Bansal39c13c22017-08-22 12:02:33 +0530117#define TMP_REG_1 (MAX_BPF_JIT_REG + 0) /* TEMP Register 1 */
118#define TMP_REG_2 (MAX_BPF_JIT_REG + 1) /* TEMP Register 2 */
119#define TCALL_CNT (MAX_BPF_JIT_REG + 2) /* Tail Call Count */
120
Shubham Bansal39c13c22017-08-22 12:02:33 +0530121#define FLAG_IMM_OVERFLOW (1 << 0)
122
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100123/*
Shubham Bansal39c13c22017-08-22 12:02:33 +0530124 * Map eBPF registers to ARM 32bit registers or stack scratch space.
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100125 *
Shubham Bansal39c13c22017-08-22 12:02:33 +0530126 * 1. First argument is passed using the arm 32bit registers and rest of the
127 * arguments are passed on stack scratch space.
Wang YanQing2b589a72018-05-11 11:06:34 +0800128 * 2. First callee-saved argument is mapped to arm 32 bit registers and rest
Shubham Bansal39c13c22017-08-22 12:02:33 +0530129 * arguments are mapped to scratch space on stack.
130 * 3. We need two 64 bit temp registers to do complex operations on eBPF
131 * registers.
132 *
133 * As the eBPF registers are all 64 bit registers and arm has only 32 bit
134 * registers, we have to map each eBPF registers with two arm 32 bit regs or
135 * scratch memory space and we have to build eBPF 64 bit register from those.
136 *
137 */
Russell King1c35ba12018-07-11 10:31:41 +0100138static const s8 bpf2a32[][2] = {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530139 /* return value from in-kernel function, and exit value from eBPF */
140 [BPF_REG_0] = {ARM_R1, ARM_R0},
141 /* arguments from eBPF program to in-kernel function */
142 [BPF_REG_1] = {ARM_R3, ARM_R2},
143 /* Stored on stack scratch space */
Russell Kingd449ceb2018-07-11 10:31:31 +0100144 [BPF_REG_2] = {STACK_OFFSET(BPF_R2_HI), STACK_OFFSET(BPF_R2_LO)},
145 [BPF_REG_3] = {STACK_OFFSET(BPF_R3_HI), STACK_OFFSET(BPF_R3_LO)},
146 [BPF_REG_4] = {STACK_OFFSET(BPF_R4_HI), STACK_OFFSET(BPF_R4_LO)},
147 [BPF_REG_5] = {STACK_OFFSET(BPF_R5_HI), STACK_OFFSET(BPF_R5_LO)},
Shubham Bansal39c13c22017-08-22 12:02:33 +0530148 /* callee saved registers that in-kernel function will preserve */
149 [BPF_REG_6] = {ARM_R5, ARM_R4},
150 /* Stored on stack scratch space */
Russell Kingd449ceb2018-07-11 10:31:31 +0100151 [BPF_REG_7] = {STACK_OFFSET(BPF_R7_HI), STACK_OFFSET(BPF_R7_LO)},
152 [BPF_REG_8] = {STACK_OFFSET(BPF_R8_HI), STACK_OFFSET(BPF_R8_LO)},
153 [BPF_REG_9] = {STACK_OFFSET(BPF_R9_HI), STACK_OFFSET(BPF_R9_LO)},
Shubham Bansal39c13c22017-08-22 12:02:33 +0530154 /* Read only Frame Pointer to access Stack */
Russell Kingd449ceb2018-07-11 10:31:31 +0100155 [BPF_REG_FP] = {STACK_OFFSET(BPF_FP_HI), STACK_OFFSET(BPF_FP_LO)},
Shubham Bansal39c13c22017-08-22 12:02:33 +0530156 /* Temporary Register for internal BPF JIT, can be used
157 * for constant blindings and others.
158 */
159 [TMP_REG_1] = {ARM_R7, ARM_R6},
160 [TMP_REG_2] = {ARM_R10, ARM_R8},
161 /* Tail call count. Stored on stack scratch space. */
Russell Kingd449ceb2018-07-11 10:31:31 +0100162 [TCALL_CNT] = {STACK_OFFSET(BPF_TC_HI), STACK_OFFSET(BPF_TC_LO)},
Shubham Bansal39c13c22017-08-22 12:02:33 +0530163 /* temporary register for blinding constants.
164 * Stored on stack scratch space.
165 */
Russell Kingd449ceb2018-07-11 10:31:31 +0100166 [BPF_REG_AX] = {STACK_OFFSET(BPF_AX_HI), STACK_OFFSET(BPF_AX_LO)},
Shubham Bansal39c13c22017-08-22 12:02:33 +0530167};
168
169#define dst_lo dst[1]
170#define dst_hi dst[0]
171#define src_lo src[1]
172#define src_hi src[0]
173
174/*
175 * JIT Context:
176 *
177 * prog : bpf_prog
178 * idx : index of current last JITed instruction.
179 * prologue_bytes : bytes used in prologue.
180 * epilogue_offset : offset of epilogue starting.
Shubham Bansal39c13c22017-08-22 12:02:33 +0530181 * offsets : array of eBPF instruction offsets in
182 * JITed code.
183 * target : final JITed code.
184 * epilogue_bytes : no of bytes used in epilogue.
185 * imm_count : no of immediate counts used for global
186 * variables.
187 * imms : array of global variable addresses.
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100188 */
189
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100190struct jit_ctx {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530191 const struct bpf_prog *prog;
192 unsigned int idx;
193 unsigned int prologue_bytes;
194 unsigned int epilogue_offset;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100195 u32 flags;
196 u32 *offsets;
197 u32 *target;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530198 u32 stack_size;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100199#if __LINUX_ARM_ARCH__ < 7
200 u16 epilogue_bytes;
201 u16 imm_count;
202 u32 *imms;
203#endif
204};
205
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100206/*
Nicolas Schichan4560cdf2015-10-02 17:06:47 +0200207 * Wrappers which handle both OABI and EABI and assures Thumb2 interworking
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100208 * (where the assembly routines like __aeabi_uidiv could cause problems).
209 */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530210static u32 jit_udiv32(u32 dividend, u32 divisor)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100211{
212 return dividend / divisor;
213}
214
Shubham Bansal39c13c22017-08-22 12:02:33 +0530215static u32 jit_mod32(u32 dividend, u32 divisor)
Nicolas Schichan4560cdf2015-10-02 17:06:47 +0200216{
217 return dividend % divisor;
218}
219
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100220static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
221{
Ben Dooks34607432013-07-24 15:44:56 +0100222 inst |= (cond << 28);
223 inst = __opcode_to_mem_arm(inst);
224
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100225 if (ctx->target != NULL)
Ben Dooks34607432013-07-24 15:44:56 +0100226 ctx->target[ctx->idx] = inst;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100227
228 ctx->idx++;
229}
230
231/*
232 * Emit an instruction that will be executed unconditionally.
233 */
234static inline void emit(u32 inst, struct jit_ctx *ctx)
235{
236 _emit(ARM_COND_AL, inst, ctx);
237}
238
Shubham Bansal39c13c22017-08-22 12:02:33 +0530239/*
Russell King1ca3b172018-07-11 10:32:07 +0100240 * This is rather horrid, but necessary to convert an integer constant
241 * to an immediate operand for the opcodes, and be able to detect at
242 * build time whether the constant can't be converted (iow, usable in
243 * BUILD_BUG_ON()).
244 */
245#define imm12val(v, s) (rol32(v, (s)) | (s) << 7)
246#define const_imm8m(x) \
247 ({ int r; \
248 u32 v = (x); \
249 if (!(v & ~0x000000ff)) \
250 r = imm12val(v, 0); \
251 else if (!(v & ~0xc000003f)) \
252 r = imm12val(v, 2); \
253 else if (!(v & ~0xf000000f)) \
254 r = imm12val(v, 4); \
255 else if (!(v & ~0xfc000003)) \
256 r = imm12val(v, 6); \
257 else if (!(v & ~0xff000000)) \
258 r = imm12val(v, 8); \
259 else if (!(v & ~0x3fc00000)) \
260 r = imm12val(v, 10); \
261 else if (!(v & ~0x0ff00000)) \
262 r = imm12val(v, 12); \
263 else if (!(v & ~0x03fc0000)) \
264 r = imm12val(v, 14); \
265 else if (!(v & ~0x00ff0000)) \
266 r = imm12val(v, 16); \
267 else if (!(v & ~0x003fc000)) \
268 r = imm12val(v, 18); \
269 else if (!(v & ~0x000ff000)) \
270 r = imm12val(v, 20); \
271 else if (!(v & ~0x0003fc00)) \
272 r = imm12val(v, 22); \
273 else if (!(v & ~0x0000ff00)) \
274 r = imm12val(v, 24); \
275 else if (!(v & ~0x00003fc0)) \
276 r = imm12val(v, 26); \
277 else if (!(v & ~0x00000ff0)) \
278 r = imm12val(v, 28); \
279 else if (!(v & ~0x000003fc)) \
280 r = imm12val(v, 30); \
281 else \
282 r = -1; \
283 r; })
284
285/*
Shubham Bansal39c13c22017-08-22 12:02:33 +0530286 * Checks if immediate value can be converted to imm12(12 bits) value.
287 */
Russell King1ca3b172018-07-11 10:32:07 +0100288static int imm8m(u32 x)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100289{
Shubham Bansal39c13c22017-08-22 12:02:33 +0530290 u32 rot;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100291
Shubham Bansal39c13c22017-08-22 12:02:33 +0530292 for (rot = 0; rot < 16; rot++)
293 if ((x & ~ror32(0xff, 2 * rot)) == 0)
294 return rol32(x, 2 * rot) | (rot << 8);
295 return -1;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100296}
297
Russell King1ca3b172018-07-11 10:32:07 +0100298#define imm8m(x) (__builtin_constant_p(x) ? const_imm8m(x) : imm8m(x))
299
Russell Kinga8ef95a2018-07-11 10:31:36 +0100300static u32 arm_bpf_ldst_imm12(u32 op, u8 rt, u8 rn, s16 imm12)
301{
302 op |= rt << 12 | rn << 16;
303 if (imm12 >= 0)
304 op |= ARM_INST_LDST__U;
305 else
306 imm12 = -imm12;
Russell King828e2b92018-07-11 10:32:12 +0100307 return op | (imm12 & ARM_INST_LDST__IMM12);
Russell Kinga8ef95a2018-07-11 10:31:36 +0100308}
309
310static u32 arm_bpf_ldst_imm8(u32 op, u8 rt, u8 rn, s16 imm8)
311{
312 op |= rt << 12 | rn << 16;
313 if (imm8 >= 0)
314 op |= ARM_INST_LDST__U;
315 else
316 imm8 = -imm8;
317 return op | (imm8 & 0xf0) << 4 | (imm8 & 0x0f);
318}
319
320#define ARM_LDR_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_LDR_I, rt, rn, off)
321#define ARM_LDRB_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_LDRB_I, rt, rn, off)
322#define ARM_LDRH_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_LDRH_I, rt, rn, off)
323
324#define ARM_STR_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_STR_I, rt, rn, off)
325#define ARM_STRB_I(rt, rn, off) arm_bpf_ldst_imm12(ARM_INST_STRB_I, rt, rn, off)
326#define ARM_STRH_I(rt, rn, off) arm_bpf_ldst_imm8(ARM_INST_STRH_I, rt, rn, off)
327
Shubham Bansal39c13c22017-08-22 12:02:33 +0530328/*
329 * Initializes the JIT space with undefined instructions.
330 */
Daniel Borkmann55309dd2014-09-08 08:04:48 +0200331static void jit_fill_hole(void *area, unsigned int size)
332{
Daniel Borkmanne8b56d52014-09-19 14:56:57 +0200333 u32 *ptr;
Daniel Borkmann55309dd2014-09-08 08:04:48 +0200334 /* We are guaranteed to have aligned memory. */
335 for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
Daniel Borkmanne8b56d52014-09-19 14:56:57 +0200336 *ptr++ = __opcode_to_mem_arm(ARM_INST_UDF);
Daniel Borkmann55309dd2014-09-08 08:04:48 +0200337}
338
Russell Kingd1220ef2018-01-13 16:10:07 +0000339#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
340/* EABI requires the stack to be aligned to 64-bit boundaries */
341#define STACK_ALIGNMENT 8
342#else
343/* Stack must be aligned to 32-bit boundaries */
344#define STACK_ALIGNMENT 4
345#endif
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100346
Shubham Bansal39c13c22017-08-22 12:02:33 +0530347/* total stack size used in JITed code */
Daniel Borkmann38ca9302018-05-14 23:22:30 +0200348#define _STACK_SIZE (ctx->prog->aux->stack_depth + SCRATCH_SIZE)
349#define STACK_SIZE ALIGN(_STACK_SIZE, STACK_ALIGNMENT)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100350
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100351#if __LINUX_ARM_ARCH__ < 7
352
353static u16 imm_offset(u32 k, struct jit_ctx *ctx)
354{
Shubham Bansal39c13c22017-08-22 12:02:33 +0530355 unsigned int i = 0, offset;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100356 u16 imm;
357
358 /* on the "fake" run we just count them (duplicates included) */
359 if (ctx->target == NULL) {
360 ctx->imm_count++;
361 return 0;
362 }
363
364 while ((i < ctx->imm_count) && ctx->imms[i]) {
365 if (ctx->imms[i] == k)
366 break;
367 i++;
368 }
369
370 if (ctx->imms[i] == 0)
371 ctx->imms[i] = k;
372
373 /* constants go just after the epilogue */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530374 offset = ctx->offsets[ctx->prog->len - 1] * 4;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100375 offset += ctx->prologue_bytes;
376 offset += ctx->epilogue_bytes;
377 offset += i * 4;
378
379 ctx->target[offset / 4] = k;
380
381 /* PC in ARM mode == address of the instruction + 8 */
382 imm = offset - (8 + ctx->idx * 4);
383
Nicolas Schichan0b59d882015-05-07 17:14:21 +0200384 if (imm & ~0xfff) {
385 /*
386 * literal pool is too far, signal it into flags. we
387 * can only detect it on the second pass unfortunately.
388 */
389 ctx->flags |= FLAG_IMM_OVERFLOW;
390 return 0;
391 }
392
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100393 return imm;
394}
395
396#endif /* __LINUX_ARM_ARCH__ */
397
Shubham Bansal39c13c22017-08-22 12:02:33 +0530398static inline int bpf2a32_offset(int bpf_to, int bpf_from,
399 const struct jit_ctx *ctx) {
400 int to, from;
401
402 if (ctx->target == NULL)
403 return 0;
404 to = ctx->offsets[bpf_to];
405 from = ctx->offsets[bpf_from];
406
407 return to - from - 1;
408}
409
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100410/*
411 * Move an immediate that's not an imm8m to a core register.
412 */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530413static inline void emit_mov_i_no8m(const u8 rd, u32 val, struct jit_ctx *ctx)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100414{
415#if __LINUX_ARM_ARCH__ < 7
416 emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx);
417#else
418 emit(ARM_MOVW(rd, val & 0xffff), ctx);
419 if (val > 0xffff)
420 emit(ARM_MOVT(rd, val >> 16), ctx);
421#endif
422}
423
Shubham Bansal39c13c22017-08-22 12:02:33 +0530424static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100425{
426 int imm12 = imm8m(val);
427
428 if (imm12 >= 0)
429 emit(ARM_MOV_I(rd, imm12), ctx);
430 else
431 emit_mov_i_no8m(rd, val, ctx);
432}
433
Russell Kinge9062482018-01-13 11:35:15 +0000434static void emit_bx_r(u8 tgt_reg, struct jit_ctx *ctx)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100435{
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100436 if (elf_hwcap & HWCAP_THUMB)
437 emit(ARM_BX(tgt_reg), ctx);
438 else
439 emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
Russell Kinge9062482018-01-13 11:35:15 +0000440}
441
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100442static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
443{
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100444#if __LINUX_ARM_ARCH__ < 5
445 emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
Russell Kinge9062482018-01-13 11:35:15 +0000446 emit_bx_r(tgt_reg, ctx);
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100447#else
448 emit(ARM_BLX_R(tgt_reg), ctx);
449#endif
450}
451
Shubham Bansal39c13c22017-08-22 12:02:33 +0530452static inline int epilogue_offset(const struct jit_ctx *ctx)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100453{
Shubham Bansal39c13c22017-08-22 12:02:33 +0530454 int to, from;
455 /* No need for 1st dummy run */
456 if (ctx->target == NULL)
457 return 0;
458 to = ctx->epilogue_offset;
459 from = ctx->idx;
460
461 return to - from - 2;
462}
463
464static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
465{
Russell King1c35ba12018-07-11 10:31:41 +0100466 const s8 *tmp = bpf2a32[TMP_REG_1];
Shubham Bansal39c13c22017-08-22 12:02:33 +0530467
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100468#if __LINUX_ARM_ARCH__ == 7
469 if (elf_hwcap & HWCAP_IDIVA) {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530470 if (op == BPF_DIV)
Nicolas Schichan4560cdf2015-10-02 17:06:47 +0200471 emit(ARM_UDIV(rd, rm, rn), ctx);
472 else {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530473 emit(ARM_UDIV(ARM_IP, rm, rn), ctx);
474 emit(ARM_MLS(rd, rn, ARM_IP, rm), ctx);
Nicolas Schichan4560cdf2015-10-02 17:06:47 +0200475 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100476 return;
477 }
478#endif
Nicolas Schichan19fc99d2015-05-06 18:31:56 +0200479
480 /*
Shubham Bansal39c13c22017-08-22 12:02:33 +0530481 * For BPF_ALU | BPF_DIV | BPF_K instructions
482 * As ARM_R1 and ARM_R0 contains 1st argument of bpf
483 * function, we need to save it on caller side to save
484 * it from getting destroyed within callee.
485 * After the return from the callee, we restore ARM_R0
486 * ARM_R1.
Nicolas Schichan19fc99d2015-05-06 18:31:56 +0200487 */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530488 if (rn != ARM_R1) {
489 emit(ARM_MOV_R(tmp[0], ARM_R1), ctx);
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100490 emit(ARM_MOV_R(ARM_R1, rn), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530491 }
492 if (rm != ARM_R0) {
493 emit(ARM_MOV_R(tmp[1], ARM_R0), ctx);
Nicolas Schichan19fc99d2015-05-06 18:31:56 +0200494 emit(ARM_MOV_R(ARM_R0, rm), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530495 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100496
Shubham Bansal39c13c22017-08-22 12:02:33 +0530497 /* Call appropriate function */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530498 emit_mov_i(ARM_IP, op == BPF_DIV ?
499 (u32)jit_udiv32 : (u32)jit_mod32, ctx);
500 emit_blx_r(ARM_IP, ctx);
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100501
Shubham Bansal39c13c22017-08-22 12:02:33 +0530502 /* Save return value */
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100503 if (rd != ARM_R0)
504 emit(ARM_MOV_R(rd, ARM_R0), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530505
506 /* Restore ARM_R0 and ARM_R1 */
507 if (rn != ARM_R1)
508 emit(ARM_MOV_R(ARM_R1, tmp[0]), ctx);
509 if (rm != ARM_R0)
510 emit(ARM_MOV_R(ARM_R0, tmp[1]), ctx);
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100511}
512
Russell King47b9c3bf2018-07-11 10:31:47 +0100513/* Is the translated BPF register on stack? */
514static bool is_stacked(s8 reg)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +0100515{
Russell King47b9c3bf2018-07-11 10:31:47 +0100516 return reg < 0;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530517}
518
Russell King7a987022018-07-11 10:31:52 +0100519/* If a BPF register is on the stack (stk is true), load it to the
520 * supplied temporary register and return the temporary register
521 * for subsequent operations, otherwise just use the CPU register.
522 */
523static s8 arm_bpf_get_reg32(s8 reg, s8 tmp, struct jit_ctx *ctx)
524{
525 if (is_stacked(reg)) {
Russell King96cced42018-07-11 10:32:02 +0100526 emit(ARM_LDR_I(tmp, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg)), ctx);
Russell King7a987022018-07-11 10:31:52 +0100527 reg = tmp;
528 }
529 return reg;
530}
531
Russell Kinga6eccac2018-07-11 10:31:57 +0100532static const s8 *arm_bpf_get_reg64(const s8 *reg, const s8 *tmp,
533 struct jit_ctx *ctx)
534{
535 if (is_stacked(reg[1])) {
Russell King96cced42018-07-11 10:32:02 +0100536 emit(ARM_LDR_I(tmp[1], ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg[1])),
537 ctx);
538 emit(ARM_LDR_I(tmp[0], ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg[0])),
539 ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100540 reg = tmp;
541 }
542 return reg;
543}
544
Russell King7a987022018-07-11 10:31:52 +0100545/* If a BPF register is on the stack (stk is true), save the register
546 * back to the stack. If the source register is not the same, then
547 * move it into the correct register.
548 */
549static void arm_bpf_put_reg32(s8 reg, s8 src, struct jit_ctx *ctx)
550{
551 if (is_stacked(reg))
Russell King96cced42018-07-11 10:32:02 +0100552 emit(ARM_STR_I(src, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg)), ctx);
Russell King7a987022018-07-11 10:31:52 +0100553 else if (reg != src)
554 emit(ARM_MOV_R(reg, src), ctx);
555}
556
Russell Kinga6eccac2018-07-11 10:31:57 +0100557static void arm_bpf_put_reg64(const s8 *reg, const s8 *src,
558 struct jit_ctx *ctx)
559{
560 if (is_stacked(reg[1])) {
Russell King96cced42018-07-11 10:32:02 +0100561 emit(ARM_STR_I(src[1], ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg[1])),
562 ctx);
563 emit(ARM_STR_I(src[0], ARM_FP, EBPF_SCRATCH_TO_ARM_FP(reg[0])),
564 ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100565 } else {
566 if (reg[1] != src[1])
567 emit(ARM_MOV_R(reg[1], src[1]), ctx);
568 if (reg[0] != src[0])
569 emit(ARM_MOV_R(reg[0], src[0]), ctx);
570 }
571}
572
Russell King1c35ba12018-07-11 10:31:41 +0100573static inline void emit_a32_mov_i(const s8 dst, const u32 val,
Russell King47b9c3bf2018-07-11 10:31:47 +0100574 struct jit_ctx *ctx)
Shubham Bansal39c13c22017-08-22 12:02:33 +0530575{
Russell King1c35ba12018-07-11 10:31:41 +0100576 const s8 *tmp = bpf2a32[TMP_REG_1];
Shubham Bansal39c13c22017-08-22 12:02:33 +0530577
Russell King47b9c3bf2018-07-11 10:31:47 +0100578 if (is_stacked(dst)) {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530579 emit_mov_i(tmp[1], val, ctx);
Russell King7a987022018-07-11 10:31:52 +0100580 arm_bpf_put_reg32(dst, tmp[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530581 } else {
582 emit_mov_i(dst, val, ctx);
583 }
584}
585
586/* Sign extended move */
Russell King1c35ba12018-07-11 10:31:41 +0100587static inline void emit_a32_mov_i64(const bool is64, const s8 dst[],
Russell King47b9c3bf2018-07-11 10:31:47 +0100588 const u32 val, struct jit_ctx *ctx) {
Shubham Bansal39c13c22017-08-22 12:02:33 +0530589 u32 hi = 0;
590
591 if (is64 && (val & (1<<31)))
592 hi = (u32)~0;
Russell King47b9c3bf2018-07-11 10:31:47 +0100593 emit_a32_mov_i(dst_lo, val, ctx);
594 emit_a32_mov_i(dst_hi, hi, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530595}
596
597static inline void emit_a32_add_r(const u8 dst, const u8 src,
598 const bool is64, const bool hi,
599 struct jit_ctx *ctx) {
600 /* 64 bit :
601 * adds dst_lo, dst_lo, src_lo
602 * adc dst_hi, dst_hi, src_hi
603 * 32 bit :
604 * add dst_lo, dst_lo, src_lo
605 */
606 if (!hi && is64)
607 emit(ARM_ADDS_R(dst, dst, src), ctx);
608 else if (hi && is64)
609 emit(ARM_ADC_R(dst, dst, src), ctx);
610 else
611 emit(ARM_ADD_R(dst, dst, src), ctx);
612}
613
614static inline void emit_a32_sub_r(const u8 dst, const u8 src,
615 const bool is64, const bool hi,
616 struct jit_ctx *ctx) {
617 /* 64 bit :
618 * subs dst_lo, dst_lo, src_lo
619 * sbc dst_hi, dst_hi, src_hi
620 * 32 bit :
621 * sub dst_lo, dst_lo, src_lo
622 */
623 if (!hi && is64)
624 emit(ARM_SUBS_R(dst, dst, src), ctx);
625 else if (hi && is64)
626 emit(ARM_SBC_R(dst, dst, src), ctx);
627 else
628 emit(ARM_SUB_R(dst, dst, src), ctx);
629}
630
631static inline void emit_alu_r(const u8 dst, const u8 src, const bool is64,
632 const bool hi, const u8 op, struct jit_ctx *ctx){
633 switch (BPF_OP(op)) {
634 /* dst = dst + src */
635 case BPF_ADD:
636 emit_a32_add_r(dst, src, is64, hi, ctx);
637 break;
638 /* dst = dst - src */
639 case BPF_SUB:
640 emit_a32_sub_r(dst, src, is64, hi, ctx);
641 break;
642 /* dst = dst | src */
643 case BPF_OR:
644 emit(ARM_ORR_R(dst, dst, src), ctx);
645 break;
646 /* dst = dst & src */
647 case BPF_AND:
648 emit(ARM_AND_R(dst, dst, src), ctx);
649 break;
650 /* dst = dst ^ src */
651 case BPF_XOR:
652 emit(ARM_EOR_R(dst, dst, src), ctx);
653 break;
654 /* dst = dst * src */
655 case BPF_MUL:
656 emit(ARM_MUL(dst, dst, src), ctx);
657 break;
658 /* dst = dst << src */
659 case BPF_LSH:
660 emit(ARM_LSL_R(dst, dst, src), ctx);
661 break;
662 /* dst = dst >> src */
663 case BPF_RSH:
664 emit(ARM_LSR_R(dst, dst, src), ctx);
665 break;
666 /* dst = dst >> src (signed)*/
667 case BPF_ARSH:
668 emit(ARM_MOV_SR(dst, dst, SRTYPE_ASR, src), ctx);
669 break;
670 }
671}
672
673/* ALU operation (32 bit)
674 * dst = dst (op) src
675 */
Russell King1c35ba12018-07-11 10:31:41 +0100676static inline void emit_a32_alu_r(const s8 dst, const s8 src,
Shubham Bansal39c13c22017-08-22 12:02:33 +0530677 struct jit_ctx *ctx, const bool is64,
678 const bool hi, const u8 op) {
Russell King1c35ba12018-07-11 10:31:41 +0100679 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell King7a987022018-07-11 10:31:52 +0100680 s8 rn, rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530681
Russell King7a987022018-07-11 10:31:52 +0100682 rn = arm_bpf_get_reg32(src, tmp[1], ctx);
683 rd = arm_bpf_get_reg32(dst, tmp[0], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530684 /* ALU operation */
Russell King7a987022018-07-11 10:31:52 +0100685 emit_alu_r(rd, rn, is64, hi, op, ctx);
686 arm_bpf_put_reg32(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530687}
688
689/* ALU operation (64 bit) */
Russell King1c35ba12018-07-11 10:31:41 +0100690static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
Russell King47b9c3bf2018-07-11 10:31:47 +0100691 const s8 src[], struct jit_ctx *ctx,
Shubham Bansal39c13c22017-08-22 12:02:33 +0530692 const u8 op) {
Russell King47b9c3bf2018-07-11 10:31:47 +0100693 emit_a32_alu_r(dst_lo, src_lo, ctx, is64, false, op);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530694 if (is64)
Russell King47b9c3bf2018-07-11 10:31:47 +0100695 emit_a32_alu_r(dst_hi, src_hi, ctx, is64, true, op);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530696 else
Russell King47b9c3bf2018-07-11 10:31:47 +0100697 emit_a32_mov_i(dst_hi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530698}
699
Russell King7a987022018-07-11 10:31:52 +0100700/* dst = src (4 bytes)*/
Russell King1c35ba12018-07-11 10:31:41 +0100701static inline void emit_a32_mov_r(const s8 dst, const s8 src,
Shubham Bansal39c13c22017-08-22 12:02:33 +0530702 struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100703 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell King7a987022018-07-11 10:31:52 +0100704 s8 rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530705
Russell King7a987022018-07-11 10:31:52 +0100706 rt = arm_bpf_get_reg32(src, tmp[0], ctx);
707 arm_bpf_put_reg32(dst, rt, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530708}
709
710/* dst = src */
Russell King1c35ba12018-07-11 10:31:41 +0100711static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
Russell King47b9c3bf2018-07-11 10:31:47 +0100712 const s8 src[],
713 struct jit_ctx *ctx) {
714 emit_a32_mov_r(dst_lo, src_lo, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530715 if (is64) {
716 /* complete 8 byte move */
Russell King47b9c3bf2018-07-11 10:31:47 +0100717 emit_a32_mov_r(dst_hi, src_hi, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530718 } else {
719 /* Zero out high 4 bytes */
Russell King47b9c3bf2018-07-11 10:31:47 +0100720 emit_a32_mov_i(dst_hi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530721 }
722}
723
724/* Shift operations */
Russell King47b9c3bf2018-07-11 10:31:47 +0100725static inline void emit_a32_alu_i(const s8 dst, const u32 val,
Shubham Bansal39c13c22017-08-22 12:02:33 +0530726 struct jit_ctx *ctx, const u8 op) {
Russell King1c35ba12018-07-11 10:31:41 +0100727 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell King7a987022018-07-11 10:31:52 +0100728 s8 rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530729
Russell King7a987022018-07-11 10:31:52 +0100730 rd = arm_bpf_get_reg32(dst, tmp[0], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530731
732 /* Do shift operation */
733 switch (op) {
734 case BPF_LSH:
735 emit(ARM_LSL_I(rd, rd, val), ctx);
736 break;
737 case BPF_RSH:
738 emit(ARM_LSR_I(rd, rd, val), ctx);
739 break;
740 case BPF_NEG:
741 emit(ARM_RSB_I(rd, rd, val), ctx);
742 break;
743 }
744
Russell King7a987022018-07-11 10:31:52 +0100745 arm_bpf_put_reg32(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530746}
747
748/* dst = ~dst (64 bit) */
Russell King47b9c3bf2018-07-11 10:31:47 +0100749static inline void emit_a32_neg64(const s8 dst[],
Shubham Bansal39c13c22017-08-22 12:02:33 +0530750 struct jit_ctx *ctx){
Russell King1c35ba12018-07-11 10:31:41 +0100751 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell Kinga6eccac2018-07-11 10:31:57 +0100752 const s8 *rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530753
754 /* Setup Operand */
Russell Kinga6eccac2018-07-11 10:31:57 +0100755 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530756
757 /* Do Negate Operation */
Russell Kinga6eccac2018-07-11 10:31:57 +0100758 emit(ARM_RSBS_I(rd[1], rd[1], 0), ctx);
759 emit(ARM_RSC_I(rd[0], rd[0], 0), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530760
Russell Kinga6eccac2018-07-11 10:31:57 +0100761 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530762}
763
764/* dst = dst << src */
Russell King47b9c3bf2018-07-11 10:31:47 +0100765static inline void emit_a32_lsh_r64(const s8 dst[], const s8 src[],
766 struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100767 const s8 *tmp = bpf2a32[TMP_REG_1];
768 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100769 const s8 *rd;
770 s8 rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530771
772 /* Setup Operands */
Russell King7a987022018-07-11 10:31:52 +0100773 rt = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100774 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530775
776 /* Do LSH operation */
777 emit(ARM_SUB_I(ARM_IP, rt, 32), ctx);
778 emit(ARM_RSB_I(tmp2[0], rt, 32), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100779 emit(ARM_MOV_SR(ARM_LR, rd[0], SRTYPE_ASL, rt), ctx);
780 emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[1], SRTYPE_ASL, ARM_IP), ctx);
781 emit(ARM_ORR_SR(ARM_IP, ARM_LR, rd[1], SRTYPE_LSR, tmp2[0]), ctx);
782 emit(ARM_MOV_SR(ARM_LR, rd[1], SRTYPE_ASL, rt), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530783
Russell King7a987022018-07-11 10:31:52 +0100784 arm_bpf_put_reg32(dst_lo, ARM_LR, ctx);
785 arm_bpf_put_reg32(dst_hi, ARM_IP, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530786}
787
788/* dst = dst >> src (signed)*/
Russell King47b9c3bf2018-07-11 10:31:47 +0100789static inline void emit_a32_arsh_r64(const s8 dst[], const s8 src[],
790 struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100791 const s8 *tmp = bpf2a32[TMP_REG_1];
792 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100793 const s8 *rd;
794 s8 rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530795
Russell King7a987022018-07-11 10:31:52 +0100796 /* Setup Operands */
797 rt = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100798 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530799
800 /* Do the ARSH operation */
801 emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
802 emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100803 emit(ARM_MOV_SR(ARM_LR, rd[1], SRTYPE_LSR, rt), ctx);
804 emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASL, ARM_IP), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530805 _emit(ARM_COND_MI, ARM_B(0), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100806 emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASR, tmp2[0]), ctx);
807 emit(ARM_MOV_SR(ARM_IP, rd[0], SRTYPE_ASR, rt), ctx);
Russell King7a987022018-07-11 10:31:52 +0100808
809 arm_bpf_put_reg32(dst_lo, ARM_LR, ctx);
810 arm_bpf_put_reg32(dst_hi, ARM_IP, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530811}
812
813/* dst = dst >> src */
Russell King47b9c3bf2018-07-11 10:31:47 +0100814static inline void emit_a32_rsh_r64(const s8 dst[], const s8 src[],
815 struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100816 const s8 *tmp = bpf2a32[TMP_REG_1];
817 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100818 const s8 *rd;
819 s8 rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530820
Russell King7a987022018-07-11 10:31:52 +0100821 /* Setup Operands */
822 rt = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100823 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530824
Wang YanQing68565a12018-05-11 10:52:17 +0800825 /* Do RSH operation */
Shubham Bansal39c13c22017-08-22 12:02:33 +0530826 emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
827 emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100828 emit(ARM_MOV_SR(ARM_LR, rd[1], SRTYPE_LSR, rt), ctx);
829 emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASL, ARM_IP), ctx);
830 emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_LSR, tmp2[0]), ctx);
831 emit(ARM_MOV_SR(ARM_IP, rd[0], SRTYPE_LSR, rt), ctx);
Russell King7a987022018-07-11 10:31:52 +0100832
833 arm_bpf_put_reg32(dst_lo, ARM_LR, ctx);
834 arm_bpf_put_reg32(dst_hi, ARM_IP, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530835}
836
837/* dst = dst << val */
Russell King47b9c3bf2018-07-11 10:31:47 +0100838static inline void emit_a32_lsh_i64(const s8 dst[],
839 const u32 val, struct jit_ctx *ctx){
Russell King1c35ba12018-07-11 10:31:41 +0100840 const s8 *tmp = bpf2a32[TMP_REG_1];
841 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100842 const s8 *rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530843
Russell King7a987022018-07-11 10:31:52 +0100844 /* Setup operands */
Russell Kinga6eccac2018-07-11 10:31:57 +0100845 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530846
847 /* Do LSH operation */
848 if (val < 32) {
Russell Kinga6eccac2018-07-11 10:31:57 +0100849 emit(ARM_MOV_SI(tmp2[0], rd[0], SRTYPE_ASL, val), ctx);
850 emit(ARM_ORR_SI(rd[0], tmp2[0], rd[1], SRTYPE_LSR, 32 - val), ctx);
851 emit(ARM_MOV_SI(rd[1], rd[1], SRTYPE_ASL, val), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530852 } else {
853 if (val == 32)
Russell Kinga6eccac2018-07-11 10:31:57 +0100854 emit(ARM_MOV_R(rd[0], rd[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530855 else
Russell Kinga6eccac2018-07-11 10:31:57 +0100856 emit(ARM_MOV_SI(rd[0], rd[1], SRTYPE_ASL, val - 32), ctx);
857 emit(ARM_EOR_R(rd[1], rd[1], rd[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530858 }
859
Russell Kinga6eccac2018-07-11 10:31:57 +0100860 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530861}
862
863/* dst = dst >> val */
Russell King47b9c3bf2018-07-11 10:31:47 +0100864static inline void emit_a32_rsh_i64(const s8 dst[],
Shubham Bansal39c13c22017-08-22 12:02:33 +0530865 const u32 val, struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100866 const s8 *tmp = bpf2a32[TMP_REG_1];
867 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100868 const s8 *rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530869
Russell King7a987022018-07-11 10:31:52 +0100870 /* Setup operands */
Russell Kinga6eccac2018-07-11 10:31:57 +0100871 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530872
873 /* Do LSR operation */
874 if (val < 32) {
Russell Kinga6eccac2018-07-11 10:31:57 +0100875 emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
876 emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
877 emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530878 } else if (val == 32) {
Russell Kinga6eccac2018-07-11 10:31:57 +0100879 emit(ARM_MOV_R(rd[1], rd[0]), ctx);
880 emit(ARM_MOV_I(rd[0], 0), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530881 } else {
Russell Kinga6eccac2018-07-11 10:31:57 +0100882 emit(ARM_MOV_SI(rd[1], rd[0], SRTYPE_LSR, val - 32), ctx);
883 emit(ARM_MOV_I(rd[0], 0), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530884 }
885
Russell Kinga6eccac2018-07-11 10:31:57 +0100886 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530887}
888
889/* dst = dst >> val (signed) */
Russell King47b9c3bf2018-07-11 10:31:47 +0100890static inline void emit_a32_arsh_i64(const s8 dst[],
Shubham Bansal39c13c22017-08-22 12:02:33 +0530891 const u32 val, struct jit_ctx *ctx){
Russell King1c35ba12018-07-11 10:31:41 +0100892 const s8 *tmp = bpf2a32[TMP_REG_1];
893 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100894 const s8 *rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530895
Russell King7a987022018-07-11 10:31:52 +0100896 /* Setup operands */
Russell Kinga6eccac2018-07-11 10:31:57 +0100897 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530898
899 /* Do ARSH operation */
900 if (val < 32) {
Russell Kinga6eccac2018-07-11 10:31:57 +0100901 emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
902 emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
903 emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530904 } else if (val == 32) {
Russell Kinga6eccac2018-07-11 10:31:57 +0100905 emit(ARM_MOV_R(rd[1], rd[0]), ctx);
906 emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, 31), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530907 } else {
Russell Kinga6eccac2018-07-11 10:31:57 +0100908 emit(ARM_MOV_SI(rd[1], rd[0], SRTYPE_ASR, val - 32), ctx);
909 emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, 31), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530910 }
911
Russell Kinga6eccac2018-07-11 10:31:57 +0100912 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530913}
914
Russell King47b9c3bf2018-07-11 10:31:47 +0100915static inline void emit_a32_mul_r64(const s8 dst[], const s8 src[],
916 struct jit_ctx *ctx) {
Russell King1c35ba12018-07-11 10:31:41 +0100917 const s8 *tmp = bpf2a32[TMP_REG_1];
918 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell Kinga6eccac2018-07-11 10:31:57 +0100919 const s8 *rd, *rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530920
Russell King7a987022018-07-11 10:31:52 +0100921 /* Setup operands for multiplication */
Russell Kinga6eccac2018-07-11 10:31:57 +0100922 rd = arm_bpf_get_reg64(dst, tmp, ctx);
923 rt = arm_bpf_get_reg64(src, tmp2, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530924
925 /* Do Multiplication */
Russell Kinga6eccac2018-07-11 10:31:57 +0100926 emit(ARM_MUL(ARM_IP, rd[1], rt[0]), ctx);
927 emit(ARM_MUL(ARM_LR, rd[0], rt[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530928 emit(ARM_ADD_R(ARM_LR, ARM_IP, ARM_LR), ctx);
929
Russell Kinga6eccac2018-07-11 10:31:57 +0100930 emit(ARM_UMULL(ARM_IP, rd[0], rd[1], rt[1]), ctx);
931 emit(ARM_ADD_R(rd[0], ARM_LR, rd[0]), ctx);
Russell King7a987022018-07-11 10:31:52 +0100932
933 arm_bpf_put_reg32(dst_lo, ARM_IP, ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100934 arm_bpf_put_reg32(dst_hi, rd[0], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530935}
936
937/* *(size *)(dst + off) = src */
Russell King47b9c3bf2018-07-11 10:31:47 +0100938static inline void emit_str_r(const s8 dst, const s8 src,
Shubham Bansal39c13c22017-08-22 12:02:33 +0530939 const s32 off, struct jit_ctx *ctx, const u8 sz){
Russell King1c35ba12018-07-11 10:31:41 +0100940 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell King7a987022018-07-11 10:31:52 +0100941 s8 rd;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530942
Russell King7a987022018-07-11 10:31:52 +0100943 rd = arm_bpf_get_reg32(dst, tmp[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530944 if (off) {
Russell King47b9c3bf2018-07-11 10:31:47 +0100945 emit_a32_mov_i(tmp[0], off, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530946 emit(ARM_ADD_R(tmp[0], rd, tmp[0]), ctx);
947 rd = tmp[0];
948 }
949 switch (sz) {
950 case BPF_W:
951 /* Store a Word */
952 emit(ARM_STR_I(src, rd, 0), ctx);
953 break;
954 case BPF_H:
955 /* Store a HalfWord */
956 emit(ARM_STRH_I(src, rd, 0), ctx);
957 break;
958 case BPF_B:
959 /* Store a Byte */
960 emit(ARM_STRB_I(src, rd, 0), ctx);
961 break;
962 }
963}
964
965/* dst = *(size*)(src + off) */
Russell King47b9c3bf2018-07-11 10:31:47 +0100966static inline void emit_ldx_r(const s8 dst[], const s8 src,
Russell Kingec19e022018-01-13 21:06:16 +0000967 s32 off, struct jit_ctx *ctx, const u8 sz){
Russell King1c35ba12018-07-11 10:31:41 +0100968 const s8 *tmp = bpf2a32[TMP_REG_1];
Russell King47b9c3bf2018-07-11 10:31:47 +0100969 const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
Russell King1c35ba12018-07-11 10:31:41 +0100970 s8 rm = src;
Russell Kingec19e022018-01-13 21:06:16 +0000971 s32 off_max;
Shubham Bansal39c13c22017-08-22 12:02:33 +0530972
Russell Kingec19e022018-01-13 21:06:16 +0000973 if (sz == BPF_H)
974 off_max = 0xff;
975 else
976 off_max = 0xfff;
977
978 if (off < 0 || off > off_max) {
Russell King47b9c3bf2018-07-11 10:31:47 +0100979 emit_a32_mov_i(tmp[0], off, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530980 emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
981 rm = tmp[0];
Russell Kingec19e022018-01-13 21:06:16 +0000982 off = 0;
983 } else if (rd[1] == rm) {
984 emit(ARM_MOV_R(tmp[0], rm), ctx);
985 rm = tmp[0];
Shubham Bansal39c13c22017-08-22 12:02:33 +0530986 }
987 switch (sz) {
Russell Kingec19e022018-01-13 21:06:16 +0000988 case BPF_B:
989 /* Load a Byte */
990 emit(ARM_LDRB_I(rd[1], rm, off), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100991 emit_a32_mov_i(rd[0], 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530992 break;
993 case BPF_H:
994 /* Load a HalfWord */
Russell Kingec19e022018-01-13 21:06:16 +0000995 emit(ARM_LDRH_I(rd[1], rm, off), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +0100996 emit_a32_mov_i(rd[0], 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +0530997 break;
Russell Kingec19e022018-01-13 21:06:16 +0000998 case BPF_W:
999 /* Load a Word */
1000 emit(ARM_LDR_I(rd[1], rm, off), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +01001001 emit_a32_mov_i(rd[0], 0, ctx);
Russell Kingec19e022018-01-13 21:06:16 +00001002 break;
1003 case BPF_DW:
1004 /* Load a Double Word */
1005 emit(ARM_LDR_I(rd[1], rm, off), ctx);
1006 emit(ARM_LDR_I(rd[0], rm, off + 4), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301007 break;
1008 }
Russell Kinga6eccac2018-07-11 10:31:57 +01001009 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301010}
1011
1012/* Arithmatic Operation */
1013static inline void emit_ar_r(const u8 rd, const u8 rt, const u8 rm,
1014 const u8 rn, struct jit_ctx *ctx, u8 op) {
1015 switch (op) {
1016 case BPF_JSET:
Shubham Bansal39c13c22017-08-22 12:02:33 +05301017 emit(ARM_AND_R(ARM_IP, rt, rn), ctx);
1018 emit(ARM_AND_R(ARM_LR, rd, rm), ctx);
1019 emit(ARM_ORRS_R(ARM_IP, ARM_LR, ARM_IP), ctx);
1020 break;
1021 case BPF_JEQ:
1022 case BPF_JNE:
1023 case BPF_JGT:
1024 case BPF_JGE:
1025 case BPF_JLE:
1026 case BPF_JLT:
1027 emit(ARM_CMP_R(rd, rm), ctx);
1028 _emit(ARM_COND_EQ, ARM_CMP_R(rt, rn), ctx);
1029 break;
1030 case BPF_JSLE:
1031 case BPF_JSGT:
1032 emit(ARM_CMP_R(rn, rt), ctx);
1033 emit(ARM_SBCS_R(ARM_IP, rm, rd), ctx);
1034 break;
1035 case BPF_JSLT:
1036 case BPF_JSGE:
1037 emit(ARM_CMP_R(rt, rn), ctx);
1038 emit(ARM_SBCS_R(ARM_IP, rd, rm), ctx);
1039 break;
1040 }
1041}
1042
1043static int out_offset = -1; /* initialized on the first pass of build_body() */
1044static int emit_bpf_tail_call(struct jit_ctx *ctx)
1045{
1046
1047 /* bpf_tail_call(void *prog_ctx, struct bpf_array *array, u64 index) */
Russell King1c35ba12018-07-11 10:31:41 +01001048 const s8 *r2 = bpf2a32[BPF_REG_2];
1049 const s8 *r3 = bpf2a32[BPF_REG_3];
1050 const s8 *tmp = bpf2a32[TMP_REG_1];
1051 const s8 *tmp2 = bpf2a32[TMP_REG_2];
1052 const s8 *tcc = bpf2a32[TCALL_CNT];
Russell Kinga6eccac2018-07-11 10:31:57 +01001053 const s8 *tc;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301054 const int idx0 = ctx->idx;
1055#define cur_offset (ctx->idx - idx0)
Russell Kingf4483f22018-01-13 11:39:54 +00001056#define jmp_offset (out_offset - (cur_offset) - 2)
Russell King828e2b92018-07-11 10:32:12 +01001057 u32 lo, hi;
Russell Kinga6eccac2018-07-11 10:31:57 +01001058 s8 r_array, r_index;
Russell King828e2b92018-07-11 10:32:12 +01001059 int off;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301060
1061 /* if (index >= array->map.max_entries)
1062 * goto out;
1063 */
Russell King828e2b92018-07-11 10:32:12 +01001064 BUILD_BUG_ON(offsetof(struct bpf_array, map.max_entries) >
1065 ARM_INST_LDST__IMM12);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301066 off = offsetof(struct bpf_array, map.max_entries);
1067 /* array->map.max_entries */
Russell King7a987022018-07-11 10:31:52 +01001068 r_array = arm_bpf_get_reg32(r2[1], tmp2[1], ctx);
Russell King828e2b92018-07-11 10:32:12 +01001069 emit(ARM_LDR_I(tmp[1], r_array, off), ctx);
Russell King091f0242018-01-13 12:11:26 +00001070 /* index is 32-bit for arrays */
Russell King7a987022018-07-11 10:31:52 +01001071 r_index = arm_bpf_get_reg32(r3[1], tmp2[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301072 /* index >= array->map.max_entries */
Russell King7a987022018-07-11 10:31:52 +01001073 emit(ARM_CMP_R(r_index, tmp[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301074 _emit(ARM_COND_CS, ARM_B(jmp_offset), ctx);
1075
1076 /* if (tail_call_cnt > MAX_TAIL_CALL_CNT)
1077 * goto out;
1078 * tail_call_cnt++;
1079 */
1080 lo = (u32)MAX_TAIL_CALL_CNT;
1081 hi = (u32)((u64)MAX_TAIL_CALL_CNT >> 32);
Russell Kinga6eccac2018-07-11 10:31:57 +01001082 tc = arm_bpf_get_reg64(tcc, tmp, ctx);
1083 emit(ARM_CMP_I(tc[0], hi), ctx);
1084 _emit(ARM_COND_EQ, ARM_CMP_I(tc[1], lo), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301085 _emit(ARM_COND_HI, ARM_B(jmp_offset), ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +01001086 emit(ARM_ADDS_I(tc[1], tc[1], 1), ctx);
1087 emit(ARM_ADC_I(tc[0], tc[0], 0), ctx);
1088 arm_bpf_put_reg64(tcc, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301089
1090 /* prog = array->ptrs[index]
1091 * if (prog == NULL)
1092 * goto out;
1093 */
Russell King828e2b92018-07-11 10:32:12 +01001094 BUILD_BUG_ON(imm8m(offsetof(struct bpf_array, ptrs)) < 0);
1095 off = imm8m(offsetof(struct bpf_array, ptrs));
Russell King7a987022018-07-11 10:31:52 +01001096 r_array = arm_bpf_get_reg32(r2[1], tmp2[1], ctx);
Russell King828e2b92018-07-11 10:32:12 +01001097 emit(ARM_ADD_I(tmp[1], r_array, off), ctx);
Russell King7a987022018-07-11 10:31:52 +01001098 r_index = arm_bpf_get_reg32(r3[1], tmp2[1], ctx);
1099 emit(ARM_MOV_SI(tmp[0], r_index, SRTYPE_ASL, 2), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301100 emit(ARM_LDR_R(tmp[1], tmp[1], tmp[0]), ctx);
1101 emit(ARM_CMP_I(tmp[1], 0), ctx);
1102 _emit(ARM_COND_EQ, ARM_B(jmp_offset), ctx);
1103
1104 /* goto *(prog->bpf_func + prologue_size); */
Russell King828e2b92018-07-11 10:32:12 +01001105 BUILD_BUG_ON(offsetof(struct bpf_prog, bpf_func) >
1106 ARM_INST_LDST__IMM12);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301107 off = offsetof(struct bpf_prog, bpf_func);
Russell King828e2b92018-07-11 10:32:12 +01001108 emit(ARM_LDR_I(tmp[1], tmp[1], off), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301109 emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx);
Russell Kinge9062482018-01-13 11:35:15 +00001110 emit_bx_r(tmp[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301111
1112 /* out: */
1113 if (out_offset == -1)
1114 out_offset = cur_offset;
1115 if (cur_offset != out_offset) {
1116 pr_err_once("tail_call out_offset = %d, expected %d!\n",
1117 cur_offset, out_offset);
1118 return -1;
1119 }
1120 return 0;
1121#undef cur_offset
1122#undef jmp_offset
1123}
1124
1125/* 0xabcd => 0xcdab */
1126static inline void emit_rev16(const u8 rd, const u8 rn, struct jit_ctx *ctx)
1127{
1128#if __LINUX_ARM_ARCH__ < 6
Russell King1c35ba12018-07-11 10:31:41 +01001129 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Shubham Bansal39c13c22017-08-22 12:02:33 +05301130
1131 emit(ARM_AND_I(tmp2[1], rn, 0xff), ctx);
1132 emit(ARM_MOV_SI(tmp2[0], rn, SRTYPE_LSR, 8), ctx);
1133 emit(ARM_AND_I(tmp2[0], tmp2[0], 0xff), ctx);
1134 emit(ARM_ORR_SI(rd, tmp2[0], tmp2[1], SRTYPE_LSL, 8), ctx);
1135#else /* ARMv6+ */
1136 emit(ARM_REV16(rd, rn), ctx);
1137#endif
1138}
1139
1140/* 0xabcdefgh => 0xghefcdab */
1141static inline void emit_rev32(const u8 rd, const u8 rn, struct jit_ctx *ctx)
1142{
1143#if __LINUX_ARM_ARCH__ < 6
Russell King1c35ba12018-07-11 10:31:41 +01001144 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Shubham Bansal39c13c22017-08-22 12:02:33 +05301145
1146 emit(ARM_AND_I(tmp2[1], rn, 0xff), ctx);
1147 emit(ARM_MOV_SI(tmp2[0], rn, SRTYPE_LSR, 24), ctx);
1148 emit(ARM_ORR_SI(ARM_IP, tmp2[0], tmp2[1], SRTYPE_LSL, 24), ctx);
1149
1150 emit(ARM_MOV_SI(tmp2[1], rn, SRTYPE_LSR, 8), ctx);
1151 emit(ARM_AND_I(tmp2[1], tmp2[1], 0xff), ctx);
1152 emit(ARM_MOV_SI(tmp2[0], rn, SRTYPE_LSR, 16), ctx);
1153 emit(ARM_AND_I(tmp2[0], tmp2[0], 0xff), ctx);
1154 emit(ARM_MOV_SI(tmp2[0], tmp2[0], SRTYPE_LSL, 8), ctx);
1155 emit(ARM_ORR_SI(tmp2[0], tmp2[0], tmp2[1], SRTYPE_LSL, 16), ctx);
1156 emit(ARM_ORR_R(rd, ARM_IP, tmp2[0]), ctx);
1157
1158#else /* ARMv6+ */
1159 emit(ARM_REV(rd, rn), ctx);
1160#endif
1161}
1162
1163// push the scratch stack register on top of the stack
Russell King96cced42018-07-11 10:32:02 +01001164static inline void emit_push_r64(const s8 src[], struct jit_ctx *ctx)
Shubham Bansal39c13c22017-08-22 12:02:33 +05301165{
Russell King1c35ba12018-07-11 10:31:41 +01001166 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Russell King96cced42018-07-11 10:32:02 +01001167 const s8 *rt;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301168 u16 reg_set = 0;
1169
Russell King96cced42018-07-11 10:32:02 +01001170 rt = arm_bpf_get_reg64(src, tmp2, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301171
Russell King96cced42018-07-11 10:32:02 +01001172 reg_set = (1 << rt[1]) | (1 << rt[0]);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301173 emit(ARM_PUSH(reg_set), ctx);
1174}
1175
1176static void build_prologue(struct jit_ctx *ctx)
1177{
Russell King1c35ba12018-07-11 10:31:41 +01001178 const s8 r0 = bpf2a32[BPF_REG_0][1];
1179 const s8 r2 = bpf2a32[BPF_REG_1][1];
1180 const s8 r3 = bpf2a32[BPF_REG_1][0];
1181 const s8 r4 = bpf2a32[BPF_REG_6][1];
1182 const s8 fplo = bpf2a32[BPF_REG_FP][1];
1183 const s8 fphi = bpf2a32[BPF_REG_FP][0];
1184 const s8 *tcc = bpf2a32[TCALL_CNT];
Shubham Bansal39c13c22017-08-22 12:02:33 +05301185
Shubham Bansal39c13c22017-08-22 12:02:33 +05301186 /* Save callee saved registers. */
Shubham Bansal39c13c22017-08-22 12:02:33 +05301187#ifdef CONFIG_FRAME_POINTER
Russell King02088d92018-01-13 22:38:18 +00001188 u16 reg_set = CALLEE_PUSH_MASK | 1 << ARM_IP | 1 << ARM_PC;
1189 emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301190 emit(ARM_PUSH(reg_set), ctx);
1191 emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
1192#else
Russell King02088d92018-01-13 22:38:18 +00001193 emit(ARM_PUSH(CALLEE_PUSH_MASK), ctx);
1194 emit(ARM_MOV_R(ARM_FP, ARM_SP), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301195#endif
1196 /* Save frame pointer for later */
Russell King02088d92018-01-13 22:38:18 +00001197 emit(ARM_SUB_I(ARM_IP, ARM_SP, SCRATCH_SIZE), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301198
1199 ctx->stack_size = imm8m(STACK_SIZE);
1200
1201 /* Set up function call stack */
1202 emit(ARM_SUB_I(ARM_SP, ARM_SP, ctx->stack_size), ctx);
1203
1204 /* Set up BPF prog stack base register */
Russell King47b9c3bf2018-07-11 10:31:47 +01001205 emit_a32_mov_r(fplo, ARM_IP, ctx);
1206 emit_a32_mov_i(fphi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301207
1208 /* mov r4, 0 */
1209 emit(ARM_MOV_I(r4, 0), ctx);
1210
1211 /* Move BPF_CTX to BPF_R1 */
1212 emit(ARM_MOV_R(r3, r4), ctx);
1213 emit(ARM_MOV_R(r2, r0), ctx);
1214 /* Initialize Tail Count */
Russell King96cced42018-07-11 10:32:02 +01001215 emit(ARM_STR_I(r4, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(tcc[0])), ctx);
1216 emit(ARM_STR_I(r4, ARM_FP, EBPF_SCRATCH_TO_ARM_FP(tcc[1])), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301217 /* end of prologue */
1218}
1219
Russell King02088d92018-01-13 22:38:18 +00001220/* restore callee saved registers. */
Shubham Bansal39c13c22017-08-22 12:02:33 +05301221static void build_epilogue(struct jit_ctx *ctx)
1222{
Shubham Bansal39c13c22017-08-22 12:02:33 +05301223#ifdef CONFIG_FRAME_POINTER
Russell King02088d92018-01-13 22:38:18 +00001224 /* When using frame pointers, some additional registers need to
1225 * be loaded. */
1226 u16 reg_set = CALLEE_POP_MASK | 1 << ARM_SP;
1227 emit(ARM_SUB_I(ARM_SP, ARM_FP, hweight16(reg_set) * 4), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301228 emit(ARM_LDM(ARM_SP, reg_set), ctx);
1229#else
Shubham Bansal39c13c22017-08-22 12:02:33 +05301230 /* Restore callee saved registers. */
Russell King02088d92018-01-13 22:38:18 +00001231 emit(ARM_MOV_R(ARM_SP, ARM_FP), ctx);
1232 emit(ARM_POP(CALLEE_POP_MASK), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301233#endif
1234}
1235
1236/*
1237 * Convert an eBPF instruction to native instruction, i.e
1238 * JITs an eBPF instruction.
1239 * Returns :
1240 * 0 - Successfully JITed an 8-byte eBPF instruction
1241 * >0 - Successfully JITed a 16-byte eBPF instruction
1242 * <0 - Failed to JIT.
1243 */
1244static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
1245{
1246 const u8 code = insn->code;
Russell King1c35ba12018-07-11 10:31:41 +01001247 const s8 *dst = bpf2a32[insn->dst_reg];
1248 const s8 *src = bpf2a32[insn->src_reg];
1249 const s8 *tmp = bpf2a32[TMP_REG_1];
1250 const s8 *tmp2 = bpf2a32[TMP_REG_2];
Shubham Bansal39c13c22017-08-22 12:02:33 +05301251 const s16 off = insn->off;
1252 const s32 imm = insn->imm;
1253 const int i = insn - ctx->prog->insnsi;
1254 const bool is64 = BPF_CLASS(code) == BPF_ALU64;
Russell Kinga6eccac2018-07-11 10:31:57 +01001255 const s8 *rd, *rs;
1256 s8 rd_lo, rt, rm, rn;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301257 s32 jmp_offset;
1258
1259#define check_imm(bits, imm) do { \
Wang YanQing2b589a72018-05-11 11:06:34 +08001260 if ((imm) >= (1 << ((bits) - 1)) || \
1261 (imm) < -(1 << ((bits) - 1))) { \
Shubham Bansal39c13c22017-08-22 12:02:33 +05301262 pr_info("[%2d] imm=%d(0x%x) out of range\n", \
1263 i, imm, imm); \
1264 return -EINVAL; \
1265 } \
1266} while (0)
1267#define check_imm24(imm) check_imm(24, imm)
1268
1269 switch (code) {
1270 /* ALU operations */
1271
1272 /* dst = src */
1273 case BPF_ALU | BPF_MOV | BPF_K:
1274 case BPF_ALU | BPF_MOV | BPF_X:
1275 case BPF_ALU64 | BPF_MOV | BPF_K:
1276 case BPF_ALU64 | BPF_MOV | BPF_X:
1277 switch (BPF_SRC(code)) {
1278 case BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001279 emit_a32_mov_r64(is64, dst, src, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301280 break;
1281 case BPF_K:
1282 /* Sign-extend immediate value to destination reg */
Russell King47b9c3bf2018-07-11 10:31:47 +01001283 emit_a32_mov_i64(is64, dst, imm, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301284 break;
1285 }
1286 break;
1287 /* dst = dst + src/imm */
1288 /* dst = dst - src/imm */
1289 /* dst = dst | src/imm */
1290 /* dst = dst & src/imm */
1291 /* dst = dst ^ src/imm */
1292 /* dst = dst * src/imm */
1293 /* dst = dst << src */
1294 /* dst = dst >> src */
1295 case BPF_ALU | BPF_ADD | BPF_K:
1296 case BPF_ALU | BPF_ADD | BPF_X:
1297 case BPF_ALU | BPF_SUB | BPF_K:
1298 case BPF_ALU | BPF_SUB | BPF_X:
1299 case BPF_ALU | BPF_OR | BPF_K:
1300 case BPF_ALU | BPF_OR | BPF_X:
1301 case BPF_ALU | BPF_AND | BPF_K:
1302 case BPF_ALU | BPF_AND | BPF_X:
1303 case BPF_ALU | BPF_XOR | BPF_K:
1304 case BPF_ALU | BPF_XOR | BPF_X:
1305 case BPF_ALU | BPF_MUL | BPF_K:
1306 case BPF_ALU | BPF_MUL | BPF_X:
1307 case BPF_ALU | BPF_LSH | BPF_X:
1308 case BPF_ALU | BPF_RSH | BPF_X:
1309 case BPF_ALU | BPF_ARSH | BPF_K:
1310 case BPF_ALU | BPF_ARSH | BPF_X:
1311 case BPF_ALU64 | BPF_ADD | BPF_K:
1312 case BPF_ALU64 | BPF_ADD | BPF_X:
1313 case BPF_ALU64 | BPF_SUB | BPF_K:
1314 case BPF_ALU64 | BPF_SUB | BPF_X:
1315 case BPF_ALU64 | BPF_OR | BPF_K:
1316 case BPF_ALU64 | BPF_OR | BPF_X:
1317 case BPF_ALU64 | BPF_AND | BPF_K:
1318 case BPF_ALU64 | BPF_AND | BPF_X:
1319 case BPF_ALU64 | BPF_XOR | BPF_K:
1320 case BPF_ALU64 | BPF_XOR | BPF_X:
1321 switch (BPF_SRC(code)) {
1322 case BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001323 emit_a32_alu_r64(is64, dst, src, ctx, BPF_OP(code));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301324 break;
1325 case BPF_K:
1326 /* Move immediate value to the temporary register
1327 * and then do the ALU operation on the temporary
1328 * register as this will sign-extend the immediate
1329 * value into temporary reg and then it would be
1330 * safe to do the operation on it.
1331 */
Russell King47b9c3bf2018-07-11 10:31:47 +01001332 emit_a32_mov_i64(is64, tmp2, imm, ctx);
1333 emit_a32_alu_r64(is64, dst, tmp2, ctx, BPF_OP(code));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301334 break;
1335 }
1336 break;
1337 /* dst = dst / src(imm) */
1338 /* dst = dst % src(imm) */
1339 case BPF_ALU | BPF_DIV | BPF_K:
1340 case BPF_ALU | BPF_DIV | BPF_X:
1341 case BPF_ALU | BPF_MOD | BPF_K:
1342 case BPF_ALU | BPF_MOD | BPF_X:
Russell Kinga6eccac2018-07-11 10:31:57 +01001343 rd_lo = arm_bpf_get_reg32(dst_lo, tmp2[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301344 switch (BPF_SRC(code)) {
1345 case BPF_X:
Russell King7a987022018-07-11 10:31:52 +01001346 rt = arm_bpf_get_reg32(src_lo, tmp2[0], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301347 break;
1348 case BPF_K:
1349 rt = tmp2[0];
Russell King47b9c3bf2018-07-11 10:31:47 +01001350 emit_a32_mov_i(rt, imm, ctx);
1351 break;
1352 default:
1353 rt = src_lo;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301354 break;
1355 }
Russell Kinga6eccac2018-07-11 10:31:57 +01001356 emit_udivmod(rd_lo, rd_lo, rt, ctx, BPF_OP(code));
1357 arm_bpf_put_reg32(dst_lo, rd_lo, ctx);
Russell King47b9c3bf2018-07-11 10:31:47 +01001358 emit_a32_mov_i(dst_hi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301359 break;
1360 case BPF_ALU64 | BPF_DIV | BPF_K:
1361 case BPF_ALU64 | BPF_DIV | BPF_X:
1362 case BPF_ALU64 | BPF_MOD | BPF_K:
1363 case BPF_ALU64 | BPF_MOD | BPF_X:
1364 goto notyet;
1365 /* dst = dst >> imm */
1366 /* dst = dst << imm */
1367 case BPF_ALU | BPF_RSH | BPF_K:
1368 case BPF_ALU | BPF_LSH | BPF_K:
1369 if (unlikely(imm > 31))
1370 return -EINVAL;
1371 if (imm)
Russell King47b9c3bf2018-07-11 10:31:47 +01001372 emit_a32_alu_i(dst_lo, imm, ctx, BPF_OP(code));
1373 emit_a32_mov_i(dst_hi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301374 break;
1375 /* dst = dst << imm */
1376 case BPF_ALU64 | BPF_LSH | BPF_K:
1377 if (unlikely(imm > 63))
1378 return -EINVAL;
Russell King47b9c3bf2018-07-11 10:31:47 +01001379 emit_a32_lsh_i64(dst, imm, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301380 break;
1381 /* dst = dst >> imm */
1382 case BPF_ALU64 | BPF_RSH | BPF_K:
1383 if (unlikely(imm > 63))
1384 return -EINVAL;
Russell King47b9c3bf2018-07-11 10:31:47 +01001385 emit_a32_rsh_i64(dst, imm, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301386 break;
1387 /* dst = dst << src */
1388 case BPF_ALU64 | BPF_LSH | BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001389 emit_a32_lsh_r64(dst, src, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301390 break;
1391 /* dst = dst >> src */
1392 case BPF_ALU64 | BPF_RSH | BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001393 emit_a32_rsh_r64(dst, src, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301394 break;
1395 /* dst = dst >> src (signed) */
1396 case BPF_ALU64 | BPF_ARSH | BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001397 emit_a32_arsh_r64(dst, src, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301398 break;
1399 /* dst = dst >> imm (signed) */
1400 case BPF_ALU64 | BPF_ARSH | BPF_K:
1401 if (unlikely(imm > 63))
1402 return -EINVAL;
Russell King47b9c3bf2018-07-11 10:31:47 +01001403 emit_a32_arsh_i64(dst, imm, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301404 break;
1405 /* dst = ~dst */
1406 case BPF_ALU | BPF_NEG:
Russell King47b9c3bf2018-07-11 10:31:47 +01001407 emit_a32_alu_i(dst_lo, 0, ctx, BPF_OP(code));
1408 emit_a32_mov_i(dst_hi, 0, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301409 break;
1410 /* dst = ~dst (64 bit) */
1411 case BPF_ALU64 | BPF_NEG:
Russell King47b9c3bf2018-07-11 10:31:47 +01001412 emit_a32_neg64(dst, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301413 break;
1414 /* dst = dst * src/imm */
1415 case BPF_ALU64 | BPF_MUL | BPF_X:
1416 case BPF_ALU64 | BPF_MUL | BPF_K:
1417 switch (BPF_SRC(code)) {
1418 case BPF_X:
Russell King47b9c3bf2018-07-11 10:31:47 +01001419 emit_a32_mul_r64(dst, src, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301420 break;
1421 case BPF_K:
1422 /* Move immediate value to the temporary register
1423 * and then do the multiplication on it as this
1424 * will sign-extend the immediate value into temp
1425 * reg then it would be safe to do the operation
1426 * on it.
1427 */
Russell King47b9c3bf2018-07-11 10:31:47 +01001428 emit_a32_mov_i64(is64, tmp2, imm, ctx);
1429 emit_a32_mul_r64(dst, tmp2, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301430 break;
1431 }
1432 break;
1433 /* dst = htole(dst) */
1434 /* dst = htobe(dst) */
1435 case BPF_ALU | BPF_END | BPF_FROM_LE:
1436 case BPF_ALU | BPF_END | BPF_FROM_BE:
Russell Kinga6eccac2018-07-11 10:31:57 +01001437 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301438 if (BPF_SRC(code) == BPF_FROM_LE)
1439 goto emit_bswap_uxt;
1440 switch (imm) {
1441 case 16:
Russell Kinga6eccac2018-07-11 10:31:57 +01001442 emit_rev16(rd[1], rd[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301443 goto emit_bswap_uxt;
1444 case 32:
Russell Kinga6eccac2018-07-11 10:31:57 +01001445 emit_rev32(rd[1], rd[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301446 goto emit_bswap_uxt;
1447 case 64:
Russell Kinga6eccac2018-07-11 10:31:57 +01001448 emit_rev32(ARM_LR, rd[1], ctx);
1449 emit_rev32(rd[1], rd[0], ctx);
1450 emit(ARM_MOV_R(rd[0], ARM_LR), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301451 break;
1452 }
1453 goto exit;
1454emit_bswap_uxt:
1455 switch (imm) {
1456 case 16:
1457 /* zero-extend 16 bits into 64 bits */
1458#if __LINUX_ARM_ARCH__ < 6
Russell King47b9c3bf2018-07-11 10:31:47 +01001459 emit_a32_mov_i(tmp2[1], 0xffff, ctx);
Russell Kinga6eccac2018-07-11 10:31:57 +01001460 emit(ARM_AND_R(rd[1], rd[1], tmp2[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301461#else /* ARMv6+ */
Russell Kinga6eccac2018-07-11 10:31:57 +01001462 emit(ARM_UXTH(rd[1], rd[1]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301463#endif
Russell Kinga6eccac2018-07-11 10:31:57 +01001464 emit(ARM_EOR_R(rd[0], rd[0], rd[0]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301465 break;
1466 case 32:
1467 /* zero-extend 32 bits into 64 bits */
Russell Kinga6eccac2018-07-11 10:31:57 +01001468 emit(ARM_EOR_R(rd[0], rd[0], rd[0]), ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301469 break;
1470 case 64:
1471 /* nop */
1472 break;
1473 }
1474exit:
Russell Kinga6eccac2018-07-11 10:31:57 +01001475 arm_bpf_put_reg64(dst, rd, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301476 break;
1477 /* dst = imm64 */
1478 case BPF_LD | BPF_IMM | BPF_DW:
1479 {
1480 const struct bpf_insn insn1 = insn[1];
1481 u32 hi, lo = imm;
1482
1483 hi = insn1.imm;
Russell King47b9c3bf2018-07-11 10:31:47 +01001484 emit_a32_mov_i(dst_lo, lo, ctx);
1485 emit_a32_mov_i(dst_hi, hi, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301486
1487 return 1;
1488 }
1489 /* LDX: dst = *(size *)(src + off) */
1490 case BPF_LDX | BPF_MEM | BPF_W:
1491 case BPF_LDX | BPF_MEM | BPF_H:
1492 case BPF_LDX | BPF_MEM | BPF_B:
1493 case BPF_LDX | BPF_MEM | BPF_DW:
Russell King7a987022018-07-11 10:31:52 +01001494 rn = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
Russell King47b9c3bf2018-07-11 10:31:47 +01001495 emit_ldx_r(dst, rn, off, ctx, BPF_SIZE(code));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301496 break;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301497 /* ST: *(size *)(dst + off) = imm */
1498 case BPF_ST | BPF_MEM | BPF_W:
1499 case BPF_ST | BPF_MEM | BPF_H:
1500 case BPF_ST | BPF_MEM | BPF_B:
1501 case BPF_ST | BPF_MEM | BPF_DW:
1502 switch (BPF_SIZE(code)) {
1503 case BPF_DW:
1504 /* Sign-extend immediate value into temp reg */
Russell King47b9c3bf2018-07-11 10:31:47 +01001505 emit_a32_mov_i64(true, tmp2, imm, ctx);
1506 emit_str_r(dst_lo, tmp2[1], off, ctx, BPF_W);
1507 emit_str_r(dst_lo, tmp2[0], off+4, ctx, BPF_W);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301508 break;
1509 case BPF_W:
1510 case BPF_H:
1511 case BPF_B:
Russell King47b9c3bf2018-07-11 10:31:47 +01001512 emit_a32_mov_i(tmp2[1], imm, ctx);
1513 emit_str_r(dst_lo, tmp2[1], off, ctx, BPF_SIZE(code));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301514 break;
1515 }
1516 break;
1517 /* STX XADD: lock *(u32 *)(dst + off) += src */
1518 case BPF_STX | BPF_XADD | BPF_W:
1519 /* STX XADD: lock *(u64 *)(dst + off) += src */
1520 case BPF_STX | BPF_XADD | BPF_DW:
1521 goto notyet;
1522 /* STX: *(size *)(dst + off) = src */
1523 case BPF_STX | BPF_MEM | BPF_W:
1524 case BPF_STX | BPF_MEM | BPF_H:
1525 case BPF_STX | BPF_MEM | BPF_B:
1526 case BPF_STX | BPF_MEM | BPF_DW:
1527 {
1528 u8 sz = BPF_SIZE(code);
1529
Russell Kinga6eccac2018-07-11 10:31:57 +01001530 rs = arm_bpf_get_reg64(src, tmp2, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301531
1532 /* Store the value */
1533 if (BPF_SIZE(code) == BPF_DW) {
Russell Kinga6eccac2018-07-11 10:31:57 +01001534 emit_str_r(dst_lo, rs[1], off, ctx, BPF_W);
1535 emit_str_r(dst_lo, rs[0], off+4, ctx, BPF_W);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301536 } else {
Russell Kinga6eccac2018-07-11 10:31:57 +01001537 emit_str_r(dst_lo, rs[1], off, ctx, sz);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301538 }
1539 break;
1540 }
1541 /* PC += off if dst == src */
1542 /* PC += off if dst > src */
1543 /* PC += off if dst >= src */
1544 /* PC += off if dst < src */
1545 /* PC += off if dst <= src */
1546 /* PC += off if dst != src */
1547 /* PC += off if dst > src (signed) */
1548 /* PC += off if dst >= src (signed) */
1549 /* PC += off if dst < src (signed) */
1550 /* PC += off if dst <= src (signed) */
1551 /* PC += off if dst & src */
1552 case BPF_JMP | BPF_JEQ | BPF_X:
1553 case BPF_JMP | BPF_JGT | BPF_X:
1554 case BPF_JMP | BPF_JGE | BPF_X:
1555 case BPF_JMP | BPF_JNE | BPF_X:
1556 case BPF_JMP | BPF_JSGT | BPF_X:
1557 case BPF_JMP | BPF_JSGE | BPF_X:
1558 case BPF_JMP | BPF_JSET | BPF_X:
1559 case BPF_JMP | BPF_JLE | BPF_X:
1560 case BPF_JMP | BPF_JLT | BPF_X:
1561 case BPF_JMP | BPF_JSLT | BPF_X:
1562 case BPF_JMP | BPF_JSLE | BPF_X:
1563 /* Setup source registers */
Russell King7a987022018-07-11 10:31:52 +01001564 rm = arm_bpf_get_reg32(src_hi, tmp2[0], ctx);
1565 rn = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301566 goto go_jmp;
1567 /* PC += off if dst == imm */
1568 /* PC += off if dst > imm */
1569 /* PC += off if dst >= imm */
1570 /* PC += off if dst < imm */
1571 /* PC += off if dst <= imm */
1572 /* PC += off if dst != imm */
1573 /* PC += off if dst > imm (signed) */
1574 /* PC += off if dst >= imm (signed) */
1575 /* PC += off if dst < imm (signed) */
1576 /* PC += off if dst <= imm (signed) */
1577 /* PC += off if dst & imm */
1578 case BPF_JMP | BPF_JEQ | BPF_K:
1579 case BPF_JMP | BPF_JGT | BPF_K:
1580 case BPF_JMP | BPF_JGE | BPF_K:
1581 case BPF_JMP | BPF_JNE | BPF_K:
1582 case BPF_JMP | BPF_JSGT | BPF_K:
1583 case BPF_JMP | BPF_JSGE | BPF_K:
1584 case BPF_JMP | BPF_JSET | BPF_K:
1585 case BPF_JMP | BPF_JLT | BPF_K:
1586 case BPF_JMP | BPF_JLE | BPF_K:
1587 case BPF_JMP | BPF_JSLT | BPF_K:
1588 case BPF_JMP | BPF_JSLE | BPF_K:
1589 if (off == 0)
1590 break;
1591 rm = tmp2[0];
1592 rn = tmp2[1];
1593 /* Sign-extend immediate value */
Russell King47b9c3bf2018-07-11 10:31:47 +01001594 emit_a32_mov_i64(true, tmp2, imm, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301595go_jmp:
1596 /* Setup destination register */
Russell Kinga6eccac2018-07-11 10:31:57 +01001597 rd = arm_bpf_get_reg64(dst, tmp, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301598
1599 /* Check for the condition */
Russell Kinga6eccac2018-07-11 10:31:57 +01001600 emit_ar_r(rd[0], rd[1], rm, rn, ctx, BPF_OP(code));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301601
1602 /* Setup JUMP instruction */
1603 jmp_offset = bpf2a32_offset(i+off, i, ctx);
1604 switch (BPF_OP(code)) {
1605 case BPF_JNE:
1606 case BPF_JSET:
1607 _emit(ARM_COND_NE, ARM_B(jmp_offset), ctx);
1608 break;
1609 case BPF_JEQ:
1610 _emit(ARM_COND_EQ, ARM_B(jmp_offset), ctx);
1611 break;
1612 case BPF_JGT:
1613 _emit(ARM_COND_HI, ARM_B(jmp_offset), ctx);
1614 break;
1615 case BPF_JGE:
1616 _emit(ARM_COND_CS, ARM_B(jmp_offset), ctx);
1617 break;
1618 case BPF_JSGT:
1619 _emit(ARM_COND_LT, ARM_B(jmp_offset), ctx);
1620 break;
1621 case BPF_JSGE:
1622 _emit(ARM_COND_GE, ARM_B(jmp_offset), ctx);
1623 break;
1624 case BPF_JLE:
1625 _emit(ARM_COND_LS, ARM_B(jmp_offset), ctx);
1626 break;
1627 case BPF_JLT:
1628 _emit(ARM_COND_CC, ARM_B(jmp_offset), ctx);
1629 break;
1630 case BPF_JSLT:
1631 _emit(ARM_COND_LT, ARM_B(jmp_offset), ctx);
1632 break;
1633 case BPF_JSLE:
1634 _emit(ARM_COND_GE, ARM_B(jmp_offset), ctx);
1635 break;
1636 }
1637 break;
1638 /* JMP OFF */
1639 case BPF_JMP | BPF_JA:
1640 {
1641 if (off == 0)
1642 break;
1643 jmp_offset = bpf2a32_offset(i+off, i, ctx);
1644 check_imm24(jmp_offset);
1645 emit(ARM_B(jmp_offset), ctx);
1646 break;
1647 }
1648 /* tail call */
1649 case BPF_JMP | BPF_TAIL_CALL:
1650 if (emit_bpf_tail_call(ctx))
1651 return -EFAULT;
1652 break;
1653 /* function call */
1654 case BPF_JMP | BPF_CALL:
1655 {
Russell King1c35ba12018-07-11 10:31:41 +01001656 const s8 *r0 = bpf2a32[BPF_REG_0];
1657 const s8 *r1 = bpf2a32[BPF_REG_1];
1658 const s8 *r2 = bpf2a32[BPF_REG_2];
1659 const s8 *r3 = bpf2a32[BPF_REG_3];
1660 const s8 *r4 = bpf2a32[BPF_REG_4];
1661 const s8 *r5 = bpf2a32[BPF_REG_5];
Shubham Bansal39c13c22017-08-22 12:02:33 +05301662 const u32 func = (u32)__bpf_call_base + (u32)imm;
1663
Russell King47b9c3bf2018-07-11 10:31:47 +01001664 emit_a32_mov_r64(true, r0, r1, ctx);
1665 emit_a32_mov_r64(true, r1, r2, ctx);
Russell King96cced42018-07-11 10:32:02 +01001666 emit_push_r64(r5, ctx);
1667 emit_push_r64(r4, ctx);
1668 emit_push_r64(r3, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301669
Russell King47b9c3bf2018-07-11 10:31:47 +01001670 emit_a32_mov_i(tmp[1], func, ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301671 emit_blx_r(tmp[1], ctx);
1672
1673 emit(ARM_ADD_I(ARM_SP, ARM_SP, imm8m(24)), ctx); // callee clean
1674 break;
1675 }
1676 /* function return */
1677 case BPF_JMP | BPF_EXIT:
1678 /* Optimization: when last instruction is EXIT
1679 * simply fallthrough to epilogue.
1680 */
1681 if (i == ctx->prog->len - 1)
1682 break;
1683 jmp_offset = epilogue_offset(ctx);
1684 check_imm24(jmp_offset);
1685 emit(ARM_B(jmp_offset), ctx);
1686 break;
1687notyet:
1688 pr_info_once("*** NOT YET: opcode %02x ***\n", code);
1689 return -EFAULT;
1690 default:
1691 pr_err_once("unknown opcode %02x\n", code);
1692 return -EINVAL;
1693 }
1694
1695 if (ctx->flags & FLAG_IMM_OVERFLOW)
1696 /*
1697 * this instruction generated an overflow when
1698 * trying to access the literal pool, so
1699 * delegate this filter to the kernel interpreter.
1700 */
1701 return -1;
1702 return 0;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001703}
1704
1705static int build_body(struct jit_ctx *ctx)
1706{
Shubham Bansal39c13c22017-08-22 12:02:33 +05301707 const struct bpf_prog *prog = ctx->prog;
1708 unsigned int i;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001709
1710 for (i = 0; i < prog->len; i++) {
Shubham Bansal39c13c22017-08-22 12:02:33 +05301711 const struct bpf_insn *insn = &(prog->insnsi[i]);
1712 int ret;
Daniel Borkmann34805932014-05-29 10:22:50 +02001713
Shubham Bansal39c13c22017-08-22 12:02:33 +05301714 ret = build_insn(insn, ctx);
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001715
Shubham Bansal39c13c22017-08-22 12:02:33 +05301716 /* It's used with loading the 64 bit immediate value. */
1717 if (ret > 0) {
1718 i++;
1719 if (ctx->target == NULL)
1720 ctx->offsets[i] = ctx->idx;
1721 continue;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001722 }
Nicolas Schichan0b59d882015-05-07 17:14:21 +02001723
Shubham Bansal39c13c22017-08-22 12:02:33 +05301724 if (ctx->target == NULL)
1725 ctx->offsets[i] = ctx->idx;
1726
1727 /* If unsuccesfull, return with error code */
1728 if (ret)
1729 return ret;
1730 }
1731 return 0;
1732}
1733
1734static int validate_code(struct jit_ctx *ctx)
1735{
1736 int i;
1737
1738 for (i = 0; i < ctx->idx; i++) {
1739 if (ctx->target[i] == __opcode_to_mem_arm(ARM_INST_UDF))
Nicolas Schichan0b59d882015-05-07 17:14:21 +02001740 return -1;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001741 }
1742
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001743 return 0;
1744}
1745
Shubham Bansal39c13c22017-08-22 12:02:33 +05301746void bpf_jit_compile(struct bpf_prog *prog)
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001747{
Shubham Bansal39c13c22017-08-22 12:02:33 +05301748 /* Nothing to do here. We support Internal BPF. */
1749}
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001750
Shubham Bansal39c13c22017-08-22 12:02:33 +05301751struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
1752{
1753 struct bpf_prog *tmp, *orig_prog = prog;
1754 struct bpf_binary_header *header;
1755 bool tmp_blinded = false;
1756 struct jit_ctx ctx;
1757 unsigned int tmp_idx;
1758 unsigned int image_size;
1759 u8 *image_ptr;
1760
1761 /* If BPF JIT was not enabled then we must fall back to
1762 * the interpreter.
1763 */
Alexei Starovoitov60b58afc2017-12-14 17:55:14 -08001764 if (!prog->jit_requested)
Shubham Bansal39c13c22017-08-22 12:02:33 +05301765 return orig_prog;
1766
1767 /* If constant blinding was enabled and we failed during blinding
1768 * then we must fall back to the interpreter. Otherwise, we save
1769 * the new JITed code.
1770 */
1771 tmp = bpf_jit_blind_constants(prog);
1772
1773 if (IS_ERR(tmp))
1774 return orig_prog;
1775 if (tmp != prog) {
1776 tmp_blinded = true;
1777 prog = tmp;
1778 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001779
1780 memset(&ctx, 0, sizeof(ctx));
Shubham Bansal39c13c22017-08-22 12:02:33 +05301781 ctx.prog = prog;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001782
Shubham Bansal39c13c22017-08-22 12:02:33 +05301783 /* Not able to allocate memory for offsets[] , then
1784 * we must fall back to the interpreter
1785 */
1786 ctx.offsets = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
1787 if (ctx.offsets == NULL) {
1788 prog = orig_prog;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001789 goto out;
Shubham Bansal39c13c22017-08-22 12:02:33 +05301790 }
1791
1792 /* 1) fake pass to find in the length of the JITed code,
1793 * to compute ctx->offsets and other context variables
1794 * needed to compute final JITed code.
1795 * Also, calculate random starting pointer/start of JITed code
1796 * which is prefixed by random number of fault instructions.
1797 *
1798 * If the first pass fails then there is no chance of it
1799 * being successful in the second pass, so just fall back
1800 * to the interpreter.
1801 */
1802 if (build_body(&ctx)) {
1803 prog = orig_prog;
1804 goto out_off;
1805 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001806
1807 tmp_idx = ctx.idx;
1808 build_prologue(&ctx);
1809 ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
1810
Shubham Bansal39c13c22017-08-22 12:02:33 +05301811 ctx.epilogue_offset = ctx.idx;
1812
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001813#if __LINUX_ARM_ARCH__ < 7
1814 tmp_idx = ctx.idx;
1815 build_epilogue(&ctx);
1816 ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
1817
1818 ctx.idx += ctx.imm_count;
1819 if (ctx.imm_count) {
Shubham Bansal39c13c22017-08-22 12:02:33 +05301820 ctx.imms = kcalloc(ctx.imm_count, sizeof(u32), GFP_KERNEL);
1821 if (ctx.imms == NULL) {
1822 prog = orig_prog;
1823 goto out_off;
1824 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001825 }
1826#else
Shubham Bansal39c13c22017-08-22 12:02:33 +05301827 /* there's nothing about the epilogue on ARMv7 */
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001828 build_epilogue(&ctx);
1829#endif
Shubham Bansal39c13c22017-08-22 12:02:33 +05301830 /* Now we can get the actual image size of the JITed arm code.
1831 * Currently, we are not considering the THUMB-2 instructions
1832 * for jit, although it can decrease the size of the image.
1833 *
1834 * As each arm instruction is of length 32bit, we are translating
1835 * number of JITed intructions into the size required to store these
1836 * JITed code.
1837 */
1838 image_size = sizeof(u32) * ctx.idx;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001839
Shubham Bansal39c13c22017-08-22 12:02:33 +05301840 /* Now we know the size of the structure to make */
1841 header = bpf_jit_binary_alloc(image_size, &image_ptr,
1842 sizeof(u32), jit_fill_hole);
1843 /* Not able to allocate memory for the structure then
1844 * we must fall back to the interpretation
1845 */
1846 if (header == NULL) {
1847 prog = orig_prog;
1848 goto out_imms;
1849 }
1850
1851 /* 2.) Actual pass to generate final JIT code */
1852 ctx.target = (u32 *) image_ptr;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001853 ctx.idx = 0;
Daniel Borkmann55309dd2014-09-08 08:04:48 +02001854
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001855 build_prologue(&ctx);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301856
1857 /* If building the body of the JITed code fails somehow,
1858 * we fall back to the interpretation.
1859 */
Nicolas Schichan0b59d882015-05-07 17:14:21 +02001860 if (build_body(&ctx) < 0) {
Shubham Bansal39c13c22017-08-22 12:02:33 +05301861 image_ptr = NULL;
Nicolas Schichan0b59d882015-05-07 17:14:21 +02001862 bpf_jit_binary_free(header);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301863 prog = orig_prog;
1864 goto out_imms;
Nicolas Schichan0b59d882015-05-07 17:14:21 +02001865 }
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001866 build_epilogue(&ctx);
1867
Shubham Bansal39c13c22017-08-22 12:02:33 +05301868 /* 3.) Extra pass to validate JITed Code */
1869 if (validate_code(&ctx)) {
1870 image_ptr = NULL;
1871 bpf_jit_binary_free(header);
1872 prog = orig_prog;
1873 goto out_imms;
1874 }
Daniel Borkmannebaef642015-11-14 01:26:53 +01001875 flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001876
Shubham Bansal39c13c22017-08-22 12:02:33 +05301877 if (bpf_jit_enable > 1)
1878 /* there are 2 passes here */
1879 bpf_jit_dump(prog->len, image_size, 2, ctx.target);
1880
Daniel Borkmann18d405a2018-06-28 23:34:57 +02001881 bpf_jit_binary_lock_ro(header);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301882 prog->bpf_func = (void *)ctx.target;
1883 prog->jited = 1;
1884 prog->jited_len = image_size;
1885
1886out_imms:
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001887#if __LINUX_ARM_ARCH__ < 7
1888 if (ctx.imm_count)
1889 kfree(ctx.imms);
1890#endif
Shubham Bansal39c13c22017-08-22 12:02:33 +05301891out_off:
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001892 kfree(ctx.offsets);
Shubham Bansal39c13c22017-08-22 12:02:33 +05301893out:
1894 if (tmp_blinded)
1895 bpf_jit_prog_release_other(prog, prog == orig_prog ?
1896 tmp : orig_prog);
1897 return prog;
Mircea Gherzanddecdfc2012-03-16 13:37:12 +01001898}
1899