]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/bpf_jit_machdep.c
Merge clang trunk r351319, resolve conflicts, and update FREEBSD-Xlist.
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / bpf_jit_machdep.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
5  * Copyright (C) 2005-2017 Jung-uk Kim <jkim@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the Politecnico di Torino nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #ifdef _KERNEL
38 #include "opt_bpf.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/socket.h>
45
46 #include <net/if.h>
47 #else
48 #include <stdlib.h>
49 #include <string.h>
50 #include <sys/mman.h>
51 #include <sys/param.h>
52 #endif
53
54 #include <sys/types.h>
55
56 #include <net/bpf.h>
57 #include <net/bpf_jitter.h>
58
59 #include <i386/i386/bpf_jit_machdep.h>
60
61 /*
62  * Emit routine to update the jump table.
63  */
64 static void
65 emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
66 {
67
68         if (stream->refs != NULL)
69                 (stream->refs)[stream->bpf_pc] += len;
70         stream->cur_ip += len;
71 }
72
73 /*
74  * Emit routine to output the actual binary code.
75  */
76 static void
77 emit_code(bpf_bin_stream *stream, u_int value, u_int len)
78 {
79
80         switch (len) {
81         case 1:
82                 stream->ibuf[stream->cur_ip] = (u_char)value;
83                 stream->cur_ip++;
84                 break;
85
86         case 2:
87                 *((u_short *)(void *)(stream->ibuf + stream->cur_ip)) =
88                     (u_short)value;
89                 stream->cur_ip += 2;
90                 break;
91
92         case 4:
93                 *((u_int *)(void *)(stream->ibuf + stream->cur_ip)) = value;
94                 stream->cur_ip += 4;
95                 break;
96         }
97
98         return;
99 }
100
101 /*
102  * Scan the filter program and find possible optimization.
103  */
104 static int
105 bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
106 {
107         int flags;
108         u_int i;
109
110         /* Do we return immediately? */
111         if (BPF_CLASS(prog[0].code) == BPF_RET)
112                 return (BPF_JIT_FRET);
113
114         for (flags = 0, i = 0; i < nins; i++) {
115                 switch (prog[i].code) {
116                 case BPF_LD|BPF_W|BPF_ABS:
117                 case BPF_LD|BPF_H|BPF_ABS:
118                 case BPF_LD|BPF_B|BPF_ABS:
119                 case BPF_LD|BPF_W|BPF_IND:
120                 case BPF_LD|BPF_H|BPF_IND:
121                 case BPF_LD|BPF_B|BPF_IND:
122                 case BPF_LDX|BPF_MSH|BPF_B:
123                         flags |= BPF_JIT_FPKT;
124                         break;
125                 case BPF_LD|BPF_MEM:
126                 case BPF_LDX|BPF_MEM:
127                 case BPF_ST:
128                 case BPF_STX:
129                         flags |= BPF_JIT_FMEM;
130                         break;
131                 case BPF_JMP|BPF_JA:
132                 case BPF_JMP|BPF_JGT|BPF_K:
133                 case BPF_JMP|BPF_JGE|BPF_K:
134                 case BPF_JMP|BPF_JEQ|BPF_K:
135                 case BPF_JMP|BPF_JSET|BPF_K:
136                 case BPF_JMP|BPF_JGT|BPF_X:
137                 case BPF_JMP|BPF_JGE|BPF_X:
138                 case BPF_JMP|BPF_JEQ|BPF_X:
139                 case BPF_JMP|BPF_JSET|BPF_X:
140                         flags |= BPF_JIT_FJMP;
141                         break;
142                 case BPF_ALU|BPF_DIV|BPF_K:
143                 case BPF_ALU|BPF_MOD|BPF_K:
144                         flags |= BPF_JIT_FADK;
145                         break;
146                 }
147                 if (flags == BPF_JIT_FLAG_ALL)
148                         break;
149         }
150
151         return (flags);
152 }
153
154 /*
155  * Function that does the real stuff.
156  */
157 bpf_filter_func
158 bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
159 {
160         bpf_bin_stream stream;
161         struct bpf_insn *ins;
162         int flags, fret, fpkt, fmem, fjmp, fadk;
163         int save_esp;
164         u_int i, pass;
165
166         /*
167          * NOTE: Do not modify the name of this variable, as it's used by
168          * the macros to emit code.
169          */
170         emit_func emitm;
171
172         flags = bpf_jit_optimize(prog, nins);
173         fret = (flags & BPF_JIT_FRET) != 0;
174         fpkt = (flags & BPF_JIT_FPKT) != 0;
175         fmem = (flags & BPF_JIT_FMEM) != 0;
176         fjmp = (flags & BPF_JIT_FJMP) != 0;
177         fadk = (flags & BPF_JIT_FADK) != 0;
178         save_esp = (fpkt || fmem || fadk);      /* Stack is used. */
179
180         if (fret)
181                 nins = 1;
182
183         memset(&stream, 0, sizeof(stream));
184
185         /* Allocate the reference table for the jumps. */
186         if (fjmp) {
187 #ifdef _KERNEL
188                 stream.refs = malloc((nins + 1) * sizeof(u_int), M_BPFJIT,
189                     M_NOWAIT | M_ZERO);
190 #else
191                 stream.refs = calloc(nins + 1, sizeof(u_int));
192 #endif
193                 if (stream.refs == NULL)
194                         return (NULL);
195         }
196
197         /*
198          * The first pass will emit the lengths of the instructions
199          * to create the reference table.
200          */
201         emitm = emit_length;
202
203         for (pass = 0; pass < 2; pass++) {
204                 ins = prog;
205
206                 /* Create the procedure header. */
207                 if (save_esp) {
208                         PUSH(EBP);
209                         MOVrd(ESP, EBP);
210                 }
211                 if (fmem)
212                         SUBib(BPF_MEMWORDS * sizeof(uint32_t), ESP);
213                 if (save_esp)
214                         PUSH(ESI);
215                 if (fpkt) {
216                         PUSH(EDI);
217                         PUSH(EBX);
218                         MOVodd(8, EBP, EBX);
219                         MOVodd(16, EBP, EDI);
220                 }
221
222                 for (i = 0; i < nins; i++) {
223                         stream.bpf_pc++;
224
225                         switch (ins->code) {
226                         default:
227 #ifdef _KERNEL
228                                 return (NULL);
229 #else
230                                 abort();
231 #endif
232
233                         case BPF_RET|BPF_K:
234                                 MOVid(ins->k, EAX);
235                                 if (save_esp) {
236                                         if (fpkt) {
237                                                 POP(EBX);
238                                                 POP(EDI);
239                                         }
240                                         POP(ESI);
241                                         LEAVE();
242                                 }
243                                 RET();
244                                 break;
245
246                         case BPF_RET|BPF_A:
247                                 if (save_esp) {
248                                         if (fpkt) {
249                                                 POP(EBX);
250                                                 POP(EDI);
251                                         }
252                                         POP(ESI);
253                                         LEAVE();
254                                 }
255                                 RET();
256                                 break;
257
258                         case BPF_LD|BPF_W|BPF_ABS:
259                                 MOVid(ins->k, ESI);
260                                 CMPrd(EDI, ESI);
261                                 JAb(12);
262                                 MOVrd(EDI, ECX);
263                                 SUBrd(ESI, ECX);
264                                 CMPid(sizeof(int32_t), ECX);
265                                 JAEb(7);
266                                 ZEROrd(EAX);
267                                 POP(EBX);
268                                 POP(EDI);
269                                 POP(ESI);
270                                 LEAVE();
271                                 RET();
272                                 MOVobd(EBX, ESI, EAX);
273                                 BSWAP(EAX);
274                                 break;
275
276                         case BPF_LD|BPF_H|BPF_ABS:
277                                 ZEROrd(EAX);
278                                 MOVid(ins->k, ESI);
279                                 CMPrd(EDI, ESI);
280                                 JAb(12);
281                                 MOVrd(EDI, ECX);
282                                 SUBrd(ESI, ECX);
283                                 CMPid(sizeof(int16_t), ECX);
284                                 JAEb(5);
285                                 POP(EBX);
286                                 POP(EDI);
287                                 POP(ESI);
288                                 LEAVE();
289                                 RET();
290                                 MOVobw(EBX, ESI, AX);
291                                 SWAP_AX();
292                                 break;
293
294                         case BPF_LD|BPF_B|BPF_ABS:
295                                 ZEROrd(EAX);
296                                 MOVid(ins->k, ESI);
297                                 CMPrd(EDI, ESI);
298                                 JBb(5);
299                                 POP(EBX);
300                                 POP(EDI);
301                                 POP(ESI);
302                                 LEAVE();
303                                 RET();
304                                 MOVobb(EBX, ESI, AL);
305                                 break;
306
307                         case BPF_LD|BPF_W|BPF_LEN:
308                                 if (save_esp)
309                                         MOVodd(12, EBP, EAX);
310                                 else {
311                                         MOVrd(ESP, ECX);
312                                         MOVodd(12, ECX, EAX);
313                                 }
314                                 break;
315
316                         case BPF_LDX|BPF_W|BPF_LEN:
317                                 if (save_esp)
318                                         MOVodd(12, EBP, EDX);
319                                 else {
320                                         MOVrd(ESP, ECX);
321                                         MOVodd(12, ECX, EDX);
322                                 }
323                                 break;
324
325                         case BPF_LD|BPF_W|BPF_IND:
326                                 CMPrd(EDI, EDX);
327                                 JAb(27);
328                                 MOVid(ins->k, ESI);
329                                 MOVrd(EDI, ECX);
330                                 SUBrd(EDX, ECX);
331                                 CMPrd(ESI, ECX);
332                                 JBb(14);
333                                 ADDrd(EDX, ESI);
334                                 MOVrd(EDI, ECX);
335                                 SUBrd(ESI, ECX);
336                                 CMPid(sizeof(int32_t), ECX);
337                                 JAEb(7);
338                                 ZEROrd(EAX);
339                                 POP(EBX);
340                                 POP(EDI);
341                                 POP(ESI);
342                                 LEAVE();
343                                 RET();
344                                 MOVobd(EBX, ESI, EAX);
345                                 BSWAP(EAX);
346                                 break;
347
348                         case BPF_LD|BPF_H|BPF_IND:
349                                 ZEROrd(EAX);
350                                 CMPrd(EDI, EDX);
351                                 JAb(27);
352                                 MOVid(ins->k, ESI);
353                                 MOVrd(EDI, ECX);
354                                 SUBrd(EDX, ECX);
355                                 CMPrd(ESI, ECX);
356                                 JBb(14);
357                                 ADDrd(EDX, ESI);
358                                 MOVrd(EDI, ECX);
359                                 SUBrd(ESI, ECX);
360                                 CMPid(sizeof(int16_t), ECX);
361                                 JAEb(5);
362                                 POP(EBX);
363                                 POP(EDI);
364                                 POP(ESI);
365                                 LEAVE();
366                                 RET();
367                                 MOVobw(EBX, ESI, AX);
368                                 SWAP_AX();
369                                 break;
370
371                         case BPF_LD|BPF_B|BPF_IND:
372                                 ZEROrd(EAX);
373                                 CMPrd(EDI, EDX);
374                                 JAEb(13);
375                                 MOVid(ins->k, ESI);
376                                 MOVrd(EDI, ECX);
377                                 SUBrd(EDX, ECX);
378                                 CMPrd(ESI, ECX);
379                                 JAb(5);
380                                 POP(EBX);
381                                 POP(EDI);
382                                 POP(ESI);
383                                 LEAVE();
384                                 RET();
385                                 ADDrd(EDX, ESI);
386                                 MOVobb(EBX, ESI, AL);
387                                 break;
388
389                         case BPF_LDX|BPF_MSH|BPF_B:
390                                 MOVid(ins->k, ESI);
391                                 CMPrd(EDI, ESI);
392                                 JBb(7);
393                                 ZEROrd(EAX);
394                                 POP(EBX);
395                                 POP(EDI);
396                                 POP(ESI);
397                                 LEAVE();
398                                 RET();
399                                 ZEROrd(EDX);
400                                 MOVobb(EBX, ESI, DL);
401                                 ANDib(0x0f, DL);
402                                 SHLib(2, EDX);
403                                 break;
404
405                         case BPF_LD|BPF_IMM:
406                                 MOVid(ins->k, EAX);
407                                 break;
408
409                         case BPF_LDX|BPF_IMM:
410                                 MOVid(ins->k, EDX);
411                                 break;
412
413                         case BPF_LD|BPF_MEM:
414                                 MOVrd(EBP, ECX);
415                                 MOVid(((int)ins->k - BPF_MEMWORDS) *
416                                     sizeof(uint32_t), ESI);
417                                 MOVobd(ECX, ESI, EAX);
418                                 break;
419
420                         case BPF_LDX|BPF_MEM:
421                                 MOVrd(EBP, ECX);
422                                 MOVid(((int)ins->k - BPF_MEMWORDS) *
423                                     sizeof(uint32_t), ESI);
424                                 MOVobd(ECX, ESI, EDX);
425                                 break;
426
427                         case BPF_ST:
428                                 /*
429                                  * XXX this command and the following could
430                                  * be optimized if the previous instruction
431                                  * was already of this type
432                                  */
433                                 MOVrd(EBP, ECX);
434                                 MOVid(((int)ins->k - BPF_MEMWORDS) *
435                                     sizeof(uint32_t), ESI);
436                                 MOVomd(EAX, ECX, ESI);
437                                 break;
438
439                         case BPF_STX:
440                                 MOVrd(EBP, ECX);
441                                 MOVid(((int)ins->k - BPF_MEMWORDS) *
442                                     sizeof(uint32_t), ESI);
443                                 MOVomd(EDX, ECX, ESI);
444                                 break;
445
446                         case BPF_JMP|BPF_JA:
447                                 JUMP(ins->k);
448                                 break;
449
450                         case BPF_JMP|BPF_JGT|BPF_K:
451                         case BPF_JMP|BPF_JGE|BPF_K:
452                         case BPF_JMP|BPF_JEQ|BPF_K:
453                         case BPF_JMP|BPF_JSET|BPF_K:
454                         case BPF_JMP|BPF_JGT|BPF_X:
455                         case BPF_JMP|BPF_JGE|BPF_X:
456                         case BPF_JMP|BPF_JEQ|BPF_X:
457                         case BPF_JMP|BPF_JSET|BPF_X:
458                                 if (ins->jt == ins->jf) {
459                                         JUMP(ins->jt);
460                                         break;
461                                 }
462                                 switch (ins->code) {
463                                 case BPF_JMP|BPF_JGT|BPF_K:
464                                         CMPid(ins->k, EAX);
465                                         JCC(JA, JBE);
466                                         break;
467
468                                 case BPF_JMP|BPF_JGE|BPF_K:
469                                         CMPid(ins->k, EAX);
470                                         JCC(JAE, JB);
471                                         break;
472
473                                 case BPF_JMP|BPF_JEQ|BPF_K:
474                                         CMPid(ins->k, EAX);
475                                         JCC(JE, JNE);
476                                         break;
477
478                                 case BPF_JMP|BPF_JSET|BPF_K:
479                                         TESTid(ins->k, EAX);
480                                         JCC(JNE, JE);
481                                         break;
482
483                                 case BPF_JMP|BPF_JGT|BPF_X:
484                                         CMPrd(EDX, EAX);
485                                         JCC(JA, JBE);
486                                         break;
487
488                                 case BPF_JMP|BPF_JGE|BPF_X:
489                                         CMPrd(EDX, EAX);
490                                         JCC(JAE, JB);
491                                         break;
492
493                                 case BPF_JMP|BPF_JEQ|BPF_X:
494                                         CMPrd(EDX, EAX);
495                                         JCC(JE, JNE);
496                                         break;
497
498                                 case BPF_JMP|BPF_JSET|BPF_X:
499                                         TESTrd(EDX, EAX);
500                                         JCC(JNE, JE);
501                                         break;
502                                 }
503                                 break;
504
505                         case BPF_ALU|BPF_ADD|BPF_X:
506                                 ADDrd(EDX, EAX);
507                                 break;
508
509                         case BPF_ALU|BPF_SUB|BPF_X:
510                                 SUBrd(EDX, EAX);
511                                 break;
512
513                         case BPF_ALU|BPF_MUL|BPF_X:
514                                 MOVrd(EDX, ECX);
515                                 MULrd(EDX);
516                                 MOVrd(ECX, EDX);
517                                 break;
518
519                         case BPF_ALU|BPF_DIV|BPF_X:
520                         case BPF_ALU|BPF_MOD|BPF_X:
521                                 TESTrd(EDX, EDX);
522                                 if (save_esp) {
523                                         if (fpkt) {
524                                                 JNEb(7);
525                                                 ZEROrd(EAX);
526                                                 POP(EBX);
527                                                 POP(EDI);
528                                         } else {
529                                                 JNEb(5);
530                                                 ZEROrd(EAX);
531                                         }
532                                         POP(ESI);
533                                         LEAVE();
534                                 } else {
535                                         JNEb(3);
536                                         ZEROrd(EAX);
537                                 }
538                                 RET();
539                                 MOVrd(EDX, ECX);
540                                 ZEROrd(EDX);
541                                 DIVrd(ECX);
542                                 if (BPF_OP(ins->code) == BPF_MOD)
543                                         MOVrd(EDX, EAX);
544                                 MOVrd(ECX, EDX);
545                                 break;
546
547                         case BPF_ALU|BPF_AND|BPF_X:
548                                 ANDrd(EDX, EAX);
549                                 break;
550
551                         case BPF_ALU|BPF_OR|BPF_X:
552                                 ORrd(EDX, EAX);
553                                 break;
554
555                         case BPF_ALU|BPF_XOR|BPF_X:
556                                 XORrd(EDX, EAX);
557                                 break;
558
559                         case BPF_ALU|BPF_LSH|BPF_X:
560                                 MOVrd(EDX, ECX);
561                                 SHL_CLrb(EAX);
562                                 break;
563
564                         case BPF_ALU|BPF_RSH|BPF_X:
565                                 MOVrd(EDX, ECX);
566                                 SHR_CLrb(EAX);
567                                 break;
568
569                         case BPF_ALU|BPF_ADD|BPF_K:
570                                 ADD_EAXi(ins->k);
571                                 break;
572
573                         case BPF_ALU|BPF_SUB|BPF_K:
574                                 SUB_EAXi(ins->k);
575                                 break;
576
577                         case BPF_ALU|BPF_MUL|BPF_K:
578                                 MOVrd(EDX, ECX);
579                                 MOVid(ins->k, EDX);
580                                 MULrd(EDX);
581                                 MOVrd(ECX, EDX);
582                                 break;
583
584                         case BPF_ALU|BPF_DIV|BPF_K:
585                         case BPF_ALU|BPF_MOD|BPF_K:
586                                 MOVrd(EDX, ECX);
587                                 ZEROrd(EDX);
588                                 MOVid(ins->k, ESI);
589                                 DIVrd(ESI);
590                                 if (BPF_OP(ins->code) == BPF_MOD)
591                                         MOVrd(EDX, EAX);
592                                 MOVrd(ECX, EDX);
593                                 break;
594
595                         case BPF_ALU|BPF_AND|BPF_K:
596                                 ANDid(ins->k, EAX);
597                                 break;
598
599                         case BPF_ALU|BPF_OR|BPF_K:
600                                 ORid(ins->k, EAX);
601                                 break;
602
603                         case BPF_ALU|BPF_XOR|BPF_K:
604                                 XORid(ins->k, EAX);
605                                 break;
606
607                         case BPF_ALU|BPF_LSH|BPF_K:
608                                 SHLib((ins->k) & 0xff, EAX);
609                                 break;
610
611                         case BPF_ALU|BPF_RSH|BPF_K:
612                                 SHRib((ins->k) & 0xff, EAX);
613                                 break;
614
615                         case BPF_ALU|BPF_NEG:
616                                 NEGd(EAX);
617                                 break;
618
619                         case BPF_MISC|BPF_TAX:
620                                 MOVrd(EAX, EDX);
621                                 break;
622
623                         case BPF_MISC|BPF_TXA:
624                                 MOVrd(EDX, EAX);
625                                 break;
626                         }
627                         ins++;
628                 }
629
630                 if (pass > 0)
631                         continue;
632
633                 *size = stream.cur_ip;
634 #ifdef _KERNEL
635                 stream.ibuf = malloc(*size, M_BPFJIT, M_EXEC | M_NOWAIT);
636                 if (stream.ibuf == NULL)
637                         break;
638 #else
639                 stream.ibuf = mmap(NULL, *size, PROT_READ | PROT_WRITE,
640                     MAP_ANON, -1, 0);
641                 if (stream.ibuf == MAP_FAILED) {
642                         stream.ibuf = NULL;
643                         break;
644                 }
645 #endif
646
647                 /*
648                  * Modify the reference table to contain the offsets and
649                  * not the lengths of the instructions.
650                  */
651                 if (fjmp)
652                         for (i = 1; i < nins + 1; i++)
653                                 stream.refs[i] += stream.refs[i - 1];
654
655                 /* Reset the counters. */
656                 stream.cur_ip = 0;
657                 stream.bpf_pc = 0;
658
659                 /* The second pass creates the actual code. */
660                 emitm = emit_code;
661         }
662
663         /*
664          * The reference table is needed only during compilation,
665          * now we can free it.
666          */
667         if (fjmp)
668 #ifdef _KERNEL
669                 free(stream.refs, M_BPFJIT);
670 #else
671                 free(stream.refs);
672 #endif
673
674 #ifndef _KERNEL
675         if (stream.ibuf != NULL &&
676             mprotect(stream.ibuf, *size, PROT_READ | PROT_EXEC) != 0) {
677                 munmap(stream.ibuf, *size);
678                 stream.ibuf = NULL;
679         }
680 #endif
681
682         return ((bpf_filter_func)(void *)stream.ibuf);
683 }