€•¼ÄŒsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ+/translations/zh_CN/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/zh_TW/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/it_IT/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ja_JP/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ko_KR/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/pt_BR/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/sp_SP/bpf/classic_vs_extended”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒClassic BPF vs eBPF”h]”hŒClassic BPF vs eBPF”…”�”}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒE/var/lib/git/docbuild/linux/Documentation/bpf/classic_vs_extended.rst”h´KubhŒ paragraph”“”)�”}”(hŒãeBPF is designed to be JITed with one to one mapping, which can also open up the possibility for GCC/LLVM compilers to generate optimized eBPF code through an eBPF backend that performs almost as fast as natively compiled code.”h]”hŒãeBPF is designed to be JITed with one to one mapping, which can also open up the possibility for GCC/LLVM compilers to generate optimized eBPF code through an eBPF backend that performs almost as fast as natively compiled code.”…”�”}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)�”}”(hŒ6Some core changes of the eBPF format from classic BPF:”h]”hŒ6Some core changes of the eBPF format from classic BPF:”…”�”}”(hhÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hX¼Number of registers increase from 2 to 10: The old format had two registers A and X, and a hidden frame pointer. The new layout extends this to be 10 internal registers and a read-only frame pointer. Since 64-bit CPUs are passing arguments to functions via registers the number of args from eBPF program to in-kernel function is restricted to 5 and one register is used to accept return value from an in-kernel function. Natively, x86_64 passes first 6 arguments in registers, aarch64/ sparcv9/mips64 have 7 - 8 registers for arguments; x86_64 has 6 callee saved registers, and aarch64/sparcv9/mips64 have 11 or more callee saved registers. Thus, all eBPF registers map one to one to HW registers on x86_64, aarch64, etc, and eBPF calling convention maps directly to ABIs used by the kernel on 64-bit architectures. On 32-bit architectures JIT may map programs that use only 32-bit arithmetic and may let more complex programs to be interpreted. R0 - R5 are scratch registers and eBPF program needs spill/fill them if necessary across calls. Note that there is only one eBPF program (== one eBPF main routine) and it cannot call other eBPF functions, it can only call predefined in-kernel functions, though. ”h]”(hÌ)�”}”(hŒ*Number of registers increase from 2 to 10:”h]”hŒ*Number of registers increase from 2 to 10:”…”�”}”(hhôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hhðubhÌ)�”}”(hXUThe old format had two registers A and X, and a hidden frame pointer. The new layout extends this to be 10 internal registers and a read-only frame pointer. Since 64-bit CPUs are passing arguments to functions via registers the number of args from eBPF program to in-kernel function is restricted to 5 and one register is used to accept return value from an in-kernel function. Natively, x86_64 passes first 6 arguments in registers, aarch64/ sparcv9/mips64 have 7 - 8 registers for arguments; x86_64 has 6 callee saved registers, and aarch64/sparcv9/mips64 have 11 or more callee saved registers.”h]”hXUThe old format had two registers A and X, and a hidden frame pointer. The new layout extends this to be 10 internal registers and a read-only frame pointer. Since 64-bit CPUs are passing arguments to functions via registers the number of args from eBPF program to in-kernel function is restricted to 5 and one register is used to accept return value from an in-kernel function. Natively, x86_64 passes first 6 arguments in registers, aarch64/ sparcv9/mips64 have 7 - 8 registers for arguments; x86_64 has 6 callee saved registers, and aarch64/sparcv9/mips64 have 11 or more callee saved registers.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhhðubhÌ)�”}”(hŒ®Thus, all eBPF registers map one to one to HW registers on x86_64, aarch64, etc, and eBPF calling convention maps directly to ABIs used by the kernel on 64-bit architectures.”h]”hŒ®Thus, all eBPF registers map one to one to HW registers on x86_64, aarch64, etc, and eBPF calling convention maps directly to ABIs used by the kernel on 64-bit architectures.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhhðubhÌ)�”}”(hŒ�On 32-bit architectures JIT may map programs that use only 32-bit arithmetic and may let more complex programs to be interpreted.”h]”hŒ�On 32-bit architectures JIT may map programs that use only 32-bit arithmetic and may let more complex programs to be interpreted.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KhhðubhÌ)�”}”(hXR0 - R5 are scratch registers and eBPF program needs spill/fill them if necessary across calls. Note that there is only one eBPF program (== one eBPF main routine) and it cannot call other eBPF functions, it can only call predefined in-kernel functions, though.”h]”hXR0 - R5 are scratch registers and eBPF program needs spill/fill them if necessary across calls. Note that there is only one eBPF program (== one eBPF main routine) and it cannot call other eBPF functions, it can only call predefined in-kernel functions, though.”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhðubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhhëh²hh³hÊh´Nubhï)�”}”(hX0Register width increases from 32-bit to 64-bit: Still, the semantics of the original 32-bit ALU operations are preserved via 32-bit subregisters. All eBPF registers are 64-bit with 32-bit lower subregisters that zero-extend into 64-bit if they are being written to. That behavior maps directly to x86_64 and arm64 subregister definition, but makes other JITs more difficult. 32-bit architectures run 64-bit eBPF programs via interpreter. Their JITs may convert BPF programs that only use 32-bit subregisters into native instruction set and let the rest being interpreted. Operation is 64-bit, because on 64-bit architectures, pointers are also 64-bit wide, and we want to pass 64-bit values in/out of kernel functions, so 32-bit eBPF registers would otherwise require to define register-pair ABI, thus, there won't be able to use a direct eBPF register to HW register mapping and JIT would need to do combine/split/move operations for every register in and out of the function, which is complex, bug prone and slow. Another reason is the use of atomic 64-bit counters. ”h]”(hÌ)�”}”(hŒ/Register width increases from 32-bit to 64-bit:”h]”hŒ/Register width increases from 32-bit to 64-bit:”…”�”}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K#hj@ubhÌ)�”}”(hXFStill, the semantics of the original 32-bit ALU operations are preserved via 32-bit subregisters. All eBPF registers are 64-bit with 32-bit lower subregisters that zero-extend into 64-bit if they are being written to. That behavior maps directly to x86_64 and arm64 subregister definition, but makes other JITs more difficult.”h]”hXFStill, the semantics of the original 32-bit ALU operations are preserved via 32-bit subregisters. All eBPF registers are 64-bit with 32-bit lower subregisters that zero-extend into 64-bit if they are being written to. That behavior maps directly to x86_64 and arm64 subregister definition, but makes other JITs more difficult.”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K%hj@ubhÌ)�”}”(hŒÄ32-bit architectures run 64-bit eBPF programs via interpreter. Their JITs may convert BPF programs that only use 32-bit subregisters into native instruction set and let the rest being interpreted.”h]”hŒÄ32-bit architectures run 64-bit eBPF programs via interpreter. Their JITs may convert BPF programs that only use 32-bit subregisters into native instruction set and let the rest being interpreted.”…”�”}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K+hj@ubhÌ)�”}”(hXðOperation is 64-bit, because on 64-bit architectures, pointers are also 64-bit wide, and we want to pass 64-bit values in/out of kernel functions, so 32-bit eBPF registers would otherwise require to define register-pair ABI, thus, there won't be able to use a direct eBPF register to HW register mapping and JIT would need to do combine/split/move operations for every register in and out of the function, which is complex, bug prone and slow. Another reason is the use of atomic 64-bit counters.”h]”hXòOperation is 64-bit, because on 64-bit architectures, pointers are also 64-bit wide, and we want to pass 64-bit values in/out of kernel functions, so 32-bit eBPF registers would otherwise require to define register-pair ABI, thus, there won’t be able to use a direct eBPF register to HW register mapping and JIT would need to do combine/split/move operations for every register in and out of the function, which is complex, bug prone and slow. Another reason is the use of atomic 64-bit counters.”…”�”}”(hjnh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K/hj@ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhhëh²hh³hÊh´Nubhï)�”}”(hXConditional jt/jf targets replaced with jt/fall-through: While the original design has constructs such as ``if (cond) jump_true; else jump_false;``, they are being replaced into alternative constructs like ``if (cond) jump_true; /* else fall-through */``. ”h]”(hÌ)�”}”(hŒ8Conditional jt/jf targets replaced with jt/fall-through:”h]”hŒ8Conditional jt/jf targets replaced with jt/fall-through:”…”�”}”(hj†h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K7hj‚ubhÌ)�”}”(hŒÆWhile the original design has constructs such as ``if (cond) jump_true; else jump_false;``, they are being replaced into alternative constructs like ``if (cond) jump_true; /* else fall-through */``.”h]”(hŒ1While the original design has constructs such as ”…”�”}”(hj”h²hh³Nh´NubhŒliteral”“”)�”}”(hŒ)``if (cond) jump_true; else jump_false;``”h]”hŒ%if (cond) jump_true; else jump_false;”…”�”}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhj”ubhŒ;, they are being replaced into alternative constructs like ”…”�”}”(hj”h²hh³Nh´Nubj�)�”}”(hŒ0``if (cond) jump_true; /* else fall-through */``”h]”hŒ,if (cond) jump_true; /* else fall-through */”…”�”}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhj”ubhŒ.”…”�”}”(hj”h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K9hj‚ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhhëh²hh³hÊh´Nubhï)�”}”(hXÐIntroduces bpf_call insn and register passing convention for zero overhead calls from/to other kernel functions: Before an in-kernel function call, the eBPF program needs to place function arguments into R1 to R5 registers to satisfy calling convention, then the interpreter will take them from registers and pass to in-kernel function. If R1 - R5 registers are mapped to CPU registers that are used for argument passing on given architecture, the JIT compiler doesn't need to emit extra moves. Function arguments will be in the correct registers and BPF_CALL instruction will be JITed as single 'call' HW instruction. This calling convention was picked to cover common call situations without performance penalty. After an in-kernel function call, R1 - R5 are reset to unreadable and R0 has a return value of the function. Since R6 - R9 are callee saved, their state is preserved across the call. For example, consider three C functions:: u64 f1() { return (*_f2)(1); } u64 f2(u64 a) { return f3(a + 1, a); } u64 f3(u64 a, u64 b) { return a - b; } GCC can compile f1, f3 into x86_64:: f1: movl $1, %edi movq _f2(%rip), %rax jmp *%rax f3: movq %rdi, %rax subq %rsi, %rax ret Function f2 in eBPF may look like:: f2: bpf_mov R2, R1 bpf_add R1, 1 bpf_call f3 bpf_exit If f2 is JITed and the pointer stored to ``_f2``. The calls f1 -> f2 -> f3 and returns will be seamless. Without JIT, __bpf_prog_run() interpreter needs to be used to call into f2. For practical reasons all eBPF programs have only one argument 'ctx' which is already placed into R1 (e.g. on __bpf_prog_run() startup) and the programs can call kernel functions with up to 5 arguments. Calls with 6 or more arguments are currently not supported, but these restrictions can be lifted if necessary in the future. On 64-bit architectures all register map to HW registers one to one. For example, x86_64 JIT compiler can map them as ... :: R0 - rax R1 - rdi R2 - rsi R3 - rdx R4 - rcx R5 - r8 R6 - rbx R7 - r13 R8 - r14 R9 - r15 R10 - rbp ... since x86_64 ABI mandates rdi, rsi, rdx, rcx, r8, r9 for argument passing and rbx, r12 - r15 are callee saved. Then the following eBPF pseudo-program:: bpf_mov R6, R1 /* save ctx */ bpf_mov R2, 2 bpf_mov R3, 3 bpf_mov R4, 4 bpf_mov R5, 5 bpf_call foo bpf_mov R7, R0 /* save foo() return value */ bpf_mov R1, R6 /* restore ctx for next call */ bpf_mov R2, 6 bpf_mov R3, 7 bpf_mov R4, 8 bpf_mov R5, 9 bpf_call bar bpf_add R0, R7 bpf_exit After JIT to x86_64 may look like:: push %rbp mov %rsp,%rbp sub $0x228,%rsp mov %rbx,-0x228(%rbp) mov %r13,-0x220(%rbp) mov %rdi,%rbx mov $0x2,%esi mov $0x3,%edx mov $0x4,%ecx mov $0x5,%r8d callq foo mov %rax,%r13 mov %rbx,%rdi mov $0x6,%esi mov $0x7,%edx mov $0x8,%ecx mov $0x9,%r8d callq bar add %r13,%rax mov -0x228(%rbp),%rbx mov -0x220(%rbp),%r13 leaveq retq Which is in this example equivalent in C to:: u64 bpf_filter(u64 ctx) { return foo(ctx, 2, 3, 4, 5) + bar(ctx, 6, 7, 8, 9); } In-kernel functions foo() and bar() with prototype: u64 (*)(u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5); will receive arguments in proper registers and place their return value into ``%rax`` which is R0 in eBPF. Prologue and epilogue are emitted by JIT and are implicit in the interpreter. R0-R5 are scratch registers, so eBPF program needs to preserve them across the calls as defined by calling convention. For example the following program is invalid:: bpf_mov R1, 1 bpf_call foo bpf_mov R0, R1 bpf_exit After the call the registers R1-R5 contain junk values and cannot be read. An in-kernel verifier.rst is used to validate eBPF programs. ”h]”(hÌ)�”}”(hŒpIntroduces bpf_call insn and register passing convention for zero overhead calls from/to other kernel functions:”h]”hŒpIntroduces bpf_call insn and register passing convention for zero overhead calls from/to other kernel functions:”…”�”}”(hjÒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K=hjÎubhÌ)�”}”(hXYBefore an in-kernel function call, the eBPF program needs to place function arguments into R1 to R5 registers to satisfy calling convention, then the interpreter will take them from registers and pass to in-kernel function. If R1 - R5 registers are mapped to CPU registers that are used for argument passing on given architecture, the JIT compiler doesn't need to emit extra moves. Function arguments will be in the correct registers and BPF_CALL instruction will be JITed as single 'call' HW instruction. This calling convention was picked to cover common call situations without performance penalty.”h]”hX_Before an in-kernel function call, the eBPF program needs to place function arguments into R1 to R5 registers to satisfy calling convention, then the interpreter will take them from registers and pass to in-kernel function. If R1 - R5 registers are mapped to CPU registers that are used for argument passing on given architecture, the JIT compiler doesn’t need to emit extra moves. Function arguments will be in the correct registers and BPF_CALL instruction will be JITed as single ‘call’ HW instruction. This calling convention was picked to cover common call situations without performance penalty.”…”�”}”(hjàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K@hjÎubhÌ)�”}”(hŒ¶After an in-kernel function call, R1 - R5 are reset to unreadable and R0 has a return value of the function. Since R6 - R9 are callee saved, their state is preserved across the call.”h]”hŒ¶After an in-kernel function call, R1 - R5 are reset to unreadable and R0 has a return value of the function. Since R6 - R9 are callee saved, their state is preserved across the call.”…”�”}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KJhjÎubhÌ)�”}”(hŒ)For example, consider three C functions::”h]”hŒ(For example, consider three C functions:”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KNhjÎubhŒ literal_block”“”)�”}”(hŒlu64 f1() { return (*_f2)(1); } u64 f2(u64 a) { return f3(a + 1, a); } u64 f3(u64 a, u64 b) { return a - b; }”h]”hŒlu64 f1() { return (*_f2)(1); } u64 f2(u64 a) { return f3(a + 1, a); } u64 f3(u64 a, u64 b) { return a - b; }”…”�”}”hj sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1j h³hÊh´KPhjÎubhÌ)�”}”(hŒ$GCC can compile f1, f3 into x86_64::”h]”hŒ#GCC can compile f1, f3 into x86_64:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KThjÎubj )�”}”(hŒqf1: movl $1, %edi movq _f2(%rip), %rax jmp *%rax f3: movq %rdi, %rax subq %rsi, %rax ret”h]”hŒqf1: movl $1, %edi movq _f2(%rip), %rax jmp *%rax f3: movq %rdi, %rax subq %rsi, %rax ret”…”�”}”hj*sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KVhjÎubhÌ)�”}”(hŒ#Function f2 in eBPF may look like::”h]”hŒ"Function f2 in eBPF may look like:”…”�”}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K_hjÎubj )�”}”(hŒEf2: bpf_mov R2, R1 bpf_add R1, 1 bpf_call f3 bpf_exit”h]”hŒEf2: bpf_mov R2, R1 bpf_add R1, 1 bpf_call f3 bpf_exit”…”�”}”hjFsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KahjÎubhÌ)�”}”(hŒ´If f2 is JITed and the pointer stored to ``_f2``. The calls f1 -> f2 -> f3 and returns will be seamless. Without JIT, __bpf_prog_run() interpreter needs to be used to call into f2.”h]”(hŒ)If f2 is JITed and the pointer stored to ”…”�”}”(hjTh²hh³Nh´Nubj�)�”}”(hŒ``_f2``”h]”hŒ_f2”…”�”}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhjTubhŒ„. The calls f1 -> f2 -> f3 and returns will be seamless. Without JIT, __bpf_prog_run() interpreter needs to be used to call into f2.”…”�”}”(hjTh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KghjÎubhÌ)�”}”(hXGFor practical reasons all eBPF programs have only one argument 'ctx' which is already placed into R1 (e.g. on __bpf_prog_run() startup) and the programs can call kernel functions with up to 5 arguments. Calls with 6 or more arguments are currently not supported, but these restrictions can be lifted if necessary in the future.”h]”hXKFor practical reasons all eBPF programs have only one argument ‘ctx’ which is already placed into R1 (e.g. on __bpf_prog_run() startup) and the programs can call kernel functions with up to 5 arguments. Calls with 6 or more arguments are currently not supported, but these restrictions can be lifted if necessary in the future.”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KkhjÎubhÌ)�”}”(hŒyOn 64-bit architectures all register map to HW registers one to one. For example, x86_64 JIT compiler can map them as ...”h]”hŒyOn 64-bit architectures all register map to HW registers one to one. For example, x86_64 JIT compiler can map them as ...”…”�”}”(hj‚h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KqhjÎubj )�”}”(hŒbR0 - rax R1 - rdi R2 - rsi R3 - rdx R4 - rcx R5 - r8 R6 - rbx R7 - r13 R8 - r14 R9 - r15 R10 - rbp”h]”hŒbR0 - rax R1 - rdi R2 - rsi R3 - rdx R4 - rcx R5 - r8 R6 - rbx R7 - r13 R8 - r14 R9 - r15 R10 - rbp”…”�”}”hj�sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KvhjÎubhÌ)�”}”(hŒr... since x86_64 ABI mandates rdi, rsi, rdx, rcx, r8, r9 for argument passing and rbx, r12 - r15 are callee saved.”h]”hŒr... since x86_64 ABI mandates rdi, rsi, rdx, rcx, r8, r9 for argument passing and rbx, r12 - r15 are callee saved.”…”�”}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K‚hjÎubhÌ)�”}”(hŒ(Then the following eBPF pseudo-program::”h]”hŒ'Then the following eBPF pseudo-program:”…”�”}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K…hjÎubj )�”}”(hXbpf_mov R6, R1 /* save ctx */ bpf_mov R2, 2 bpf_mov R3, 3 bpf_mov R4, 4 bpf_mov R5, 5 bpf_call foo bpf_mov R7, R0 /* save foo() return value */ bpf_mov R1, R6 /* restore ctx for next call */ bpf_mov R2, 6 bpf_mov R3, 7 bpf_mov R4, 8 bpf_mov R5, 9 bpf_call bar bpf_add R0, R7 bpf_exit”h]”hXbpf_mov R6, R1 /* save ctx */ bpf_mov R2, 2 bpf_mov R3, 3 bpf_mov R4, 4 bpf_mov R5, 5 bpf_call foo bpf_mov R7, R0 /* save foo() return value */ bpf_mov R1, R6 /* restore ctx for next call */ bpf_mov R2, 6 bpf_mov R3, 7 bpf_mov R4, 8 bpf_mov R5, 9 bpf_call bar bpf_add R0, R7 bpf_exit”…”�”}”hjºsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´K‡hjÎubhÌ)�”}”(hŒ#After JIT to x86_64 may look like::”h]”hŒ"After JIT to x86_64 may look like:”…”�”}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K—hjÎubj )�”}”(hXGpush %rbp mov %rsp,%rbp sub $0x228,%rsp mov %rbx,-0x228(%rbp) mov %r13,-0x220(%rbp) mov %rdi,%rbx mov $0x2,%esi mov $0x3,%edx mov $0x4,%ecx mov $0x5,%r8d callq foo mov %rax,%r13 mov %rbx,%rdi mov $0x6,%esi mov $0x7,%edx mov $0x8,%ecx mov $0x9,%r8d callq bar add %r13,%rax mov -0x228(%rbp),%rbx mov -0x220(%rbp),%r13 leaveq retq”h]”hXGpush %rbp mov %rsp,%rbp sub $0x228,%rsp mov %rbx,-0x228(%rbp) mov %r13,-0x220(%rbp) mov %rdi,%rbx mov $0x2,%esi mov $0x3,%edx mov $0x4,%ecx mov $0x5,%r8d callq foo mov %rax,%r13 mov %rbx,%rdi mov $0x6,%esi mov $0x7,%edx mov $0x8,%ecx mov $0x9,%r8d callq bar add %r13,%rax mov -0x228(%rbp),%rbx mov -0x220(%rbp),%r13 leaveq retq”…”�”}”hjÖsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´K™hjÎubhÌ)�”}”(hŒ-Which is in this example equivalent in C to::”h]”hŒ,Which is in this example equivalent in C to:”…”�”}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K±hjÎubj )�”}”(hŒSu64 bpf_filter(u64 ctx) { return foo(ctx, 2, 3, 4, 5) + bar(ctx, 6, 7, 8, 9); }”h]”hŒSu64 bpf_filter(u64 ctx) { return foo(ctx, 2, 3, 4, 5) + bar(ctx, 6, 7, 8, 9); }”…”�”}”hjòsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´K³hjÎubhÌ)�”}”(hXžIn-kernel functions foo() and bar() with prototype: u64 (*)(u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5); will receive arguments in proper registers and place their return value into ``%rax`` which is R0 in eBPF. Prologue and epilogue are emitted by JIT and are implicit in the interpreter. R0-R5 are scratch registers, so eBPF program needs to preserve them across the calls as defined by calling convention.”h]”(hŒ¼In-kernel functions foo() and bar() with prototype: u64 (*)(u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5); will receive arguments in proper registers and place their return value into ”…”�”}”(hjh²hh³Nh´Nubj�)�”}”(hŒ``%rax``”h]”hŒ%rax”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhjubhŒÚ which is R0 in eBPF. Prologue and epilogue are emitted by JIT and are implicit in the interpreter. R0-R5 are scratch registers, so eBPF program needs to preserve them across the calls as defined by calling convention.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¸hjÎubhÌ)�”}”(hŒ.For example the following program is invalid::”h]”hŒ-For example the following program is invalid:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¿hjÎubj )�”}”(hŒ2bpf_mov R1, 1 bpf_call foo bpf_mov R0, R1 bpf_exit”h]”hŒ2bpf_mov R1, 1 bpf_call foo bpf_mov R0, R1 bpf_exit”…”�”}”hj.sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KÁhjÎubhÌ)�”}”(hŒ‡After the call the registers R1-R5 contain junk values and cannot be read. An in-kernel verifier.rst is used to validate eBPF programs.”h]”hŒ‡After the call the registers R1-R5 contain junk values and cannot be read. An in-kernel verifier.rst is used to validate eBPF programs.”…”�”}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÆhjÎubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhhëh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1héh³hÊh´K hh·h²hubhÌ)�”}”(hX%Also in the new design, eBPF is limited to 4096 insns, which means that any program will terminate quickly and will only call a fixed number of kernel functions. Original BPF and eBPF are two operand instructions, which helps to do one-to-one mapping between eBPF insn and x86 insn during JIT.”h]”hX%Also in the new design, eBPF is limited to 4096 insns, which means that any program will terminate quickly and will only call a fixed number of kernel functions. Original BPF and eBPF are two operand instructions, which helps to do one-to-one mapping between eBPF insn and x86 insn during JIT.”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÉhh·h²hubhÌ)�”}”(hŒØThe input context pointer for invoking the interpreter function is generic, its content is defined by a specific use case. For seccomp register R1 points to seccomp_data, for converted BPF filters R1 points to a skb.”h]”hŒØThe input context pointer for invoking the interpreter function is generic, its content is defined by a specific use case. For seccomp register R1 points to seccomp_data, for converted BPF filters R1 points to a skb.”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÎhh·h²hubhÌ)�”}”(hŒMA program, that is translated internally consists of the following elements::”h]”hŒLA program, that is translated internally consists of the following elements:”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÒhh·h²hubj )�”}”(hŒLop:16, jt:8, jf:8, k:32 ==> op:8, dst_reg:4, src_reg:4, off:16, imm:32”h]”hŒLop:16, jt:8, jf:8, k:32 ==> op:8, dst_reg:4, src_reg:4, off:16, imm:32”…”�”}”hj‚sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KÔhh·h²hubhÌ)�”}”(hŒâSo far 87 eBPF instructions were implemented. 8-bit 'op' opcode field has room for new instructions. Some of them may use 16/24/32 byte encoding. New instructions must be multiple of 8 bytes to preserve backward compatibility.”h]”hŒæSo far 87 eBPF instructions were implemented. 8-bit ‘op’ opcode field has room for new instructions. Some of them may use 16/24/32 byte encoding. New instructions must be multiple of 8 bytes to preserve backward compatibility.”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÖhh·h²hubhÌ)�”}”(hX¼eBPF is a general purpose RISC instruction set. Not every register and every instruction are used during translation from original BPF to eBPF. For example, socket filters are not using ``exclusive add`` instruction, but tracing filters may do to maintain counters of events, for example. Register R9 is not used by socket filters either, but more complex filters may be running out of registers and would have to resort to spill/fill to stack.”h]”(hŒºeBPF is a general purpose RISC instruction set. Not every register and every instruction are used during translation from original BPF to eBPF. For example, socket filters are not using ”…”�”}”(hjžh²hh³Nh´Nubj�)�”}”(hŒ``exclusive add``”h]”hŒ exclusive add”…”�”}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhjžubhŒñ instruction, but tracing filters may do to maintain counters of events, for example. Register R9 is not used by socket filters either, but more complex filters may be running out of registers and would have to resort to spill/fill to stack.”…”�”}”(hjžh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÚhh·h²hubhÌ)�”}”(hXêeBPF can be used as a generic assembler for last step performance optimizations, socket filters and seccomp are using it as assembler. Tracing filters may use it as assembler to generate code from kernel. In kernel usage may not be bounded by security considerations, since generated eBPF code may be optimizing internal code path and not being exposed to the user space. Safety of eBPF can come from the verifier.rst. In such use cases as described, it may be used as safe instruction set.”h]”hXêeBPF can be used as a generic assembler for last step performance optimizations, socket filters and seccomp are using it as assembler. Tracing filters may use it as assembler to generate code from kernel. In kernel usage may not be bounded by security considerations, since generated eBPF code may be optimizing internal code path and not being exposed to the user space. Safety of eBPF can come from the verifier.rst. In such use cases as described, it may be used as safe instruction set.”…”�”}”(hj¾h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Káhh·h²hubhÌ)�”}”(hX©Just like the original BPF, eBPF runs within a controlled environment, is deterministic and the kernel can easily prove that. The safety of the program can be determined in two steps: first step does depth-first-search to disallow loops and other CFG validation; second step starts from the first insn and descends all possible paths. It simulates execution of every insn and observes the state change of registers and stack.”h]”hX©Just like the original BPF, eBPF runs within a controlled environment, is deterministic and the kernel can easily prove that. The safety of the program can be determined in two steps: first step does depth-first-search to disallow loops and other CFG validation; second step starts from the first insn and descends all possible paths. It simulates execution of every insn and observes the state change of registers and stack.”…”�”}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kéhh·h²hubh¶)�”}”(hhh]”(h»)�”}”(hŒopcode encoding”h]”hŒopcode encoding”…”�”}”(hjÝh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÚh²hh³hÊh´KñubhÌ)�”}”(hŒgeBPF is reusing most of the opcode encoding from classic to simplify conversion of classic BPF to eBPF.”h]”hŒgeBPF is reusing most of the opcode encoding from classic to simplify conversion of classic BPF to eBPF.”…”�”}”(hjëh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KóhjÚh²hubhÌ)�”}”(hŒYFor arithmetic and jump instructions the 8-bit 'code' field is divided into three parts::”h]”hŒ\For arithmetic and jump instructions the 8-bit ‘code’ field is divided into three parts:”…”�”}”(hjùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KöhjÚh²hubj )�”}”(hŒô+----------------+--------+--------------------+ | 4 bits | 1 bit | 3 bits | | operation code | source | instruction class | +----------------+--------+--------------------+ (MSB) (LSB)”h]”hŒô+----------------+--------+--------------------+ | 4 bits | 1 bit | 3 bits | | operation code | source | instruction class | +----------------+--------+--------------------+ (MSB) (LSB)”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´KùhjÚh²hubhÌ)�”}”(hŒ7Three LSB bits store instruction class which is one of:”h]”hŒ7Three LSB bits store instruction class which is one of:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÿhjÚh²hubhŒ block_quote”“”)�”}”(hXÕ=================== =============== Classic BPF classes eBPF classes =================== =============== BPF_LD 0x00 BPF_LD 0x00 BPF_LDX 0x01 BPF_LDX 0x01 BPF_ST 0x02 BPF_ST 0x02 BPF_STX 0x03 BPF_STX 0x03 BPF_ALU 0x04 BPF_ALU 0x04 BPF_JMP 0x05 BPF_JMP 0x05 BPF_RET 0x06 BPF_JMP32 0x06 BPF_MISC 0x07 BPF_ALU64 0x07 =================== =============== ”h]”hŒtable”“”)�”}”(hhh]”hŒtgroup”“”)�”}”(hhh]”(hŒcolspec”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1j3hj0ubj4)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1j3hj0ubhŒthead”“”)�”}”(hhh]”hŒrow”“”)�”}”(hhh]”(hŒentry”“”)�”}”(hhh]”hÌ)�”}”(hŒClassic BPF classes”h]”hŒClassic BPF classes”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjUubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjPubjT)�”}”(hhh]”hÌ)�”}”(hŒ eBPF classes”h]”hŒ eBPF classes”…”�”}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjlubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjPubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhjKubah}”(h]”h ]”h"]”h$]”h&]”uh1jIhj0ubhŒtbody”“”)�”}”(hhh]”(jO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_LD 0x00”h]”hŒBPF_LD 0x00”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj—ubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj”ubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_LD 0x00”h]”hŒBPF_LD 0x00”…”�”}”(hj±h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj®ubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj”ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_LDX 0x01”h]”hŒBPF_LDX 0x01”…”�”}”(hjÑh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÎubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjËubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_LDX 0x01”h]”hŒBPF_LDX 0x01”…”�”}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjåubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjËubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_ST 0x02”h]”hŒBPF_ST 0x02”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_ST 0x02”h]”hŒBPF_ST 0x02”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_STX 0x03”h]”hŒBPF_STX 0x03”…”�”}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj<ubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj9ubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_STX 0x03”h]”hŒBPF_STX 0x03”…”�”}”(hjVh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjSubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj9ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_ALU 0x04”h]”hŒBPF_ALU 0x04”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhjsubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjpubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_ALU 0x04”h]”hŒBPF_ALU 0x04”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjŠubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjpubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_JMP 0x05”h]”hŒBPF_JMP 0x05”…”�”}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hjªubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj§ubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_JMP 0x05”h]”hŒBPF_JMP 0x05”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hjÁubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj§ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_RET 0x06”h]”hŒBPF_RET 0x06”…”�”}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hjáubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjÞubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_JMP32 0x06”h]”hŒBPF_JMP32 0x06”…”�”}”(hjûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hjøubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjÞubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubjO)�”}”(hhh]”(jT)�”}”(hhh]”hÌ)�”}”(hŒBPF_MISC 0x07”h]”hŒBPF_MISC 0x07”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjubjT)�”}”(hhh]”hÌ)�”}”(hŒBPF_ALU64 0x07”h]”hŒBPF_ALU64 0x07”…”�”}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M hj/ubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jNhj‘ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j�hj0ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1j.hj+ubah}”(h]”h ]”h"]”h$]”h&]”uh1j)hj%ubah}”(h]”h ]”h"]”h$]”h&]”uh1j#h³hÊh´MhjÚh²hubhÌ)�”}”(hŒ*The 4th bit encodes the source operand ...”h]”hŒ*The 4th bit encodes the source operand ...”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÚh²hubj$)�”}”(hX† :: BPF_K 0x00 BPF_X 0x08 * in classic BPF, this means:: BPF_SRC(code) == BPF_X - use register X as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand * in eBPF, this means:: BPF_SRC(code) == BPF_X - use 'src_reg' register as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand ”h]”(j$)�”}”(hŒ*:: BPF_K 0x00 BPF_X 0x08 ”h]”j )�”}”(hŒBPF_K 0x00 BPF_X 0x08”h]”hŒBPF_K 0x00 BPF_X 0x08”…”�”}”hj{sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´Mhjwubah}”(h]”h ]”h"]”h$]”h&]”uh1j#h³hÊh´Mhjsubhê)�”}”(hhh]”(hï)�”}”(hŒ¢in classic BPF, this means:: BPF_SRC(code) == BPF_X - use register X as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand ”h]”(hÌ)�”}”(hŒin classic BPF, this means::”h]”hŒin classic BPF, this means:”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj’ubj )�”}”(hŒyBPF_SRC(code) == BPF_X - use register X as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand”h]”hŒyBPF_SRC(code) == BPF_X - use register X as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand”…”�”}”hj¤sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´Mhj’ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhj�ubhï)�”}”(hŒ£in eBPF, this means:: BPF_SRC(code) == BPF_X - use 'src_reg' register as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand ”h]”(hÌ)�”}”(hŒin eBPF, this means::”h]”hŒin eBPF, this means:”…”�”}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Mhj¸ubj )�”}”(hŒ�BPF_SRC(code) == BPF_X - use 'src_reg' register as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand”h]”hŒ�BPF_SRC(code) == BPF_X - use 'src_reg' register as source operand BPF_SRC(code) == BPF_K - use 32-bit immediate as source operand”…”�”}”hjÊsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´Mhj¸ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîhj�ubeh}”(h]”h ]”h"]”h$]”h&]”jVŒ*”uh1héh³hÊh´Mhjsubeh}”(h]”h ]”h"]”h$]”h&]”uh1j#h³hÊh´MhjÚh²hubhÌ)�”}”(hŒ+... and four MSB bits store operation code.”h]”hŒ+... and four MSB bits store operation code.”…”�”}”(hjëh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MhjÚh²hubhÌ)�”}”(hŒPIf BPF_CLASS(code) == BPF_ALU or BPF_ALU64 [ in eBPF ], BPF_OP(code) is one of::”h]”hŒOIf BPF_CLASS(code) == BPF_ALU or BPF_ALU64 [ in eBPF ], BPF_OP(code) is one of:”…”�”}”(hjùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M!hjÚh²hubj )�”}”(hXGBPF_ADD 0x00 BPF_SUB 0x10 BPF_MUL 0x20 BPF_DIV 0x30 BPF_OR 0x40 BPF_AND 0x50 BPF_LSH 0x60 BPF_RSH 0x70 BPF_NEG 0x80 BPF_MOD 0x90 BPF_XOR 0xa0 BPF_MOV 0xb0 /* eBPF only: mov reg to reg */ BPF_ARSH 0xc0 /* eBPF only: sign extending shift right */ BPF_END 0xd0 /* eBPF only: endianness conversion */”h]”hXGBPF_ADD 0x00 BPF_SUB 0x10 BPF_MUL 0x20 BPF_DIV 0x30 BPF_OR 0x40 BPF_AND 0x50 BPF_LSH 0x60 BPF_RSH 0x70 BPF_NEG 0x80 BPF_MOD 0x90 BPF_XOR 0xa0 BPF_MOV 0xb0 /* eBPF only: mov reg to reg */ BPF_ARSH 0xc0 /* eBPF only: sign extending shift right */ BPF_END 0xd0 /* eBPF only: endianness conversion */”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´M#hjÚh²hubhÌ)�”}”(hŒPIf BPF_CLASS(code) == BPF_JMP or BPF_JMP32 [ in eBPF ], BPF_OP(code) is one of::”h]”hŒOIf BPF_CLASS(code) == BPF_JMP or BPF_JMP32 [ in eBPF ], BPF_OP(code) is one of:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M2hjÚh²hubj )�”}”(hXBPF_JA 0x00 /* BPF_JMP only */ BPF_JEQ 0x10 BPF_JGT 0x20 BPF_JGE 0x30 BPF_JSET 0x40 BPF_JNE 0x50 /* eBPF only: jump != */ BPF_JSGT 0x60 /* eBPF only: signed '>' */ BPF_JSGE 0x70 /* eBPF only: signed '>=' */ BPF_CALL 0x80 /* eBPF BPF_JMP only: function call */ BPF_EXIT 0x90 /* eBPF BPF_JMP only: function return */ BPF_JLT 0xa0 /* eBPF only: unsigned '<' */ BPF_JLE 0xb0 /* eBPF only: unsigned '<=' */ BPF_JSLT 0xc0 /* eBPF only: signed '<' */ BPF_JSLE 0xd0 /* eBPF only: signed '<=' */”h]”hXBPF_JA 0x00 /* BPF_JMP only */ BPF_JEQ 0x10 BPF_JGT 0x20 BPF_JGE 0x30 BPF_JSET 0x40 BPF_JNE 0x50 /* eBPF only: jump != */ BPF_JSGT 0x60 /* eBPF only: signed '>' */ BPF_JSGE 0x70 /* eBPF only: signed '>=' */ BPF_CALL 0x80 /* eBPF BPF_JMP only: function call */ BPF_EXIT 0x90 /* eBPF BPF_JMP only: function return */ BPF_JLT 0xa0 /* eBPF only: unsigned '<' */ BPF_JLE 0xb0 /* eBPF only: unsigned '<=' */ BPF_JSLT 0xc0 /* eBPF only: signed '<' */ BPF_JSLE 0xd0 /* eBPF only: signed '<=' */”…”�”}”hj#sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´M4hjÚh²hubhÌ)�”}”(hXMSo BPF_ADD | BPF_X | BPF_ALU means 32-bit addition in both classic BPF and eBPF. There are only two registers in classic BPF, so it means A += X. In eBPF it means dst_reg = (u32) dst_reg + (u32) src_reg; similarly, BPF_XOR | BPF_K | BPF_ALU means A ^= imm32 in classic BPF and analogous src_reg = (u32) src_reg ^ (u32) imm32 in eBPF.”h]”hXMSo BPF_ADD | BPF_X | BPF_ALU means 32-bit addition in both classic BPF and eBPF. There are only two registers in classic BPF, so it means A += X. In eBPF it means dst_reg = (u32) dst_reg + (u32) src_reg; similarly, BPF_XOR | BPF_K | BPF_ALU means A ^= imm32 in classic BPF and analogous src_reg = (u32) src_reg ^ (u32) imm32 in eBPF.”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MChjÚh²hubhÌ)�”}”(hX}Classic BPF is using BPF_MISC class to represent A = X and X = A moves. eBPF is using BPF_MOV | BPF_X | BPF_ALU code instead. Since there are no BPF_MISC operations in eBPF, the class 7 is used as BPF_ALU64 to mean exactly the same operations as BPF_ALU, but with 64-bit wide operands instead. So BPF_ADD | BPF_X | BPF_ALU64 means 64-bit addition, i.e.: dst_reg = dst_reg + src_reg”h]”hX}Classic BPF is using BPF_MISC class to represent A = X and X = A moves. eBPF is using BPF_MOV | BPF_X | BPF_ALU code instead. Since there are no BPF_MISC operations in eBPF, the class 7 is used as BPF_ALU64 to mean exactly the same operations as BPF_ALU, but with 64-bit wide operands instead. So BPF_ADD | BPF_X | BPF_ALU64 means 64-bit addition, i.e.: dst_reg = dst_reg + src_reg”…”�”}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MIhjÚh²hubhÌ)�”}”(hXéClassic BPF wastes the whole BPF_RET class to represent a single ``ret`` operation. Classic BPF_RET | BPF_K means copy imm32 into return register and perform function exit. eBPF is modeled to match CPU, so BPF_JMP | BPF_EXIT in eBPF means function exit only. The eBPF program needs to store return value into register R0 before doing a BPF_EXIT. Class 6 in eBPF is used as BPF_JMP32 to mean exactly the same operations as BPF_JMP, but with 32-bit wide operands for the comparisons instead.”h]”(hŒAClassic BPF wastes the whole BPF_RET class to represent a single ”…”�”}”(hjMh²hh³Nh´Nubj�)�”}”(hŒ``ret``”h]”hŒret”…”�”}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jœhjMubhX¡ operation. Classic BPF_RET | BPF_K means copy imm32 into return register and perform function exit. eBPF is modeled to match CPU, so BPF_JMP | BPF_EXIT in eBPF means function exit only. The eBPF program needs to store return value into register R0 before doing a BPF_EXIT. Class 6 in eBPF is used as BPF_JMP32 to mean exactly the same operations as BPF_JMP, but with 32-bit wide operands for the comparisons instead.”…”�”}”(hjMh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MPhjÚh²hubhÌ)�”}”(hŒFFor load and store instructions the 8-bit 'code' field is divided as::”h]”hŒIFor load and store instructions the 8-bit ‘code’ field is divided as:”…”�”}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MXhjÚh²hubj )�”}”(hŒÇ+--------+--------+-------------------+ | 3 bits | 2 bits | 3 bits | | mode | size | instruction class | +--------+--------+-------------------+ (MSB) (LSB)”h]”hŒÇ+--------+--------+-------------------+ | 3 bits | 2 bits | 3 bits | | mode | size | instruction class | +--------+--------+-------------------+ (MSB) (LSB)”…”�”}”hj{sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´MZhjÚh²hubhÌ)�”}”(hŒSize modifier is one of ...”h]”hŒSize modifier is one of ...”…”�”}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´M`hjÚh²hubj )�”}”(hŒ‚BPF_W 0x00 /* word */ BPF_H 0x08 /* half word */ BPF_B 0x10 /* byte */ BPF_DW 0x18 /* eBPF only, double word */”h]”hŒ‚BPF_W 0x00 /* word */ BPF_H 0x08 /* half word */ BPF_B 0x10 /* byte */ BPF_DW 0x18 /* eBPF only, double word */”…”�”}”hj—sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´MdhjÚh²hubhÌ)�”}”(hŒ0... which encodes size of load/store operation::”h]”hŒ/... which encodes size of load/store operation:”…”�”}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MihjÚh²hubj )�”}”(hŒ;B - 1 byte H - 2 byte W - 4 byte DW - 8 byte (eBPF only)”h]”hŒ;B - 1 byte H - 2 byte W - 4 byte DW - 8 byte (eBPF only)”…”�”}”hj³sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´MkhjÚh²hubhÌ)�”}”(hŒMode modifier is one of::”h]”hŒMode modifier is one of:”…”�”}”(hjÁh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´MphjÚh²hubj )�”}”(hX+BPF_IMM 0x00 /* used for 32-bit mov in classic BPF and 64-bit in eBPF */ BPF_ABS 0x20 BPF_IND 0x40 BPF_MEM 0x60 BPF_LEN 0x80 /* classic BPF only, reserved in eBPF */ BPF_MSH 0xa0 /* classic BPF only, reserved in eBPF */ BPF_ATOMIC 0xc0 /* eBPF only, atomic operations */”h]”hX+BPF_IMM 0x00 /* used for 32-bit mov in classic BPF and 64-bit in eBPF */ BPF_ABS 0x20 BPF_IND 0x40 BPF_MEM 0x60 BPF_LEN 0x80 /* classic BPF only, reserved in eBPF */ BPF_MSH 0xa0 /* classic BPF only, reserved in eBPF */ BPF_ATOMIC 0xc0 /* eBPF only, atomic operations */”…”�”}”hjÏsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1j h³hÊh´MrhjÚh²hubeh}”(h]”Œopcode-encoding”ah ]”h"]”Œopcode encoding”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kñubeh}”(h]”Œclassic-bpf-vs-ebpf”ah ]”h"]”Œclassic bpf vs ebpf”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”jSŒfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jêjçjâjßuŒ nametypes”}”(jê‰jâ‰uh}”(jçh·jßjÚuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.