Merge tag 'timers-v5.9-rc4' of https://git.linaro.org/people/daniel.lezcano/linux...
[linux-2.6-microblaze.git] / arch / riscv / net / bpf_jit.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Common functionality for RV32 and RV64 BPF JIT compilers
4  *
5  * Copyright (c) 2019 Björn Töpel <bjorn.topel@gmail.com>
6  *
7  */
8
9 #ifndef _BPF_JIT_H
10 #define _BPF_JIT_H
11
12 #include <linux/bpf.h>
13 #include <linux/filter.h>
14 #include <asm/cacheflush.h>
15
16 enum {
17         RV_REG_ZERO =   0,      /* The constant value 0 */
18         RV_REG_RA =     1,      /* Return address */
19         RV_REG_SP =     2,      /* Stack pointer */
20         RV_REG_GP =     3,      /* Global pointer */
21         RV_REG_TP =     4,      /* Thread pointer */
22         RV_REG_T0 =     5,      /* Temporaries */
23         RV_REG_T1 =     6,
24         RV_REG_T2 =     7,
25         RV_REG_FP =     8,      /* Saved register/frame pointer */
26         RV_REG_S1 =     9,      /* Saved register */
27         RV_REG_A0 =     10,     /* Function argument/return values */
28         RV_REG_A1 =     11,     /* Function arguments */
29         RV_REG_A2 =     12,
30         RV_REG_A3 =     13,
31         RV_REG_A4 =     14,
32         RV_REG_A5 =     15,
33         RV_REG_A6 =     16,
34         RV_REG_A7 =     17,
35         RV_REG_S2 =     18,     /* Saved registers */
36         RV_REG_S3 =     19,
37         RV_REG_S4 =     20,
38         RV_REG_S5 =     21,
39         RV_REG_S6 =     22,
40         RV_REG_S7 =     23,
41         RV_REG_S8 =     24,
42         RV_REG_S9 =     25,
43         RV_REG_S10 =    26,
44         RV_REG_S11 =    27,
45         RV_REG_T3 =     28,     /* Temporaries */
46         RV_REG_T4 =     29,
47         RV_REG_T5 =     30,
48         RV_REG_T6 =     31,
49 };
50
51 struct rv_jit_context {
52         struct bpf_prog *prog;
53         u32 *insns;             /* RV insns */
54         int ninsns;
55         int epilogue_offset;
56         int *offset;            /* BPF to RV */
57         unsigned long flags;
58         int stack_size;
59 };
60
61 struct rv_jit_data {
62         struct bpf_binary_header *header;
63         u8 *image;
64         struct rv_jit_context ctx;
65 };
66
67 static inline void bpf_fill_ill_insns(void *area, unsigned int size)
68 {
69         memset(area, 0, size);
70 }
71
72 static inline void bpf_flush_icache(void *start, void *end)
73 {
74         flush_icache_range((unsigned long)start, (unsigned long)end);
75 }
76
77 static inline void emit(const u32 insn, struct rv_jit_context *ctx)
78 {
79         if (ctx->insns)
80                 ctx->insns[ctx->ninsns] = insn;
81
82         ctx->ninsns++;
83 }
84
85 static inline int epilogue_offset(struct rv_jit_context *ctx)
86 {
87         int to = ctx->epilogue_offset, from = ctx->ninsns;
88
89         return (to - from) << 2;
90 }
91
92 /* Return -1 or inverted cond. */
93 static inline int invert_bpf_cond(u8 cond)
94 {
95         switch (cond) {
96         case BPF_JEQ:
97                 return BPF_JNE;
98         case BPF_JGT:
99                 return BPF_JLE;
100         case BPF_JLT:
101                 return BPF_JGE;
102         case BPF_JGE:
103                 return BPF_JLT;
104         case BPF_JLE:
105                 return BPF_JGT;
106         case BPF_JNE:
107                 return BPF_JEQ;
108         case BPF_JSGT:
109                 return BPF_JSLE;
110         case BPF_JSLT:
111                 return BPF_JSGE;
112         case BPF_JSGE:
113                 return BPF_JSLT;
114         case BPF_JSLE:
115                 return BPF_JSGT;
116         }
117         return -1;
118 }
119
120 static inline bool is_12b_int(long val)
121 {
122         return -(1L << 11) <= val && val < (1L << 11);
123 }
124
125 static inline int is_12b_check(int off, int insn)
126 {
127         if (!is_12b_int(off)) {
128                 pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n",
129                        insn, (int)off);
130                 return -1;
131         }
132         return 0;
133 }
134
135 static inline bool is_13b_int(long val)
136 {
137         return -(1L << 12) <= val && val < (1L << 12);
138 }
139
140 static inline bool is_21b_int(long val)
141 {
142         return -(1L << 20) <= val && val < (1L << 20);
143 }
144
145 static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx)
146 {
147         int from, to;
148
149         off++; /* BPF branch is from PC+1, RV is from PC */
150         from = (insn > 0) ? ctx->offset[insn - 1] : 0;
151         to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
152         return (to - from) << 2;
153 }
154
155 /* Instruction formats. */
156
157 static inline u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd,
158                             u8 opcode)
159 {
160         return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
161                 (rd << 7) | opcode;
162 }
163
164 static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
165 {
166         return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) |
167                 opcode;
168 }
169
170 static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
171 {
172         u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
173
174         return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
175                 (imm4_0 << 7) | opcode;
176 }
177
178 static inline u32 rv_b_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
179 {
180         u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4);
181         u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10);
182
183         return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
184                 (imm4_1 << 7) | opcode;
185 }
186
187 static inline u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode)
188 {
189         return (imm31_12 << 12) | (rd << 7) | opcode;
190 }
191
192 static inline u32 rv_j_insn(u32 imm20_1, u8 rd, u8 opcode)
193 {
194         u32 imm;
195
196         imm = (imm20_1 & 0x80000) | ((imm20_1 & 0x3ff) << 9) |
197                 ((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11);
198
199         return (imm << 12) | (rd << 7) | opcode;
200 }
201
202 static inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
203                               u8 funct3, u8 rd, u8 opcode)
204 {
205         u8 funct7 = (funct5 << 2) | (aq << 1) | rl;
206
207         return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
208 }
209
210 /* Instructions shared by both RV32 and RV64. */
211
212 static inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
213 {
214         return rv_i_insn(imm11_0, rs1, 0, rd, 0x13);
215 }
216
217 static inline u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0)
218 {
219         return rv_i_insn(imm11_0, rs1, 7, rd, 0x13);
220 }
221
222 static inline u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0)
223 {
224         return rv_i_insn(imm11_0, rs1, 6, rd, 0x13);
225 }
226
227 static inline u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0)
228 {
229         return rv_i_insn(imm11_0, rs1, 4, rd, 0x13);
230 }
231
232 static inline u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0)
233 {
234         return rv_i_insn(imm11_0, rs1, 1, rd, 0x13);
235 }
236
237 static inline u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0)
238 {
239         return rv_i_insn(imm11_0, rs1, 5, rd, 0x13);
240 }
241
242 static inline u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0)
243 {
244         return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13);
245 }
246
247 static inline u32 rv_lui(u8 rd, u32 imm31_12)
248 {
249         return rv_u_insn(imm31_12, rd, 0x37);
250 }
251
252 static inline u32 rv_auipc(u8 rd, u32 imm31_12)
253 {
254         return rv_u_insn(imm31_12, rd, 0x17);
255 }
256
257 static inline u32 rv_add(u8 rd, u8 rs1, u8 rs2)
258 {
259         return rv_r_insn(0, rs2, rs1, 0, rd, 0x33);
260 }
261
262 static inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2)
263 {
264         return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33);
265 }
266
267 static inline u32 rv_sltu(u8 rd, u8 rs1, u8 rs2)
268 {
269         return rv_r_insn(0, rs2, rs1, 3, rd, 0x33);
270 }
271
272 static inline u32 rv_and(u8 rd, u8 rs1, u8 rs2)
273 {
274         return rv_r_insn(0, rs2, rs1, 7, rd, 0x33);
275 }
276
277 static inline u32 rv_or(u8 rd, u8 rs1, u8 rs2)
278 {
279         return rv_r_insn(0, rs2, rs1, 6, rd, 0x33);
280 }
281
282 static inline u32 rv_xor(u8 rd, u8 rs1, u8 rs2)
283 {
284         return rv_r_insn(0, rs2, rs1, 4, rd, 0x33);
285 }
286
287 static inline u32 rv_sll(u8 rd, u8 rs1, u8 rs2)
288 {
289         return rv_r_insn(0, rs2, rs1, 1, rd, 0x33);
290 }
291
292 static inline u32 rv_srl(u8 rd, u8 rs1, u8 rs2)
293 {
294         return rv_r_insn(0, rs2, rs1, 5, rd, 0x33);
295 }
296
297 static inline u32 rv_sra(u8 rd, u8 rs1, u8 rs2)
298 {
299         return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33);
300 }
301
302 static inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2)
303 {
304         return rv_r_insn(1, rs2, rs1, 0, rd, 0x33);
305 }
306
307 static inline u32 rv_mulhu(u8 rd, u8 rs1, u8 rs2)
308 {
309         return rv_r_insn(1, rs2, rs1, 3, rd, 0x33);
310 }
311
312 static inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2)
313 {
314         return rv_r_insn(1, rs2, rs1, 5, rd, 0x33);
315 }
316
317 static inline u32 rv_remu(u8 rd, u8 rs1, u8 rs2)
318 {
319         return rv_r_insn(1, rs2, rs1, 7, rd, 0x33);
320 }
321
322 static inline u32 rv_jal(u8 rd, u32 imm20_1)
323 {
324         return rv_j_insn(imm20_1, rd, 0x6f);
325 }
326
327 static inline u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0)
328 {
329         return rv_i_insn(imm11_0, rs1, 0, rd, 0x67);
330 }
331
332 static inline u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1)
333 {
334         return rv_b_insn(imm12_1, rs2, rs1, 0, 0x63);
335 }
336
337 static inline u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1)
338 {
339         return rv_b_insn(imm12_1, rs2, rs1, 1, 0x63);
340 }
341
342 static inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1)
343 {
344         return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63);
345 }
346
347 static inline u32 rv_bgtu(u8 rs1, u8 rs2, u16 imm12_1)
348 {
349         return rv_bltu(rs2, rs1, imm12_1);
350 }
351
352 static inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1)
353 {
354         return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63);
355 }
356
357 static inline u32 rv_bleu(u8 rs1, u8 rs2, u16 imm12_1)
358 {
359         return rv_bgeu(rs2, rs1, imm12_1);
360 }
361
362 static inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1)
363 {
364         return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63);
365 }
366
367 static inline u32 rv_bgt(u8 rs1, u8 rs2, u16 imm12_1)
368 {
369         return rv_blt(rs2, rs1, imm12_1);
370 }
371
372 static inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1)
373 {
374         return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63);
375 }
376
377 static inline u32 rv_ble(u8 rs1, u8 rs2, u16 imm12_1)
378 {
379         return rv_bge(rs2, rs1, imm12_1);
380 }
381
382 static inline u32 rv_lw(u8 rd, u16 imm11_0, u8 rs1)
383 {
384         return rv_i_insn(imm11_0, rs1, 2, rd, 0x03);
385 }
386
387 static inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1)
388 {
389         return rv_i_insn(imm11_0, rs1, 4, rd, 0x03);
390 }
391
392 static inline u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1)
393 {
394         return rv_i_insn(imm11_0, rs1, 5, rd, 0x03);
395 }
396
397 static inline u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2)
398 {
399         return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23);
400 }
401
402 static inline u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2)
403 {
404         return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23);
405 }
406
407 static inline u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2)
408 {
409         return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23);
410 }
411
412 static inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
413 {
414         return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
415 }
416
417 /*
418  * RV64-only instructions.
419  *
420  * These instructions are not available on RV32.  Wrap them below a #if to
421  * ensure that the RV32 JIT doesn't emit any of these instructions.
422  */
423
424 #if __riscv_xlen == 64
425
426 static inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0)
427 {
428         return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b);
429 }
430
431 static inline u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0)
432 {
433         return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b);
434 }
435
436 static inline u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0)
437 {
438         return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b);
439 }
440
441 static inline u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0)
442 {
443         return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b);
444 }
445
446 static inline u32 rv_addw(u8 rd, u8 rs1, u8 rs2)
447 {
448         return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b);
449 }
450
451 static inline u32 rv_subw(u8 rd, u8 rs1, u8 rs2)
452 {
453         return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b);
454 }
455
456 static inline u32 rv_sllw(u8 rd, u8 rs1, u8 rs2)
457 {
458         return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b);
459 }
460
461 static inline u32 rv_srlw(u8 rd, u8 rs1, u8 rs2)
462 {
463         return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b);
464 }
465
466 static inline u32 rv_sraw(u8 rd, u8 rs1, u8 rs2)
467 {
468         return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b);
469 }
470
471 static inline u32 rv_mulw(u8 rd, u8 rs1, u8 rs2)
472 {
473         return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b);
474 }
475
476 static inline u32 rv_divuw(u8 rd, u8 rs1, u8 rs2)
477 {
478         return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b);
479 }
480
481 static inline u32 rv_remuw(u8 rd, u8 rs1, u8 rs2)
482 {
483         return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b);
484 }
485
486 static inline u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1)
487 {
488         return rv_i_insn(imm11_0, rs1, 3, rd, 0x03);
489 }
490
491 static inline u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1)
492 {
493         return rv_i_insn(imm11_0, rs1, 6, rd, 0x03);
494 }
495
496 static inline u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2)
497 {
498         return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23);
499 }
500
501 static inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
502 {
503         return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
504 }
505
506 #endif /* __riscv_xlen == 64 */
507
508 void bpf_jit_build_prologue(struct rv_jit_context *ctx);
509 void bpf_jit_build_epilogue(struct rv_jit_context *ctx);
510
511 int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
512                       bool extra_pass);
513
514 #endif /* _BPF_JIT_H */