RFC 9669

BPF Instruction Set Architecture (ISA)

๐Ÿ“… published October 2024, from ietf

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 (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 ๐Ÿช„.

  1. Copy all X bits from A into the lower X bits of B.
  2. 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 type can be used by disassemblers for display ๐Ÿ‘€
  • the dst type can 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

8.2. Informative References

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

+------+-------+----+----+------------------------+--------+-------+

0x340x00anydst = (u32)((imm != 0) ?divmul32RFC
((u32)dst / (u32)imm) :9669,
0)Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x340x01anydst = (u32)((imm != 0) ?divmul32RFC
((s32)dst s/ imm) : 0)9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x350x0anyanyif dst >= imm gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x360x0anyanyif (u32)dst >= imm gotobase32RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x370x00anydst = (imm != 0) ? (dstdivmul64RFC
/ (u32)imm) : 09669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x370x01anydst = (imm != 0) ? (dstdivmul64RFC
s/ imm) : 09669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x3cany00x00dst = (u32)((src != 0) ?divmul32RFC
((u32)dst / (u32)src) :9669,
0)Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x3cany10x00dst = (u32)((src != 0) ?divmul32RFC
((s32)dst s/(s32)src) :9669,
0)Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x3danyany0x00if dst >= src gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x3eanyany0x00if (u32)dst >= (u32)srcbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x3fany00x00dst = (src != 0) ? (dstdivmul64RFC
/ src) : 09669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x3fany10x00dst = (src != 0) ? (dstdivmul64RFC
s/ src) : 09669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x40any0any(deprecated,packetRFC
implementation-specific)9669,
Section
5.5

+------+-------+----+----+------------------------+--------+-------+

0x440x00anydst = (u32)(dstimm)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x450x0anyanyif dst & imm gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x460x0anyanyif (u32)dst & imm gotobase32RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x470x00anydst= immbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x48any0any(deprecated,packetRFC
implementation-specific)9669,
Section
5.5

+------+-------+----+----+------------------------+--------+-------+

0x4cany00x00dst = (u32)(dstsrc)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x4danyany0x00if dst & src gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x4eanyany0x00if (u32)dst & (u32)srcbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x4fany00x00dst= srcbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x50any0any(deprecated,packetRFC
implementation-specific)9669,
Section
5.5

+------+-------+----+----+------------------------+--------+-------+

0x540x00anydst = (u32)(dst & imm)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x550x0anyanyif dst != imm gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x560x0anyanyif (u32)dst != imm gotobase32RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x570x00anydst &= immbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x5cany00x00dst = (u32)(dst & src)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x5danyany0x00if dst != src gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x5eanyany0x00if (u32)dst != (u32)srcbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0x5fany00x00dst &= srcbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0x61anyany0x00dst = *(u32 *)(src +base32RFC
offset)9669,
Section
5

+------+-------+----+----+------------------------+--------+-------+

0x620x0anyany*(u32 *)(dst + offset) =base32RFC
imm9669,
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    |
   +------+-------+----+----+------------------------+--------+-------+
0xc3anyany0x51src =atomic32RFC
atomic_fetch_and_32((u329669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xc3anyany0xa0lock *(u32 *)(dst +atomic32RFC
offset) ^= src9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xc3anyany0xa1src =atomic32RFC
atomic_fetch_xor_32((u329669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xc3anyany0xe1src = xchg_32((u32atomic32RFC
*)(dst + offset), src)9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xc3anyany0xf1r0 = cmpxchg_32((u32atomic32RFC
*)(dst + offset), r0,9669,
src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xc40x00anydst = (u32)(dst s>> imm)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0xc50x0anyanyif dst s< imm gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xc60x0anyanyif (s32)dst s< (s32)immbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xc70x00anydst s>>= immbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0xccany00x00dst = (u32)(dst s>> src)base32RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0xcdanyany0x00if dst s< src gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xceanyany0x00if (s32)dst s< (s32)srcbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xcfany00x00dst s>>= srcbase64RFC
9669,
Section
4.1

+------+-------+----+----+------------------------+--------+-------+

0xd40x000x10dst = htole16(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xd40x000x20dst = htole32(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xd40x000x40dst = htole64(dst)base64RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xd50x0anyanyif dst s<= imm gotobase64RFC
+offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xd60x0anyanyif (s32)dst s<= (s32)immbase32RFC
goto +offset9669,
Section
4.3

+------+-------+----+----+------------------------+--------+-------+

0xd70x000x10dst = bswap16(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xd70x000x20dst = bswap32(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xd70x000x40dst = bswap64(dst)base64RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x00lock *(u64 *)(dst +atomic64RFC
offset) += src9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x01src =atomic64RFC
atomic_fetch_add_64((u649669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x40lock *(u64 *)(dst +atomic64RFC
offset)= src9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x41src =atomic64RFC
atomic_fetch_or_64((u649669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x50lock *(u64 *)(dst +atomic64RFC
offset) &= src9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0x51src =atomic64RFC
atomic_fetch_and_64((u649669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0xa0lock *(u64 *)(dst +atomic64RFC
offset) ^= src9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0xa1src =atomic64RFC
atomic_fetch_xor_64((u649669,
*)(dst + offset), src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0xe1src = xchg_64((u64atomic64RFC
*)(dst + offset), src)9669,
Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdbanyany0xf1r0 = cmpxchg_64((u64atomic64RFC
*)(dst + offset), r0,9669,
src)Section
5.3

+------+-------+----+----+------------------------+--------+-------+

0xdc0x000x10dst = htobe16(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xdc0x000x20dst = htobe32(dst)base32RFC
9669,
Section
4.2

+------+-------+----+----+------------------------+--------+-------+

0xdc0x000x40dst = htobe64(dst)base64RFC

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