RFC 9669
BPF Instruction Set Architecture (ISA)
BPF Instruction Set Architecture (ISA) ๐ฆ
- RFC number: 9669, published by the Internet Engineering Task Force (IETF) ๐ธ
- Authors: D. Thaler, Ed. ๐
- Category: Standards Track ๐
- Date: October 2024 ๐
- ISSN: 2070-1721
- Obsoletes / Updates: the header doesn't list anything this one obsoletes or updates โจ
Abstract ๐
okay so eBPF doesn't stand for anything anymore ๐ , but people still call it BPF all the time. It started out in the Linux kernel and can run untrusted programs inside a privileged context, like the operating system kernel ๐ญ. This document is the spec for the BPF instruction set architecture (ISA) ๐ง.
Status of This Memo ๐
This is an Internet Standards Track document โจ.
It's a product of the Internet Engineering Task Force (IETF) and reflects the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG) ๐ซถ. If you want more on Internet Standards, check out Section 2 of RFC 7841 ๐.
For the current status, any errata, and how to send feedback, head to https://www.rfc-editor.org/info/rfc9669 ๐.
Copyright Notice ๐
Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved ยฉ๏ธ.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read these, bestie, because they spell out your rights and restrictions for this doc ๐. Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as the Revised BSD License describes ๐ฅ.
Table of Contents ๐๏ธ
1. Introduction
2. Documentation Conventions
2.1. Types
2.2. Functions
2.3. Definitions
2.4. Conformance Groups
3. Instruction Encoding
3.1. Basic Instruction Encoding
3.2. Wide Instruction Encoding
3.3. Instruction Classes
4. Arithmetic and Jump Instructions
4.1. Arithmetic Instructions
4.2. Byte Swap Instructions
4.3. Jump Instructions
4.3.1. Helper Functions
4.3.2. Program-Local Functions
5. Load and Store Instructions
5.1. Regular Load and Store Operations
5.2. Sign-Extension Load Operations
5.3. Atomic Operations
5.4. 64-bit Immediate Instructions
5.4.1. Maps
5.4.2. Platform Variables
5.5. Legacy BPF Packet Access Instructions
6. Security Considerations
7. IANA Considerations
7.1. BPF Instruction Conformance Groups Registry
7.1.1. BPF Instruction Conformance Groups Registration
Template
7.2. BPF Instruction Set Registry
7.2.1. BPF Instruction Registration Template
7.3. Adding Instructions
7.4. Deprecating Instructions
7.5. Change Control
7.6. Expert Review Instructions
8. References
8.1. Normative References
8.2. Informative References
Appendix A. Initial BPF Instruction Set Values
Acknowledgements
Author's Address
1. Introduction โจ
eBPF, also called BPF, started in the Linux kernel and can run untrusted programs in a privileged context like an operating system kernel. This document specifies the BPF instruction set architecture (ISA) ๐ฆ.
Quick history moment ๐ฐ๏ธ: BPF originally stood for Berkeley Packet Filter. But it can do so much more than packet filtering now, so the acronym doesn't make sense anymore. BPF is just its own standalone name now ๐ . People sometimes call the original BPF cBPF (classic BPF) to tell it apart from the widely deployed eBPF (extended BPF) ๐ธ.
2. Documentation Conventions ๐งธ
So about those BCP 14 key words ๐. When "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" show up in this document, they mean what BCP 14 [RFC2119] [RFC8174] says they mean. But that's only when they're written in all capitals, exactly like that ๐.
The document also uses a shorthand for families of types and some mnemonic functions to explain how instructions behave. The valid values for those types and what those functions do are defined in the subsections below ๐ง.
2.1. Types
Here the notation SN means an integer type, where S is its signedness and N is its bit width โจ.
+===+==========+
| S | Meaning |
+===+==========+
| u | unsigned |
+---+----------+
| s | signed |
+---+----------+
Table 1: Meaning of
Signedness Notation
+=====+===========+
| N | Bit Width |
+=====+===========+
| 8 | 8 bits |
+-----+-----------+
| 16 | 16 bits |
+-----+-----------+
| 32 | 32 bits |
+-----+-----------+
| 64 | 64 bits |
+-----+-----------+
| 128 | 128 bits |
+-----+-----------+
Table 2: Meaning of
Bit-Width Notation
For example, u32 is a type whose valid values are all the 32-bit unsigned numbers, and s16 is a type whose valid values are all the 16-bit signed numbers ๐.
2.2. Functions
These byte swap functions don't care which direction you're going ๐. The same function handles conversion either way, so it's not a choice you have to make ๐ .
be16: takes an unsigned 16-bit number and converts it between host byte order and big-endian byte order [IEN137] ๐ธ.be32: takes an unsigned 32-bit number and converts it between host byte order and big-endian byte order ๐ธ.be64: takes an unsigned 64-bit number and converts it between host byte order and big-endian byte order ๐ธ.bswap16: takes an unsigned 16-bit number in either big- or little-endian format and returns the equivalent number with the same bit width but opposite endianness ๐.bswap32: takes an unsigned 32-bit number in either big- or little-endian format and returns the equivalent number with the same bit width but opposite endianness ๐.bswap64: takes an unsigned 64-bit number in either big- or little-endian format and returns the equivalent number with the same bit width but opposite endianness ๐.le16: takes an unsigned 16-bit number and converts it between host byte order and little-endian byte order ๐.le32: takes an unsigned 32-bit number and converts it between host byte order and little-endian byte order ๐.le64: takes an unsigned 64-bit number and converts it between host byte order and little-endian byte order ๐.
2.3. Definitions
Sign Extend: to sign extend an X-bit number, A, into a Y-bit number, B, you do two things ๐ช.
- Copy all X bits from A into the lower X bits of B.
- Set the remaining Y - X bits of B to whatever the most significant bit of A is.
Example time ๐: say you sign extend an 8-bit number A into a 16-bit number B on a big-endian platform. Here's how it looks:
A: 10000110
B: 11111111 10000110
2.4. Conformance Groups
Okay, not every implementation has to support every instruction in this document, like deprecated ones ๐. Instead, the spec defines a bunch of conformance groups. An implementation MUST support the base32 conformance group, and it MAY support extra conformance groups. Supporting a group means you MUST support every instruction in that group ๐.
Named groups make it possible for a runtime and tools like compilers (the things that generate instructions for the runtime) to work together ๐ค. So capability discovery through conformance groups might happen manually by users or automatically by tools ๐ง.
Each group has a short ASCII label, like "base32", that points to a set of mandatory instructions. Every instruction belongs to one or more conformance groups ๐.
This document defines these conformance groups:
base32: includes all instructions defined in this specification unless otherwise noted ๐.base64: includes base32, plus instructions explicitly noted as being in the base64 conformance group ๐ฆ.atomic32: includes 32-bit atomic operation instructions (see Section 5.3) โ๏ธ.atomic64: includes atomic32, plus 64-bit atomic operation instructions โ๏ธ.divmul32: includes 32-bit division, multiplication, and modulo instructions โ.divmul64: includes divmul32, plus 64-bit division, multiplication, and modulo instructions โ.packet: deprecated packet access instructions ๐.
3. Instruction Encoding ๐
BPF has two instruction encodings, and they're giving two very different vibes ๐ :
- the basic instruction encoding, which uses 64 bits to encode an instruction ๐ฌ
- the wide instruction encoding, which tacks a second 64 bits onto the basic instruction for a total of 128 bits ๐
3.1. Basic Instruction Encoding โจ
okay so every basic instruction is packed into the same little shape ๐ It's 8 bytes total: an opcode, a regs byte, a 16-bit offset, and a 32-bit imm. Here's the layout:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| opcode | regs | offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| imm |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The opcode is the operation to perform. It's one byte, split into two pieces ๐ง
+-+-+-+-+-+-+-+-+
|specific |class|
+-+-+-+-+-+-+-+-+
- specific: the bits here change shape depending on the instruction class ๐ธ
- class: the instruction class, see Section 3.3 so you can look up what each one means ๐
The regs byte holds the source and destination register numbers. The order flips depending on the host's byte order, which is very much a vibe check for your machine ๐
On a little-endian host, it looks like this:
+-+-+-+-+-+-+-+-+
|src_reg|dst_reg|
+-+-+-+-+-+-+-+-+
On a big-endian host, it looks like this:
+-+-+-+-+-+-+-+-+
|dst_reg|src_reg|
+-+-+-+-+-+-+-+-+
- src_reg: the source register number (0-10). The exception is 64-bit immediate instructions (see Section 5.4), which reuse this field for other purposes ๐ฆ
- dst_reg: the destination register number (0-10), unless said otherwise. Future instructions might reuse this field for other purposes too, so keep your eyes open ๐
- offset: a signed integer offset used with pointer arithmetic. Some arithmetic instructions reuse this field for something else, so check the fine print ๐
- imm: a signed integer immediate value ๐
The multi-byte fields ('offset' and 'imm') are stored in big-endian byte order on big-endian hosts, and in little-endian byte order on little-endian hosts. So the bytes just follow whatever your machine is doing, no drama ๐ซถ
Here's an example so you can see the two orderings side by side ๐
opcode offset imm assembly
src_reg dst_reg
07 0 1 00 00 44 33 22 11 r1 += 0x11223344 // little
dst_reg src_reg
07 1 0 00 00 11 22 33 44 r1 += 0x11223344 // big
Most instructions don't use every field, which is honestly relatable ๐ญ Unused fields SHALL be cleared to zero. Zero them out, bestie, no exceptions โจ
3.2. Wide Instruction Encoding ๐
Some instructions use the wide instruction encoding, which gives you two 32-bit immediate values instead of one. This is giving more space and I'm here for it ๐
The 64 bits right after the basic instruction format hold a pseudo instruction. In that pseudo instruction, 'opcode', 'dst_reg', 'src_reg', and 'offset' are all set to zero. Zero, zero, zero, zero. Very minimalist ๐
Here's the picture:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| opcode | regs | offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| imm |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| next_imm |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- opcode: the operation to perform, encoded as explained above
- regs: the source and destination register numbers (unless said otherwise), encoded as explained above
- offset: a signed integer offset used with pointer arithmetic, unless said otherwise
- imm: a signed integer immediate value
- reserved: unused, set to zero ๐ง
- next_imm: the second signed integer immediate value ๐
3.3. Instruction Classes ๐
The three least significant bits of the 'opcode' field store the instruction class. That's the whole secret, and it's lowkey genius ๐ง
+=======+=======+=================================+===========+
| class | Value | Description | Reference |
+=======+=======+=================================+===========+
| LD | 0x0 | non-standard load operations | Section 5 |
+-------+-------+---------------------------------+-----------+
| LDX | 0x1 | load into register operations | Section 5 |
+-------+-------+---------------------------------+-----------+
| ST | 0x2 | store from immediate operations | Section 5 |
+-------+-------+---------------------------------+-----------+
| STX | 0x3 | store from register operations | Section 5 |
+-------+-------+---------------------------------+-----------+
| ALU | 0x4 | 32-bit arithmetic operations | Section 4 |
+-------+-------+---------------------------------+-----------+
| JMP | 0x5 | 64-bit jump operations | Section 4 |
+-------+-------+---------------------------------+-----------+
| JMP32 | 0x6 | 32-bit jump operations | Section 4 |
+-------+-------+---------------------------------+-----------+
| ALU64 | 0x7 | 64-bit arithmetic operations | Section 4 |
+-------+-------+---------------------------------+-----------+
Table 3: Instruction Class
4. Arithmetic and Jump Instructions โจ
For arithmetic and jump instructions (ALU, ALU64, JMP, and JMP32), the 8-bit 'opcode' field splits into three parts ๐ฅ
+-+-+-+-+-+-+-+-+
| code |s|class|
+-+-+-+-+-+-+-+-+
- code: the operation code. What it means depends on the instruction class ๐ธ
- s (source): the source operand location. Unless said otherwise, it's one of these two options ๐ฆ
+========+=======+==========================================+
| source | Value | Description |
+========+=======+==========================================+
| K | 0 | use 32-bit 'imm' value as source operand |
+--------+-------+------------------------------------------+
| X | 1 | use 'src_reg' register value as source |
| | | operand |
+--------+-------+------------------------------------------+
Table 4: Source Operand Location
- class: the instruction class (see Section 3.3) ๐
4.1. Arithmetic Instructions
okay so ALU uses 32-bit wide operands while ALU64 uses 64-bit wide operands for otherwise identical operations ๐ ALU64 instructions belong to the base64 conformance group unless noted otherwise ๐. The code field encodes the operation as shown below, where src refers to the source operand and dst refers to the value of the destination register โจ
+=======+======+=========+=======================================+
| Name | code | offset | Description |
+=======+======+=========+=======================================+
| ADD | 0x0 | 0 | dst += src |
+-------+------+---------+---------------------------------------+
| SUB | 0x1 | 0 | dst -= src |
+-------+------+---------+---------------------------------------+
| MUL | 0x2 | 0 | dst *= src |
+-------+------+---------+---------------------------------------+
| DIV | 0x3 | 0 | dst = (src != 0) ? (dst / src) : 0 |
+-------+------+---------+---------------------------------------+
| SDIV | 0x3 | 1 | dst = (src != 0) ? (dst s/ src) : 0 |
+-------+------+---------+---------------------------------------+
| OR | 0x4 | 0 | dst |= src |
+-------+------+---------+---------------------------------------+
| AND | 0x5 | 0 | dst &= src |
+-------+------+---------+---------------------------------------+
| LSH | 0x6 | 0 | dst <<= (src & mask) |
+-------+------+---------+---------------------------------------+
| RSH | 0x7 | 0 | dst >>= (src & mask) |
+-------+------+---------+---------------------------------------+
| NEG | 0x8 | 0 | dst = -dst |
+-------+------+---------+---------------------------------------+
| MOD | 0x9 | 0 | dst = (src != 0) ? (dst % src) : dst |
+-------+------+---------+---------------------------------------+
| SMOD | 0x9 | 1 | dst = (src != 0) ? (dst s% src) : dst |
+-------+------+---------+---------------------------------------+
| XOR | 0xa | 0 | dst ^= src |
+-------+------+---------+---------------------------------------+
| MOV | 0xb | 0 | dst = src |
+-------+------+---------+---------------------------------------+
| MOVSX | 0xb | 8/16/32 | dst = (s8,s16,s32)src |
+-------+------+---------+---------------------------------------+
| ARSH | 0xc | 0 | sign extending (Section 2.3) dst >>= |
| | | | (src & mask) |
+-------+------+---------+---------------------------------------+
| END | 0xd | 0 | byte swap operations (see |
| | | | Section 4.2) |
+-------+------+---------+---------------------------------------+
Table 5: Arithmetic Instructions
Underflow and overflow are allowed during arithmetic operations, so the 64-bit or 32-bit value just wraps around ๐. If BPF program execution would result in division by zero, the destination register is instead set to zero ๐ซถ. If execution would result in modulo by zero, then for ALU64 the value of the destination register is unchanged, whereas for ALU the upper 32 bits of the destination register are zeroed ๐ .
{ADD, X, ALU}, where code = ADD, source = X, and class = ALU, means:
dst = (u32) ((u32) dst + (u32) src)
where (u32) indicates that the upper 32 bits are zeroed โจ.
{ADD, X, ALU64} means:
dst = dst + src
{XOR, K, ALU} means:
dst = (u32) dst ^ (u32) imm
{XOR, K, ALU64} means:
dst = dst ^ imm
Note that most arithmetic instructions have offset set to 0. Only three instructions (SDIV, SMOD, MOVSX) have a non-zero offset ๐.
Division, multiplication, and modulo operations for ALU are part of the "divmul32" conformance group, and division, multiplication, and modulo operations for ALU64 are part of the "divmul64" conformance group ๐ง. The division and modulo operations support both unsigned and signed flavors ๐.
For unsigned operations (DIV and MOD), for ALU, imm is interpreted as a 32-bit unsigned value. For ALU64, imm is first sign extended (Section 2.3) from 32 to 64 bits, and then interpreted as a 64-bit unsigned value ๐.
For signed operations (SDIV and SMOD), for ALU, imm is interpreted as a 32-bit signed value. For ALU64, imm is first sign extended (Section 2.3) from 32 to 64 bits, and then interpreted as a 64-bit signed value ๐ฆ.
Note that there are varying definitions of the signed modulo operation when the dividend or divisor are negative. Implementations often vary by language, so Python, Ruby, etc. differ from C, Go, Java, etc. ๐ This specification requires that signed modulo MUST use truncated division (where -13 % 3 == -1) as implemented in C, Go, etc.:
a % n = a - n * trunc(a / n)
The MOVSX instruction does a move operation with sign extension ๐. {MOVSX, X, ALU} sign extends (Section 2.3) 8-bit and 16-bit operands into 32-bit operands, and zeroes the remaining upper 32 bits. {MOVSX, X, ALU64} sign extends (Section 2.3) 8-bit, 16-bit, and 32-bit operands into 64-bit operands. Unlike other arithmetic instructions, MOVSX is only defined for register source operands (X) ๐ธ.
{MOV, K, ALU64} means:
dst = (s64)imm
{MOV, X, ALU} means:
dst = (u32)src
{MOVSX, X, ALU} with offset 8 means:
dst = (u32)(s32)(s8)src
The NEG instruction is only defined when the source bit is clear (K) ๐ฅฒ.
Shift operations use a mask of 0x3F (63) for 64-bit operations and 0x1F (31) for 32-bit operations โญ.
4.2. Byte Swap Instructions
The byte swap instructions use instruction classes of ALU and ALU64 and a 4-bit code field of END ๐ฅ.
The byte swap instructions operate on the destination register only, and they do not use a separate source register or immediate value ๐ .
For ALU, the 1-bit source operand field in the opcode is used to select what byte order the operation converts from or to. For ALU64, the 1-bit source operand field in the opcode is reserved and MUST be set to 0 ๐ซถ.
+=======+==========+=======+===========================+
| class | source | Value | Description |
+=======+==========+=======+===========================+
| ALU | LE | 0 | convert between host byte |
| | | | order and little endian |
+-------+----------+-------+---------------------------+
| ALU | BE | 1 | convert between host byte |
| | | | order and big endian |
+-------+----------+-------+---------------------------+
| ALU64 | Reserved | 0 | do byte swap |
| | | | unconditionally |
+-------+----------+-------+---------------------------+
Table 6: Byte Swap Instructions
The imm field encodes the width of the swap operations. The following widths are supported: 16, 32, and 64. Width 64 operations belong to the base64 conformance group, and other swap operations belong to the base32 conformance group ๐.
Examples:
{END, LE, ALU} with imm = 16/32/64 means:
dst = le16(dst)
dst = le32(dst)
dst = le64(dst)
{END, BE, ALU} with imm = 16/32/64 means:
dst = be16(dst)
dst = be32(dst)
dst = be64(dst)
{END, TO, ALU64} with imm = 16/32/64 means:
dst = bswap16(dst)
dst = bswap32(dst)
dst = bswap64(dst)
4.3. Jump Instructions ๐ฆ
okay bestie, so JMP32 uses 32-bit wide operands and sits in the base32 conformance group ๐
. JMP does the exact same stuff but with 64-bit operands, and it's in base64 unless otherwise specified โจ. The code field tells you which operation you're getting, and here's the whole menu:
+======+=======+=========+======================+================+
| code | Value | src_reg | Description | Notes |
+======+=======+=========+======================+================+
| JA | 0x0 | 0x0 | PC += offset | {JA, K, JMP} |
| | | | | only |
+------+-------+---------+----------------------+----------------+
| JA | 0x0 | 0x0 | PC += imm | {JA, K, JMP32} |
| | | | | only |
+------+-------+---------+----------------------+----------------+
| JEQ | 0x1 | any | PC += offset if dst | |
| | | | == src | |
+------+-------+---------+----------------------+----------------+
| JGT | 0x2 | any | PC += offset if dst | unsigned |
| | | | > src | |
+------+-------+---------+----------------------+----------------+
| JGE | 0x3 | any | PC += offset if dst | unsigned |
| | | | >= src | |
+------+-------+---------+----------------------+----------------+
| JSET | 0x4 | any | PC += offset if dst | |
| | | | & src | |
+------+-------+---------+----------------------+----------------+
| JNE | 0x5 | any | PC += offset if dst | |
| | | | != src | |
+------+-------+---------+----------------------+----------------+
| JSGT | 0x6 | any | PC += offset if dst | signed |
| | | | > src | |
+------+-------+---------+----------------------+----------------+
| JSGE | 0x7 | any | PC += offset if dst | signed |
| | | | >= src | |
+------+-------+---------+----------------------+----------------+
| CALL | 0x8 | 0x0 | call helper function | {CALL, K, JMP} |
| | | | by static ID | only, see |
| | | | | Section 4.3.1 |
+------+-------+---------+----------------------+----------------+
| CALL | 0x8 | 0x1 | call PC += imm | {CALL, K, JMP} |
| | | | | only, see |
| | | | | Section 4.3.2 |
+------+-------+---------+----------------------+----------------+
| CALL | 0x8 | 0x2 | call helper function | {CALL, K, JMP} |
| | | | by BTF ID | only, see |
| | | | | Section 4.3.1 |
+------+-------+---------+----------------------+----------------+
| EXIT | 0x9 | 0x0 | return | {CALL, K, JMP} |
| | | | | only |
+------+-------+---------+----------------------+----------------+
| JLT | 0xa | any | PC += offset if dst | unsigned |
| | | | < src | |
+------+-------+---------+----------------------+----------------+
| JLE | 0xb | any | PC += offset if dst | unsigned |
| | | | <= src | |
+------+-------+---------+----------------------+----------------+
| JSLT | 0xc | any | PC += offset if dst | signed |
| | | | < src | |
+------+-------+---------+----------------------+----------------+
| JSLE | 0xd | any | PC += offset if dst | signed |
| | | | <= src | |
+------+-------+---------+----------------------+----------------+
Table 7: Jump Instructions
Here PC is the program counter, and the offset to jump by is measured in units of 64-bit instructions, counting from the instruction right after the jump ๐ง. So PC += 1 skips the next instruction if it's a basic instruction, but if the next one is a 128-bit wide instruction, you get undefined behavior ๐. Yikes!
Examples time, iykyk ๐ธ:
{JSGE, X, JMP32} means:
if (s32)dst s>= (s32)src goto +offset
Here s>= means a signed >= comparison โจ.
{JLE, K, JMP} means:
if dst <= (u64)(s64)imm goto +offset
{JA, K, JMP32} means:
gotol +imm
where imm means the branch offset comes from the imm field ๐.
Note that there are two flavors of JA ๐. The JMP class permits a 16-bit jump offset specified by the offset field, whereas the JMP32 class permits a 32-bit jump offset specified by the imm field. A conditional jump greater than 16 bits may be converted to a conditional jump less than 16 bits plus a 32-bit unconditional jump, which is giving very clever optimization energy ๐.
All CALL and JA instructions belong to the base32 conformance group ๐.
4.3.1. Helper Functions
okay so helper functions are basically a way for BPF programs to call into a set of function calls that the underlying platform exposes ๐.
Historically, each helper function was identified by a static ID encoded in the imm field. Further documentation of helper functions is outside the scope of this document and standardization is left for future work, but use is widely deployed and more information can be found in platform-specific documentation (e.g., Linux kernel documentation) ๐.
Platforms that support the BPF Type Format (BTF) can identify a helper function by a BTF ID encoded in the imm field, where the BTF ID identifies the helper name and type โจ. Further documentation of BTF is outside the scope of this document and standardization is left for future work, but use is widely deployed and more information can be found in platform-specific documentation (e.g., Linux kernel documentation) ๐ซถ.
4.3.2. Program-Local Functions
Program-local functions are functions exposed by the same BPF program as the caller ๐ฆ. They're referenced by offset from the instruction following the call instruction, kinda like JA does. The offset is encoded in the imm field of the call instruction. An EXIT within the program-local function will return to the caller ๐ฅ.
5. Load and Store Instructions ๐
For load and store instructions (LD, LDX, ST, and STX), the 8-bit opcode field is split up like this ๐ง:
+-+-+-+-+-+-+-+-+
|mode |sz |class|
+-+-+-+-+-+-+-+-+
mode: The mode modifier is one of:
+========+=======+===============================+=============+
| mode | Value | Description | Reference |
+========+=======+===============================+=============+
| IMM | 0 | 64-bit immediate instructions | Section 5.4 |
+--------+-------+-------------------------------+-------------+
| ABS | 1 | legacy BPF packet access | Section 5.5 |
| | | (absolute) | |
+--------+-------+-------------------------------+-------------+
| IND | 2 | legacy BPF packet access | Section 5.5 |
| | | (indirect) | |
+--------+-------+-------------------------------+-------------+
| MEM | 3 | regular load and store | Section 5.1 |
| | | operations | |
+--------+-------+-------------------------------+-------------+
| MEMSX | 4 | sign-extension load | Section 5.2 |
| | | operations | |
+--------+-------+-------------------------------+-------------+
| ATOMIC | 6 | atomic operations | Section 5.3 |
+--------+-------+-------------------------------+-------------+
Table 8: Mode Modifier
sz (size): The size modifier is one of:
+======+=======+=======================+
| size | Value | Description |
+======+=======+=======================+
| W | 0 | word (4 bytes) |
+------+-------+-----------------------+
| H | 1 | half word (2 bytes) |
+------+-------+-----------------------+
| B | 2 | byte |
+------+-------+-----------------------+
| DW | 3 | double word (8 bytes) |
+------+-------+-----------------------+
Table 9: Size Modifier
Instructions using DW belong to the base64 conformance group ๐ธ.
class: The instruction class (see Section 3.3) ๐
5.1. Regular Load and Store Operations
The MEM mode modifier is used to encode regular load and store instructions that transfer data between a register and memory ๐. The forms are:
{MEM, <size>, STX} means:
*(size *) (dst + offset) = src
{MEM, <size>, ST} means:
*(size *) (dst + offset) = imm
{MEM, <size>, LDX} means:
dst = *(unsigned size *) (src + offset)
Where <size> is one of: B, H, W, or DW, and unsigned size is one of: u8, u16, u32, or u64 โจ.
5.2. Sign-Extension Load Operations
The MEMSX mode modifier is used to encode sign-extension load instructions (Section 2.3) that transfer data between a register and memory ๐ฆ.
{MEMSX, <size>, LDX} means:
dst = *(signed size *) (src + offset)
Where <size> is one of: B, H, or W, and signed size is one of: s8, s16, or s32 ๐ซถ.
5.3. Atomic Operations ๐ซ
okay so atomic ops are the ones that touch memory and nothing can cut in the middle ๐ซถ no other BPF program or outside thing can interrupt them or mess up that same memory region while they're going, periodt ๐
every atomic op is written as a store op using the ATOMIC mode modifier, like this:
{ATOMIC, W, STX}for 32-bit ops, which are in the "atomic32" conformance group ๐ธ{ATOMIC, DW, STX}for 64-bit ops, which are in the "atomic64" conformance group ๐- 8-bit and 16-bit atomic ops are not supported ๐ so don't even try
the imm field is where the actual atomic op gets picked. the simple ones borrow some of the values we already use for arithmetic ops in imm, and it's giving dรฉjร vu but make it atomic ๐ฆ
+=====+=======+=============+
| imm | Value | Description |
+=====+=======+=============+
| ADD | 0x00 | atomic add |
+-----+-------+-------------+
| OR | 0x40 | atomic or |
+-----+-------+-------------+
| AND | 0x50 | atomic and |
+-----+-------+-------------+
| XOR | 0xa0 | atomic xor |
+-----+-------+-------------+
Table 10: Simple Atomic
Operations
so {ATOMIC, W, STX} with imm = ADD means:
*(u32 *)(dst + offset) += src
and {ATOMIC, DW, STX} with imm = ADD means:
*(u64 *)(dst + offset) += src
now the simple ops aren't the only ones at the party ๐ there's also a modifier and two complex atomic ops:
+=========+==============+=============================+
| imm | Value | Description |
+=========+==============+=============================+
| FETCH | 0x01 | modifier: return old value |
+---------+--------------+-----------------------------+
| XCHG | 0xe0 | FETCH | atomic exchange |
+---------+--------------+-----------------------------+
| CMPXCHG | 0xf0 | FETCH | atomic compare and exchange |
+---------+--------------+-----------------------------+
Table 11: Complex Atomic Operations and a Modifier
the FETCH modifier is optional for simple atomic ops ๐ but the complex ones always have it set. when FETCH is set, the op also overwrites src with whatever was in memory before the change. that's the "old value" glow-up โจ
XCHG is the swap queen ๐ it atomically exchanges src with the value at dst + offset.
CMPXCHG is giving compare-then-decide ๐ง it atomically compares the value at dst + offset with R0. if they match, the value at dst + offset gets replaced with src. either way, the value that was at dst + offset before the op gets zero-extended and loaded back into R0. iconic behaviour, no notes ๐
5.4. 64-bit Immediate Instructions ๐
instructions with the IMM mode modifier use the wide instruction encoding from Section 3, and they use the src_reg field of the basic instruction to hold an opcode subtype. so src_reg is basically the little sub-category label ๐ท๏ธ
this table defines a set of {IMM, DW, LD} instructions with opcode subtypes in src_reg. it uses some new terms, like "map", which we explain further down ๐
+=========+================================+==========+==========+
| src_reg | Pseudocode | imm Type | dst Type |
+=========+================================+==========+==========+
| 0x0 | dst = (next_imm << 32) | imm | integer | integer |
+---------+--------------------------------+----------+----------+
| 0x1 | dst = map_by_fd(imm) | map fd | map |
+---------+--------------------------------+----------+----------+
| 0x2 | dst = map_val(map_by_fd(imm)) | map fd | data |
| | + next_imm | | address |
+---------+--------------------------------+----------+----------+
| 0x3 | dst = var_addr(imm) | variable | data |
| | | id | address |
+---------+--------------------------------+----------+----------+
| 0x4 | dst = code_addr(imm) | integer | code |
| | | | address |
+---------+--------------------------------+----------+----------+
| 0x5 | dst = map_by_idx(imm) | map | map |
| | | index | |
+---------+--------------------------------+----------+----------+
| 0x6 | dst = map_val(map_by_idx(imm)) | map | data |
| | + next_imm | index | address |
+---------+--------------------------------+----------+----------+
Table 12: 64-bit Immediate Instructions
where:
map_by_fd(imm)means turning a 32-bit file descriptor into the address of a map (see Section 5.4.1) ๐บ๏ธmap_by_idx(imm)means turning a 32-bit index into the address of a map ๐map_val(map)gets the address of the first value in a given map ๐var_addr(imm)gets the address of a platform variable (see Section 5.4.2) with a given id ๐code_addr(imm)gets the address of the instruction at a specified relative offset, counted in (64-bit) instructions ๐งญ- the
imm typecan be used by disassemblers for display ๐ - the
dst typecan be used for verification and just-in-time compilation purposes โก
5.4.1. Maps
maps are shared memory regions that BPF programs can access on some platforms โจ a map can have different semantics, which get defined in a separate document. it may or may not have one single contiguous memory region. the map_val(map) thing is only defined for maps that do have a single contiguous region, so keep that in mind bestie ๐ซถ
each map can have a file descriptor (fd) if the platform supports it. map_by_fd(imm) means "get the map with this file descriptor" ๐๏ธ each BPF program can also be set up at load time to use a set of maps tied to that program. map_by_idx(imm) means "get the map at this index in the set tied to the program that has the instruction" ๐ฏ
5.4.2. Platform Variables
platform variables are memory regions. they get identified by integer ids, the runtime exposes them, and BPF programs can access them on some platforms ๐ท the var_addr(imm) op means "get the address of the memory region with this id." that's it, that's the tea โ
5.5. Legacy BPF Packet Access Instructions ๐ฐ๏ธ
BPF used to have special instructions for accessing packet data. they were carried over from classic BPF, so they're kinda vintage ๐งธ those instructions used an instruction class of LD, a size modifier of W, H, or B, and a mode modifier of ABS or IND. the dst_reg and offset fields were set to zero, and src_reg was set to zero for ABS.
BUT these instructions are deprecated, so they SHOULD no longer be used ๐ all the legacy packet access instructions belong to the "packet" conformance group.
6. Security Considerations ๐จ
okay bestie, this section is serious business ๐ญ BPF programs could use BPF instructions to do malicious things with memory, CPU, networking, or other system resources. honestly that's not a unique problem, it's the same deal with any software that runs on a device ๐
so execution environments should be carefully designed to only run BPF programs that are trusted and verified. sandboxing and privilege level separation are the key strategies for limiting security and abuse impact ๐ก๏ธ
BPF verifiers are the well-known, widely deployed bodyguards here ๐ช they're responsible for making sure BPF programs terminate within a reasonable time, only interact with memory in safe ways, stick to platform-specified API contracts, and don't use instructions with undefined behavior. this level of verification can often give a stronger level of security assurance than other software and OS code, which is lowkey iconic โจ
the details are out of scope for this document, but Linux [LINUX] and PREVAIL [PREVAIL] have lots of info ๐ and future IETF work will document verifier expectations and building blocks for safely running untrusted BPF programs ๐ฎ
โ ๏ธ executing programs using the BPF instruction set also requires either an interpreter or a compiler to translate them into built-in hardware processor instructions. interpreters are generally considered a source of insecurity whenever they run in the same memory address space as data with confidentiality concerns. this is because of things like gadgets that are susceptible to side-channel attacks due to speculative execution. so use of a compiler is recommended instead ๐ compilers should be audited carefully for vulnerabilities, so that compiling a trusted and verified BPF program into built-in processor instructions doesn't introduce any vulnerabilities ๐
exposing functionality via BPF extends the interface between the component executing the BPF program and the component submitting it ๐ค so careful consideration is required about what functionality gets exposed and how that impacts the security properties you want ๐ฅน
7. IANA Considerations ๐
this document defines two registries ๐
7.1. BPF Instruction Conformance Groups Registry ๐
okay so this section creates a brand new IANA registry just for BPF instruction conformance groups ๐ง it's giving organized and honestly iconic.
- Name of the registry: BPF Instruction Conformance Groups
- Name of the registry group: BPF Instructions
- Required information for registrations: see the BPF Instruction Conformance Groups Registration Template (Section 7.1.1)
- Syntax of registry entries: each entry has these fields: name, description, includes, excludes, status, change controller, and reference. Check Section 7.1.1 for the deets ๐
- Registration policy (see Section 4 of [RFC8126] for details):
- Permanent: Standards Action or IESG Approval
- Provisional: Specification Required
- Historical: Specification Required
- Contact: BPF Working Group
- Change Controller: IETF
the initial entries in the registry look like this, bestie ๐ธ
+========+===============+========+========+============+===========+
|Name | Description |Includes|Excludes| Status | Reference |
+========+===============+========+========+============+===========+
|atomic32| 32-bit |- |- | Permanent | RFC 9669, |
| | atomic | | | | Section |
| | instructions | | | | 5.3 |
+--------+---------------+--------+--------+------------+-----------+
|atomic64| 64-bit |atomic32|- | Permanent | RFC 9669, |
| | atomic | | | | Section |
| | instructions | | | | 5.3 |
+--------+---------------+--------+--------+------------+-----------+
|base32 | 32-bit base |- |- | Permanent | RFC 9669 |
| | instructions | | | | |
+--------+---------------+--------+--------+------------+-----------+
|base64 | 64-bit base |base32 |- | Permanent | RFC 9669 |
| | instructions | | | | |
+--------+---------------+--------+--------+------------+-----------+
|divmul32| 32-bit |- |- | Permanent | RFC 9669, |
| | division and | | | | Section |
| | modulo | | | | 4.1 |
+--------+---------------+--------+--------+------------+-----------+
|divmul64| 64-bit |divmul32|- | Permanent | RFC 9669, |
| | division and | | | | Section |
| | modulo | | | | 4.1 |
+--------+---------------+--------+--------+------------+-----------+
|packet | Legacy |- |- | Historical | RFC 9669, |
| | packet | | | | Section |
| | instructions | | | | 5.5 |
+--------+---------------+--------+--------+------------+-----------+
Table 13: Initial Conformance Groups
7.1.1. BPF Instruction Conformance Groups Registration Template โจ
this is the template that shows which fields you have to fill in when you request a registration ๐
Name: an alphanumeric label with the name of the conformance group.
Description: a short description of the conformance group.
Includes: any other conformance groups that this group includes.
Excludes: any other conformance groups that this group excludes.
Status: the status you're requesting, which must be one of 'Permanent', 'Provisional', or 'Historical'.
Contact: a person (with contact info) to reach out to for more info.
Change Controller: the organization or person (often the author of the defining spec), with contact info, who's allowed to change this ๐ซถ
Reference: a reference to the defining specification. Include full citations for every referenced document. Registration requests for 'Provisional' registration can go in an Internet-Draft. Once the documents are approved for publication as an RFC, the registration gets updated to 'Permanent' ๐ฆ
7.2. BPF Instruction Set Registry ๐
and now we get the registry for the actual BPF instructions ๐ฅ
- Name of the registry: BPF Instruction Set
- Name of the registry group: BPF Instructions
- Required information for registrations: see the BPF Instruction Registration Template (Section 7.2.1)
- Syntax of registry entries: each entry has these fields: opcode, src, offset, imm, description, groups, change controller, and reference. Check Section 7.2.1 for more details.
- Registration policy: new instructions need a new entry in the conformance group registry, and the same registration policies apply.
- Contact: BPF Working Group
- Change Controller: IETF
- Initial registrations: see Appendix A. Instructions other than those listed as deprecated are Permanent. Any listed as deprecated are Historical.
7.2.1. BPF Instruction Registration Template ๐
this is the template for registering an individual instruction ๐ง
Opcode: a 1-byte value in hex format showing the value of the opcode field.
Src_reg: either a numeric value showing the value of the src_reg field, or "any".
Offset: either a numeric value showing the value of the offset field, or "any".
Imm: either a value showing the value of the imm field, or "any".
Description: what the instruction does, usually written as pseudocode.
Groups: a list of one or more comma-separated conformance groups that the instruction belongs to.
Contact: a person (with contact info) to reach out to for more info.
Change Controller: the organization or person (often the author), with contact info, who's allowed to change this.
Reference: a reference to the defining specification. Include full citations for every referenced document. Registration requests for 'Provisional' registration can go in an Internet-Draft. Once the documents are approved for publication as an RFC, the registration gets updated to 'Permanent' ๐
7.3. Adding Instructions ๐ฆ
okay so a spec is allowed to add new instructions to the BPF Instruction Set registry ๐ but here's the tea: once a conformance group is registered with a set of instructions, you can't add any more instructions to that group. the move instead is to create a new conformance group that includes the original group plus the newly added instructions ๐ the original group gets included through the "includes" column of the BPF Instruction Conformance Groups registry, and the new instructions get included through the "groups" column of the BPF Instruction Set registry.
for example, say there's an existing made-up group called "example" with two instructions in it. you could add two more instructions by first adding an "examplev2" group to the BPF Instruction Conformance Groups registry like this ๐ธ
+===========+==================+==========+==========+===========+
| Name | Description | Includes | Excludes | Status |
+===========+==================+==========+==========+===========+
| example | Original example | - | - | Permanent |
| | instructions | | | |
+-----------+------------------+----------+----------+-----------+
| examplev2 | Newer set of | example | - | Permanent |
| | example | | | |
| | instructions | | | |
+-----------+------------------+----------+----------+-----------+
Table 14: Conformance Group Example for Addition
and then you add the new instructions to the BPF Instruction Set registry like this ๐ง
+========+=====+================================+===========+
| opcode | ... | Description | Groups |
+========+=====+================================+===========+
| aaa | ... | Original example instruction 1 | example |
+--------+-----+--------------------------------+-----------+
| bbb | ... | Original example instruction 2 | example |
+--------+-----+--------------------------------+-----------+
| ccc | ... | Added example instruction 3 | examplev2 |
+--------+-----+--------------------------------+-----------+
| ddd | ... | Added example instruction 4 | examplev2 |
+--------+-----+--------------------------------+-----------+
Table 15: Instruction Addition Example
so supporting the "examplev2" group means supporting all four example instructions, periodt ๐๐ฉท
7.4. Deprecating Instructions ๐๏ธโจ
okay bestie, deprecating an instruction that already lives in a conformance group is kinda delicate, so let's be careful ๐ซถ The move is to define a new conformance group for the newly deprecated instructions, and then define a new group that supersedes the existing one. That superseding group includes the existing group and excludes the deprecated instruction group. It's giving clean breakup with receipts ๐
Say we're deprecating an instruction in an existing hypothetical group called example. We could register two new groups, legacyexample and examplev2, in the BPF Instruction Conformance Groups registry like this ๐
+===============+==============+========+===============+==========+
| Name | Description |Includes| Excludes |Status |
+===============+==============+========+===============+==========+
| example | Original |- | - |Permanent |
| | example | | | |
| | instructions | | | |
+---------------+--------------+--------+---------------+----------+
| legacyexample | Legacy |- | - |Historical|
| | example | | | |
| | instructions | | | |
+---------------+--------------+--------+---------------+----------+
| examplev2 | Example |example | legacyexample |Permanent |
| | instructions | | | |
+---------------+--------------+--------+---------------+----------+
Table 16: Conformance Group Example for Deprecation
Next up, the BPF Instruction Set registry entries for the deprecated instructions get updated so they also belong to legacyexample ๐ง It looks like this:
+========+=====+=============================+===============+
| opcode | ... | Description | Groups |
+========+=====+=============================+===============+
| aaa | ... | Good original instruction 1 | example |
+--------+-----+-----------------------------+---------------+
| bbb | ... | Good original instruction 2 | example |
+--------+-----+-----------------------------+---------------+
| ccc | ... | Bad original instruction 3 | example, |
| | | | legacyexample |
+--------+-----+-----------------------------+---------------+
| ddd | ... | Bad original instruction 4 | example, |
| | | | legacyexample |
+--------+-----+-----------------------------+---------------+
Table 17: Instruction Deprecation Example
And the payoff ๐ Implementations that dropped support for the deprecated instructions can then claim conformance to "examplev2" instead of "example". Main character glow-up, iykyk ๐ฆ
7.5. Change Control ๐
Registrations can be updated in a registry through the same mechanism that's required for an initial registration. Now, if the original definition of an entry lives in an IESG-approved document (so the IETF is the change controller), updating that specification also needs IESG approval. Very official, very important ๐
'Provisional' registrations can be updated by the change controller named in the existing registration. The IESG can also reassign responsibility for a 'Provisional' registration, or request specific changes to an entry. Why does this matter? It lets changes happen when the original registrant is out of contact, or is unwilling or unable to make them ๐ซ
Moving from 'Provisional' to 'Permanent' can be requested and approved the same way as a new 'Permanent' registration โจ Moving from 'Permanent' to 'Historical' needs IESG approval. And moving from 'Provisional' to 'Historical' can be requested by anyone authorized to update the 'Provisional' registration ๐
7.6. Expert Review Instructions ๐ง
The IANA registries set up by this document are informed by written specifications. Those specifications are facilitated and approved through an Expert Review process (see Section 5.3 of [RFC8126]) ๐
Designated experts are expected to consult with the active BPF working group, for example by emailing the working group's mailing list, if one exists. They should also check with other interested parties, for example by emailing one or more active mailing lists for relevant BPF communities and platforms ๐ฌ The designated expert is expected to verify that the encoding and semantics of any new instructions are properly documented in a public-facing specification. And if future RFC documents for ISA extensions come along, experts may permit early assignment before the RFC document is available, as long as a specification that meets the above requirements exists ๐ฅ
8. References ๐
8.1. Normative References
- [IEN137] Cohen, D., "ON HOLY WARS AND A PLEA FOR PEACE", IEN 137, 1 April 1980,
https://www.rfc-editor.org/ien/ien137.txt. - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,
https://www.rfc-editor.org/info/rfc2119. - [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
https://www.rfc-editor.org/info/rfc8126. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,
https://www.rfc-editor.org/info/rfc8174.
8.2. Informative References
- [LINUX] "eBPF verifier",
https://www.kernel.org/doc/html/latest/bpf/verifier.html. - [PREVAIL] Gershuni, E., Amit, N., Gurfinkel, A., Narodytska, N., Navas, J., Rinetzky, N., Ryzhyk, L., and M. Sagiv, "Simple and Precise Static Analysis of Untrusted Linux Kernel Extensions", DOI 10.1145/3314221.3314590, June 2019,
https://doi.org/10.1145/3314221.3314590.
Appendix A. Initial BPF Instruction Set Values ๐ธ
Here are the initial values for the BPF Instruction Set registry ๐ The descriptions in this table are informative, so don't stress about them too much. If there's ever a discrepancy, the reference is the authoritative source, periodt ๐
Okay bestie, the table keeps going with the next opcodes, so let's keep the vibe going ๐๐ฆ
+======+=======+====+====+========================+========+=======+
|opcode|src_reg|off-|imm |Description |Groups |Ref |
| | |set | | | | |
+======+=======+====+====+========================+========+=======+
|0x00 |0x0 |0 |any |(additional immediate |base64 |RFC |
| | | | |value) | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x04 |0x0 |0 |any |dst = (u32)((u32)dst + |base32 |RFC |
| | | | |(u32)imm) | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x05 |0x0 |any |0x00|goto +offset |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x06 |0x0 |0 |any |goto +imm |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x07 |0x0 |0 |any |dst += imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x0c |any |0 |0x00|dst = (u32)((u32)dst + |base32 |RFC |
| | | | |(u32)src) | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x0f |any |0 |0x00|dst += src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x14 |0x0 |0 |any |dst = (u32)((u32)dst - |base32 |RFC |
| | | | |(u32)imm) | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x15 |0x0 |any |any |if dst == imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x16 |0x0 |any |any |if (u32)dst == imm goto |base32 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x17 |0x0 |0 |any |dst -= imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x0 |0 |any |dst = (next_imm << 32) ||base64 |RFC |
| | | | |imm | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x1 |0 |any |dst = map_by_fd(imm) |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x2 |0 |any |dst = |base64 |RFC |
| | | | |map_val(map_by_fd(imm)) | |9669, |
| | | | |+ next_imm | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x3 |0 |any |dst = var_addr(imm) |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x4 |0 |any |dst = code_addr(imm) |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x5 |0 |any |dst = map_by_idx(imm) |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x18 |0x6 |0 |any |dst = |base64 |RFC |
| | | | |map_val(map_by_idx(imm))| |9669, |
| | | | |+ next_imm | |Section|
| | | | | | |5.4 |
+------+-------+----+----+------------------------+--------+-------+
|0x1c |any |0 |0x00|dst = (u32)((u32)dst - |base32 |RFC |
| | | | |(u32)src) | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x1d |any |any |0x00|if dst == src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x1e |any |any |0x00|if (u32)dst == (u32)src |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x1f |any |0 |0x00|dst -= src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x20 |0x0 |0 |any |(deprecated, |packet |RFC |
| | | | |implementation-specific)| |9669, |
| | | | | | |Section|
| | | | | | |5.5 |
+------+-------+----+----+------------------------+--------+-------+
|0x24 |0x0 |0 |any |dst = (u32)(dst * imm) |divmul32|RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x25 |0x0 |any |any |if dst > imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x26 |0x0 |any |any |if (u32)dst > imm goto |base32 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x27 |0x0 |0 |any |dst *= imm |divmul64|RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x28 |0x0 |0 |any |(deprecated, |packet |RFC |
| | | | |implementation-specific)| |9669, |
| | | | | | |Section|
| | | | | | |5.5 |
+------+-------+----+----+------------------------+--------+-------+
|0x2c |any |0 |0x00|dst = (u32)(dst * src) |divmul32|RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x2d |any |any |0x00|if dst > src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x2e |any |any |0x00|if (u32)dst > (u32)src |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x2f |any |0 |0x00|dst *= src |divmul64|RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x30 |0x0 |0 |any |(deprecated, |packet |RFC |
| | | | |implementation-specific)| |9669, |
| Section | ||||||
|---|---|---|---|---|---|---|
| 5.5 |
+------+-------+----+----+------------------------+--------+-------+
| 0x34 | 0x0 | 0 | any | dst = (u32)((imm != 0) ? | divmul32 | RFC |
|---|---|---|---|---|---|---|
| ((u32)dst / (u32)imm) : | 9669, | |||||
| 0) | Section | |||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x34 | 0x0 | 1 | any | dst = (u32)((imm != 0) ? | divmul32 | RFC |
|---|---|---|---|---|---|---|
| ((s32)dst s/ imm) : 0) | 9669, | |||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x35 | 0x0 | any | any | if dst >= imm goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x36 | 0x0 | any | any | if (u32)dst >= imm goto | base32 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x37 | 0x0 | 0 | any | dst = (imm != 0) ? (dst | divmul64 | RFC |
|---|---|---|---|---|---|---|
| / (u32)imm) : 0 | 9669, | |||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x37 | 0x0 | 1 | any | dst = (imm != 0) ? (dst | divmul64 | RFC |
|---|---|---|---|---|---|---|
| s/ imm) : 0 | 9669, | |||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3c | any | 0 | 0x00 | dst = (u32)((src != 0) ? | divmul32 | RFC |
|---|---|---|---|---|---|---|
| ((u32)dst / (u32)src) : | 9669, | |||||
| 0) | Section | |||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3c | any | 1 | 0x00 | dst = (u32)((src != 0) ? | divmul32 | RFC |
|---|---|---|---|---|---|---|
| ((s32)dst s/(s32)src) : | 9669, | |||||
| 0) | Section | |||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3d | any | any | 0x00 | if dst >= src goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3e | any | any | 0x00 | if (u32)dst >= (u32)src | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3f | any | 0 | 0x00 | dst = (src != 0) ? (dst | divmul64 | RFC |
|---|---|---|---|---|---|---|
| / src) : 0 | 9669, | |||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x3f | any | 1 | 0x00 | dst = (src != 0) ? (dst | divmul64 | RFC |
|---|---|---|---|---|---|---|
| s/ src) : 0 | 9669, | |||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x40 | any | 0 | any | (deprecated, | packet | RFC |
|---|---|---|---|---|---|---|
| implementation-specific) | 9669, | |||||
| Section | ||||||
| 5.5 |
+------+-------+----+----+------------------------+--------+-------+
| 0x44 | 0x0 | 0 | any | dst = (u32)(dst | imm) | base32 | RFC |
|---|---|---|---|---|---|---|---|
| 9669, | |||||||
| Section | |||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x45 | 0x0 | any | any | if dst & imm goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x46 | 0x0 | any | any | if (u32)dst & imm goto | base32 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x47 | 0x0 | 0 | any | dst | = imm | base64 | RFC |
|---|---|---|---|---|---|---|---|
| 9669, | |||||||
| Section | |||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x48 | any | 0 | any | (deprecated, | packet | RFC |
|---|---|---|---|---|---|---|
| implementation-specific) | 9669, | |||||
| Section | ||||||
| 5.5 |
+------+-------+----+----+------------------------+--------+-------+
| 0x4c | any | 0 | 0x00 | dst = (u32)(dst | src) | base32 | RFC |
|---|---|---|---|---|---|---|---|
| 9669, | |||||||
| Section | |||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x4d | any | any | 0x00 | if dst & src goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x4e | any | any | 0x00 | if (u32)dst & (u32)src | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x4f | any | 0 | 0x00 | dst | = src | base64 | RFC |
|---|---|---|---|---|---|---|---|
| 9669, | |||||||
| Section | |||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x50 | any | 0 | any | (deprecated, | packet | RFC |
|---|---|---|---|---|---|---|
| implementation-specific) | 9669, | |||||
| Section | ||||||
| 5.5 |
+------+-------+----+----+------------------------+--------+-------+
| 0x54 | 0x0 | 0 | any | dst = (u32)(dst & imm) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x55 | 0x0 | any | any | if dst != imm goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x56 | 0x0 | any | any | if (u32)dst != imm goto | base32 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x57 | 0x0 | 0 | any | dst &= imm | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x5c | any | 0 | 0x00 | dst = (u32)(dst & src) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x5d | any | any | 0x00 | if dst != src goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x5e | any | any | 0x00 | if (u32)dst != (u32)src | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0x5f | any | 0 | 0x00 | dst &= src | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0x61 | any | any | 0x00 | dst = *(u32 *)(src + | base32 | RFC |
|---|---|---|---|---|---|---|
| offset) | 9669, | |||||
| Section | ||||||
| 5 |
+------+-------+----+----+------------------------+--------+-------+
| 0x62 | 0x0 | any | any | *(u32 *)(dst + offset) = | base32 | RFC |
|---|---|---|---|---|---|---|
| imm | 9669, | |||||
| Section |
okay the instruction table is still going, bestie ๐ฆ every row matters so here's the next chunk ๐
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x63 |any |any |0x00|*(u32 *)(dst + offset) =|base32 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x64 |0x0 |0 |any |dst = (u32)(dst << imm) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x65 |0x0 |any |any |if dst s> imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x66 |0x0 |any |any |if (s32)dst s> (s32)imm |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x67 |0x0 |0 |any |dst <<= imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x69 |any |any |0x00|dst = *(u16 *)(src + |base32 |RFC |
| | | | |offset) | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x6a |0x0 |any |any |*(u16 *)(dst + offset) =|base32 |RFC |
| | | | |imm | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x6b |any |any |0x00|*(u16 *)(dst + offset) =|base32 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x6c |any |0 |0x00|dst = (u32)(dst << src) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x6d |any |any |0x00|if dst s> src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x6e |any |any |0x00|if (s32)dst s> (s32)src |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x6f |any |0 |0x00|dst <<= src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x71 |any |any |0x00|dst = *(u8 *)(src + |base32 |RFC |
| | | | |offset) | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x72 |0x0 |any |any |*(u8 *)(dst + offset) = |base32 |RFC |
| | | | |imm | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x73 |any |any |0x00|*(u8 *)(dst + offset) = |base32 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x74 |0x0 |0 |any |dst = (u32)(dst >> imm) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x75 |0x0 |any |any |if dst s>= imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x76 |0x0 |any |any |if (s32)dst s>= (s32)imm|base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x77 |0x0 |0 |any |dst >>= imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x79 |any |any |0x00|dst = *(u64 *)(src + |base64 |RFC |
| | | | |offset) | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x7a |0x0 |any |any |*(u64 *)(dst + offset) =|base64 |RFC |
| | | | |imm | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x7b |any |any |0x00|*(u64 *)(dst + offset) =|base64 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |5 |
+------+-------+----+----+------------------------+--------+-------+
|0x7c |any |0 |0x00|dst = (u32)(dst >> src) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x7d |any |any |0x00|if dst s>= src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x7e |any |any |0x00|if (s32)dst s>= (s32)src|base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x7f |any |0 |0x00|dst >>= src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x84 |0x0 |0 |0x00|dst = (u32)-dst |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x85 |0x0 |0 |any |call helper function by |base32 |RFC |
| | | | |static ID | |9669, |
| | | | | | |Section|
| | | | | | |4.3.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x85 |0x1 |0 |any |call PC += imm |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.3.2 |
+------+-------+----+----+------------------------+--------+-------+
|0x85 |0x2 |0 |any |call helper function by |base32 |RFC |
| | | | |BTF ID | |9669, |
| | | | | | |Section|
| | | | | | |4.3.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x87 |0x0 |0 |0x00|dst = -dst |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x94 |0x0 |0 |any |dst = (u32)((imm != |divmul32|RFC |
| | | | |0)?((u32)dst % (u32)imm)| |9669, |
| | | | |: dst) | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x94 |0x0 |1 |any |dst = (u32)((imm != 0) ?|divmul32|RFC |
| | | | |((s32)dst s% imm) : dst)| |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
Okay bestie, the table keeps going and it's still giving main character energy ๐ ๐ฆ
+------+-------+----+----+------------------------+--------+-------+
|0x95 |0x0 |0 |0x00|return |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0x97 |0x0 |0 |any |dst = (imm != 0) ? (dst |divmul64|RFC |
| | | | |% (u32)imm) : dst | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x97 |0x0 |1 |any |dst = (imm != 0) ? (dst |divmul64|RFC |
| | | | |s% imm) : dst | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x9c |any |0 |0x00|dst = (u32)((src != |divmul32|RFC |
| | | | |0)?((u32)dst % (u32)src)| |9669, |
| | | | |: dst) | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x9c |any |1 |0x00|dst = (u32)((src != |divmul32|RFC |
| | | | |0)?((s32)dst s% | |9669, |
| | | | |(s32)src) :dst) | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x9f |any |0 |0x00|dst = (src != 0) ? (dst |divmul64|RFC |
| | | | |% src) : dst | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0x9f |any |1 |0x00|dst = (src != 0) ? (dst |divmul64|RFC |
| | | | |s% src) : dst | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xa4 |0x0 |0 |any |dst = (u32)(dst ^ imm) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xa5 |0x0 |any |any |if dst < imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xa6 |0x0 |any |any |if (u32)dst < imm goto |base32 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xa7 |0x0 |0 |any |dst ^= imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xac |any |0 |0x00|dst = (u32)(dst ^ src) |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xad |any |any |0x00|if dst < src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xae |any |any |0x00|if (u32)dst < (u32)src |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xaf |any |0 |0x00|dst ^= src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xb4 |0x0 |0 |any |dst = (u32) imm |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xb5 |0x0 |any |any |if dst <= imm goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xb6 |0x0 |any |any |if (u32)dst <= imm goto |base32 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xb7 |0x0 |0 |any |dst = imm |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbc |any |0 |0x00|dst = (u32) src |base32 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbc |any |8 |0x00|dst = (u32) (s32) (s8) |base32 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbc |any |16 |0x00|dst = (u32) (s32) (s16) |base32 |RFC |
| | | | |src | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbd |any |any |0x00|if dst <= src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xbe |any |any |0x00|if (u32)dst <= (u32)src |base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xbf |any |0 |0x00|dst = src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbf |any |8 |0x00|dst = (s64) (s8) src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbf |any |16 |0x00|dst = (s64) (s16) src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xbf |any |32 |0x00|dst = (s64) (s32) src |base64 |RFC |
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.1 |
+------+-------+----+----+------------------------+--------+-------+
|0xc3 |any |any |0x00|lock *(u32 *)(dst + |atomic32|RFC |
| | | | |offset) += src | |9669, |
| | | | | | |Section|
| | | | | | |5.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xc3 |any |any |0x01|src = |atomic32|RFC |
| | | | |atomic_fetch_add_32((u32| |9669, |
| | | | |*)(dst + offset), src) | |Section|
| | | | | | |5.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xc3 |any |any |0x40|lock *(u32 *)(dst + |atomic32|RFC |
| | | | |offset) |= src | |9669, |
| | | | | | |Section|
| | | | | | |5.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xc3 |any |any |0x41|src = |atomic32|RFC |
| | | | |atomic_fetch_or_32((u32 | |9669, |
| | | | |*)(dst + offset), src) | |Section|
| | | | | | |5.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xc3 |any |any |0x50|lock *(u32 *)(dst + |atomic32|RFC |
| | | | |offset) &= src | |9669, |
| | | | | | |Section|
| | | | | | |5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc3 | any | any | 0x51 | src = | atomic32 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_and_32((u32 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc3 | any | any | 0xa0 | lock *(u32 *)(dst + | atomic32 | RFC |
|---|---|---|---|---|---|---|
| offset) ^= src | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc3 | any | any | 0xa1 | src = | atomic32 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_xor_32((u32 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc3 | any | any | 0xe1 | src = xchg_32((u32 | atomic32 | RFC |
|---|---|---|---|---|---|---|
| *)(dst + offset), src) | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc3 | any | any | 0xf1 | r0 = cmpxchg_32((u32 | atomic32 | RFC |
|---|---|---|---|---|---|---|
| *)(dst + offset), r0, | 9669, | |||||
| src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc4 | 0x0 | 0 | any | dst = (u32)(dst s>> imm) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc5 | 0x0 | any | any | if dst s< imm goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc6 | 0x0 | any | any | if (s32)dst s< (s32)imm | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xc7 | 0x0 | 0 | any | dst s>>= imm | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0xcc | any | 0 | 0x00 | dst = (u32)(dst s>> src) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0xcd | any | any | 0x00 | if dst s< src goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xce | any | any | 0x00 | if (s32)dst s< (s32)src | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xcf | any | 0 | 0x00 | dst s>>= src | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.1 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd4 | 0x0 | 0 | 0x10 | dst = htole16(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd4 | 0x0 | 0 | 0x20 | dst = htole32(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd4 | 0x0 | 0 | 0x40 | dst = htole64(dst) | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd5 | 0x0 | any | any | if dst s<= imm goto | base64 | RFC |
|---|---|---|---|---|---|---|
| +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd6 | 0x0 | any | any | if (s32)dst s<= (s32)imm | base32 | RFC |
|---|---|---|---|---|---|---|
| goto +offset | 9669, | |||||
| Section | ||||||
| 4.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd7 | 0x0 | 0 | 0x10 | dst = bswap16(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd7 | 0x0 | 0 | 0x20 | dst = bswap32(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xd7 | 0x0 | 0 | 0x40 | dst = bswap64(dst) | base64 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x00 | lock *(u64 *)(dst + | atomic64 | RFC |
|---|---|---|---|---|---|---|
| offset) += src | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x01 | src = | atomic64 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_add_64((u64 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x40 | lock *(u64 *)(dst + | atomic64 | RFC | |
|---|---|---|---|---|---|---|---|
| offset) | = src | 9669, | |||||
| Section | |||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x41 | src = | atomic64 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_or_64((u64 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x50 | lock *(u64 *)(dst + | atomic64 | RFC |
|---|---|---|---|---|---|---|
| offset) &= src | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0x51 | src = | atomic64 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_and_64((u64 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0xa0 | lock *(u64 *)(dst + | atomic64 | RFC |
|---|---|---|---|---|---|---|
| offset) ^= src | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0xa1 | src = | atomic64 | RFC |
|---|---|---|---|---|---|---|
| atomic_fetch_xor_64((u64 | 9669, | |||||
| *)(dst + offset), src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0xe1 | src = xchg_64((u64 | atomic64 | RFC |
|---|---|---|---|---|---|---|
| *)(dst + offset), src) | 9669, | |||||
| Section | ||||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdb | any | any | 0xf1 | r0 = cmpxchg_64((u64 | atomic64 | RFC |
|---|---|---|---|---|---|---|
| *)(dst + offset), r0, | 9669, | |||||
| src) | Section | |||||
| 5.3 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdc | 0x0 | 0 | 0x10 | dst = htobe16(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdc | 0x0 | 0 | 0x20 | dst = htobe32(dst) | base32 | RFC |
|---|---|---|---|---|---|---|
| 9669, | ||||||
| Section | ||||||
| 4.2 |
+------+-------+----+----+------------------------+--------+-------+
| 0xdc | 0x0 | 0 | 0x40 | dst = htobe64(dst) | base64 | RFC |
Okay bestie, the last bit of Appendix A is this little table, and the two new rows are giving base64 and base32 energy ๐งโจ
| | | | | | |9669, |
| | | | | | |Section|
| | | | | | |4.2 |
+------+-------+----+----+------------------------+--------+-------+
|0xdd |any |any |0x00|if dst s<= src goto |base64 |RFC |
| | | | |+offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
|0xde |any |any |0x00|if (s32)dst s<= (s32)src|base32 |RFC |
| | | | |goto +offset | |9669, |
| | | | | | |Section|
| | | | | | |4.3 |
+------+-------+----+----+------------------------+--------+-------+
Table 18: Initial BPF Instruction Set Values
Acknowledgements ๐ซถ
Huge thank-you energy to everyone who helped make this doc! ๐ It was generated from instruction-set.rst in the Linux kernel repository, which has had a whole crew of contributors over the years: Akhil Raj, Alexei Starovoitov, Brendan Jackman, Christoph Hellwig, Daniel Borkmann, Ilya Leoshkevich, Jiong Wang, Jose E. Marchesi, Kosuke Fujimoto, Shahab Vahedi, Tiezhu Yang, Will Hawkins, and Zheng Yejian. ๐ Then there were the reviewers who gave feedback and suggestions, and they were absolutely iconic: Alan Jowett, Andrii Nakryiko, David Vernet, Jim Harris, Quentin Monnet, Song Liu, Shung-Hsi Yu, Stanislav Fomichev, Watson Ladd, and Yonghong Song. ๐ Y'all are the reason this spec slaps.
Author's Address ๐
The editor is Dave Thaler, so if you want to reach out, here's the info:
Dave Thaler (editor)
Redmond, WA 98052
United States of America
Email: dave.thaler.ietf@gmail.com
๐ฆ where this page comes from
- ietf: rfc9669 2024-10
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms