Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | /* bpf_jit.S : BPF JIT helper functions * * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; version 2 * of the License. */ #include <linux/linkage.h> #include <asm/frame.h> /* * Calling convention : * rbx : skb pointer (callee saved) * esi : offset of byte(s) to fetch in skb (can be scratched) * r10 : copy of skb->data * r9d : hlen = skb->len - skb->data_len */ #define SKBDATA %r10 #define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */ #define MAX_BPF_STACK (512 /* from filter.h */ + \ 32 /* space for rbx,r13,r14,r15 */ + \ 8 /* space for skb_copy_bits */) #define FUNC(name) \ .globl name; \ .type name, @function; \ name: FUNC(sk_load_word) test %esi,%esi js bpf_slow_path_word_neg FUNC(sk_load_word_positive_offset) mov %r9d,%eax # hlen sub %esi,%eax # hlen - offset cmp $3,%eax jle bpf_slow_path_word mov (SKBDATA,%rsi),%eax bswap %eax /* ntohl() */ ret FUNC(sk_load_half) test %esi,%esi js bpf_slow_path_half_neg FUNC(sk_load_half_positive_offset) mov %r9d,%eax sub %esi,%eax # hlen - offset cmp $1,%eax jle bpf_slow_path_half movzwl (SKBDATA,%rsi),%eax rol $8,%ax # ntohs() ret FUNC(sk_load_byte) test %esi,%esi js bpf_slow_path_byte_neg FUNC(sk_load_byte_positive_offset) cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ jle bpf_slow_path_byte movzbl (SKBDATA,%rsi),%eax ret /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ lea -MAX_BPF_STACK + 32(%rbp), %rdx;\ FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $LEN,%ecx; /* len */ \ call skb_copy_bits; \ test %eax,%eax; \ pop SKBDATA; \ pop %r9; \ FRAME_END bpf_slow_path_word: bpf_slow_path_common(4) js bpf_error mov - MAX_BPF_STACK + 32(%rbp),%eax bswap %eax ret bpf_slow_path_half: bpf_slow_path_common(2) js bpf_error mov - MAX_BPF_STACK + 32(%rbp),%ax rol $8,%ax movzwl %ax,%eax ret bpf_slow_path_byte: bpf_slow_path_common(1) js bpf_error movzbl - MAX_BPF_STACK + 32(%rbp),%eax ret #define sk_negative_common(SIZE) \ FRAME_BEGIN; \ mov %rbx, %rdi; /* arg1 == skb */ \ push %r9; \ push SKBDATA; \ /* rsi already has offset */ \ mov $SIZE,%edx; /* size */ \ call bpf_internal_load_pointer_neg_helper; \ test %rax,%rax; \ pop SKBDATA; \ pop %r9; \ FRAME_END; \ jz bpf_error bpf_slow_path_word_neg: cmp SKF_MAX_NEG_OFF, %esi /* test range */ jl bpf_error /* offset lower -> error */ FUNC(sk_load_word_negative_offset) sk_negative_common(4) mov (%rax), %eax bswap %eax ret bpf_slow_path_half_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error FUNC(sk_load_half_negative_offset) sk_negative_common(2) mov (%rax),%ax rol $8,%ax movzwl %ax,%eax ret bpf_slow_path_byte_neg: cmp SKF_MAX_NEG_OFF, %esi jl bpf_error FUNC(sk_load_byte_negative_offset) sk_negative_common(1) movzbl (%rax), %eax ret bpf_error: # force a return 0 from jit handler xor %eax,%eax mov - MAX_BPF_STACK(%rbp),%rbx mov - MAX_BPF_STACK + 8(%rbp),%r13 mov - MAX_BPF_STACK + 16(%rbp),%r14 mov - MAX_BPF_STACK + 24(%rbp),%r15 leaveq ret |