diff --git a/isa/kernel.org/instruction-set.rst b/isa/kernel.org/instruction-set.rst index 7f8ee00..9d77d28 100644 --- a/isa/kernel.org/instruction-set.rst +++ b/isa/kernel.org/instruction-set.rst @@ -67,7 +67,8 @@ eBPF has two instruction encodings: * the wide instruction encoding, which appends a second 64-bit immediate (i.e., constant) value after the basic instruction for a total of 128 bits. -The basic instruction encoding is as follows: +The basic instruction encoding is as follows, where MSB and LSB mean the most significant +bits and least significant bits, respectively: ============= ======= =============== ==================== ============ 32 bits (MSB) 16 bits 4 bits 4 bits 8 bits (LSB) @@ -76,13 +77,14 @@ imm offset src dst opcode ============= ======= =============== ==================== ============ imm - integer immediate value + signed integer immediate value offset signed integer offset used with pointer arithmetic src - source register number (0-10) + the source register number (0-10), except where otherwise specified + (`64-bit immediate instructions`_ reuse this field for other purposes) dst destination register number (0-10) @@ -93,17 +95,24 @@ opcode Note that most instructions do not use all of the fields. Unused fields must be set to zero. -As discussed below in `64-bit immediate instructions`_, some basic -instructions denote that a 64-bit immediate value follows. Thus -the wide instruction encoding is as follows: +As discussed below in `64-bit immediate instructions`_, some +instructions use a 64-bit immediate value that is constructed as follows. +The 64 bits following the basic instruction contain a pseudo instruction +using the same format but with opcode, dst, src, and offset all set to zero, +and imm containing the high 32 bits of the immediate value. -================= ============= +================= ================== 64 bits (MSB) 64 bits (LSB) -================= ============= -basic instruction imm64 -================= ============= +================= ================== +basic instruction pseudo instruction +================= ================== -where MSB and LSB mean the most significant bits and least significant bits, respectively. +Thus the 64-bit immediate value is constructed as follows: + + imm64 = imm + (next_imm << 32) + +where 'next_imm' refers to the imm value of the pseudo instruction +following the basic instruction. In the remainder of this document 'src' and 'dst' refer to the values of the source and destination registers, respectively, rather than the register number. @@ -182,31 +191,33 @@ code value description BPF_ADD 0x00 dst += src BPF_SUB 0x10 dst -= src BPF_MUL 0x20 dst \*= src -BPF_DIV 0x30 dst /= src +BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0 BPF_OR 0x40 dst \|= src BPF_AND 0x50 dst &= src BPF_LSH 0x60 dst <<= src BPF_RSH 0x70 dst >>= src BPF_NEG 0x80 dst = ~src -BPF_MOD 0x90 dst %= src +BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : src BPF_XOR 0xa0 dst ^= src BPF_MOV 0xb0 dst = src BPF_ARSH 0xc0 sign extending shift right BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below) ======== ===== ================================================= -Underflow and overflow are allowed during arithmetic operations, -meaning the 64-bit or 32-bit value will wrap. +where 'src' is the source operand value. -``BPF_DIV`` has an implicit program exit condition as well. If +Underflow and overflow are allowed during arithmetic operations, +meaning the 64-bit or 32-bit value will wrap. If eBPF program execution would result in division by zero, -program execution must be gracefully aborted. +the destination register is instead set to zero. +If execution would result in module by zero, +the destination register is instead set to the source value. Examples: ``BPF_ADD | BPF_X | BPF_ALU`` (0x0c) means:: - dst = (uint32_t) (dst + src); + dst = (uint32_t) (dst + src) where '(uint32_t)' indicates truncation to 32 bits. @@ -325,6 +336,14 @@ with the remaining registers being ignored. The definition of a helper function is responsible for specifying the type (e.g., integer, pointer, etc.) of the value returned, the number of arguments, and the type of each argument. +Note that ``BPF_CALL | BPF_X | BPF_JMP`` (0x8d), where the helper function integer +would be read from a specified register, is not currently permitted. + + **Note** + + *Clang implementation*: + Clang will generate this invalid instruction if ``-O0`` is used. + Load and store instructions =========================== @@ -468,250 +487,273 @@ and loaded back to ``R0``. ----------------------------- Instructions with the ``BPF_IMM`` 'mode' modifier use the wide instruction -encoding for an extra imm64 value. - -There is currently only one such instruction. +encoding defined in `Instruction encoding`_, and use the 'src' field of the +basic instruction to hold an opcode subtype. + +The following instructions are defined, and use additional concepts defined below: + +========================= ====== ==== ===================================== =========== ============== +opcode construction opcode src pseudocode imm type dst type +========================= ====== ==== ===================================== =========== ============== +BPF_IMM | BPF_DW | BPF_LD 0x18 0x00 dst = imm64 integer integer +BPF_IMM | BPF_DW | BPF_LD 0x18 0x01 dst = map_by_fd(imm) map fd map +BPF_IMM | BPF_DW | BPF_LD 0x18 0x02 dst = mva(map_by_fd(imm)) + next_imm map fd data pointer +BPF_IMM | BPF_DW | BPF_LD 0x18 0x03 dst = variable_addr(imm) variable id data pointer +BPF_IMM | BPF_DW | BPF_LD 0x18 0x04 dst = code_addr(imm) integer code pointer +BPF_IMM | BPF_DW | BPF_LD 0x18 0x05 dst = mva(map_by_idx(imm)) map index map +BPF_IMM | BPF_DW | BPF_LD 0x18 0x06 dst = mva(map_by_idx(imm)) + next_imm map index data pointer +========================= ====== ==== ===================================== =========== ============== -``BPF_IMM | BPF_DW | BPF_LD`` (0x18) means:: +where - dst = imm64 +* map_by_fd(fd) means to convert a 32-bit POSIX file descriptor into an address of a map object +* map_by_index(index) means to convert a 32-bit index into an address of a map object +* mva(map) gets the address of the memory region expressed by a given map object +* variable_addr(id) gets the address of a variable with a given id +* code_addr(offset) gets the address of the instruction at a specified relative offset in units of 64-bit blocks +* the 'imm type' can be used by disassemblers for display +* the 'dst type' can be used for verification and JIT compilation purposes +Map objects +~~~~~~~~~~~ -Legacy BPF Packet access instructions -------------------------------------- +Maps are shared memory regions accessible by eBPF programs, where we use the term "map object" +to refer to an object containing the data and metadata (e.g., size) about the memory region. +A map can have various semantics as defined in a separate document, and may or may not have a single +contiguous memory region, but the 'mva(map)' is currently only defined for maps that do have a single +contiguous memory region. -eBPF has special instructions for access to packet data that have been -carried over from classic BPF to retain the performance of legacy socket -filters running in an eBPF interpreter. + **Note** -The instructions come in two forms: ``BPF_ABS | | BPF_LD`` and -``BPF_IND | | BPF_LD``. + *Linux implementation*: Linux only supports the 'mva(map)' operation on array maps with a single element. -These instructions are used to access packet data and can only be used when -the program context contains a pointer to a networking packet. ``BPF_ABS`` -accesses packet data at an absolute offset specified by the immediate data -and ``BPF_IND`` access packet data at an offset that includes the value of -a register in addition to the immediate data. +Each map object can have a POSIX file descriptor (fd) if supported by the platform, +where 'map_by_fd(fd)' means to get the map with the specified file descriptor. +Each eBPF program can also be defined to use a set of maps associated with the program +at load time, and 'map_by_index(index)' means to get the map with the given index in the set +associated with the eBPF program containing the instruction. -These instructions have seven implicit operands: +Variables +~~~~~~~~~ -* Register R6 is an implicit input that must contain a pointer to a - context structure with a packet data pointer. -* Register R0 is an implicit output which contains the data fetched from - the packet. -* Registers R1-R5 are scratch registers that are clobbered by the - instruction. +Variables are memory regions, identified by integer ids, accessible by eBPF programs on +some platforms. The 'variable_addr(id)' operation means to get the address of the memory region +identified by the given id. **Note** - *Linux implementation*: In Linux, R6 references a struct sk_buff. - -These instructions have an implicit program exit condition as well. If an -eBPF program attempts access data beyond the packet boundary, the -program execution must be gracefully aborted. + *Linux implementation*: Linux uses BTF ids to identify variables. -``BPF_ABS | BPF_W | BPF_LD`` (0x20) means:: - - R0 = ntohl(*(uint32_t *) (R6->data + imm)) +Legacy BPF Packet access instructions +------------------------------------- -where ``ntohl()`` converts a 32-bit value from network byte order to host byte order. +Linux introduced special instructions for access to packet data that were +carried over from classic BPF. However, these instructions are +deprecated and should no longer be used in any version of the ISA. -``BPF_IND | BPF_W | BPF_LD`` (0x40) means:: + **Note** - R0 = ntohl(*(uint32_t *) (R6->data + src + imm)) + *Linux implementation*: Details can be found in the `Linux historical notes `_. Appendix ======== For reference, the following table lists opcodes in order by value. -====== ==== =================================================== ============= -opcode imm description reference -====== ==== =================================================== ============= -0x04 any dst = (uint32_t)(dst + imm) `Arithmetic instructions`_ -0x05 0x00 goto +offset `Jump instructions`_ -0x07 any dst += imm `Arithmetic instructions`_ -0x0c 0x00 dst = (uint32_t)(dst + src) `Arithmetic instructions`_ -0x0f 0x00 dst += src `Arithmetic instructions`_ -0x14 any dst = (uint32_t)(dst - imm) `Arithmetic instructions`_ -0x15 any if dst == imm goto +offset `Jump instructions`_ -0x16 any if (uint32_t)dst == imm goto +offset `Jump instructions`_ -0x17 any dst -= imm `Arithmetic instructions`_ -0x18 any dst = imm `Load and store instructions`_ -0x1c 0x00 dst = (uint32_t)(dst - src) `Arithmetic instructions`_ -0x1d 0x00 if dst == src goto +offset `Jump instructions`_ -0x1e 0x00 if (uint32_t)dst == (uint32_t)src goto +offset `Jump instructions`_ -0x1f 0x00 dst -= src `Arithmetic instructions`_ -0x20 any dst = ntohl(\*(uint32_t \*)(R6->data + imm)) `Load and store instructions`_ -0x24 any dst = (uint32_t)(dst \* imm) `Arithmetic instructions`_ -0x25 any if dst > imm goto +offset `Jump instructions`_ -0x26 any if (uint32_t)dst > imm goto +offset `Jump instructions`_ -0x27 any dst \*= imm `Arithmetic instructions`_ -0x28 any dst = ntohs(\*(uint16_t \*)(R6->data + imm)) `Load and store instructions`_ -0x2c 0x00 dst = (uint32_t)(dst \* src) `Arithmetic instructions`_ -0x2d 0x00 if dst > src goto +offset `Jump instructions`_ -0x2e 0x00 if (uint32_t)dst > (uint32_t)src goto +offset `Jump instructions`_ -0x2f 0x00 dst \*= src `Arithmetic instructions`_ -0x30 any dst = (\*(uint8_t \*)(R6->data + imm)) `Load and store instructions`_ -0x34 any dst = (uint32_t)(dst / imm) `Arithmetic instructions`_ -0x35 any if dst >= imm goto +offset `Jump instructions`_ -0x36 any if (uint32_t)dst >= imm goto +offset `Jump instructions`_ -0x37 any dst /= imm `Arithmetic instructions`_ -0x38 any dst = ntohll(\*(uint64_t \*)(R6->data + imm)) `Load and store instructions`_ -0x3c 0x00 dst = (uint32_t)(dst / src) `Arithmetic instructions`_ -0x3d 0x00 if dst >= src goto +offset `Jump instructions`_ -0x3e 0x00 if (uint32_t)dst >= (uint32_t)src goto +offset `Jump instructions`_ -0x3f 0x00 dst /= src `Arithmetic instructions`_ -0x40 any dst = ntohl(\*(uint32_t \*)(R6->data + src + imm)) `Load and store instructions`_ -0x44 any dst = (uint32_t)(dst \| imm) `Arithmetic instructions`_ -0x45 any if dst & imm goto +offset `Jump instructions`_ -0x46 any if (uint32_t)dst & imm goto +offset `Jump instructions`_ -0x47 any dst \|= imm `Arithmetic instructions`_ -0x48 any dst = ntohs(\*(uint16_t \*)(R6->data + src + imm)) `Load and store instructions`_ -0x4c 0x00 dst = (uint32_t)(dst \| src) `Arithmetic instructions`_ -0x4d 0x00 if dst & src goto +offset `Jump instructions`_ -0x4e 0x00 if (uint32_t)dst & (uint32_t)src goto +offset `Jump instructions`_ -0x4f 0x00 dst \|= src `Arithmetic instructions`_ -0x50 any dst = \*(uint8_t \*)(R6->data + src + imm)) `Load and store instructions`_ -0x54 any dst = (uint32_t)(dst & imm) `Arithmetic instructions`_ -0x55 any if dst != imm goto +offset `Jump instructions`_ -0x56 any if (uint32_t)dst != imm goto +offset `Jump instructions`_ -0x57 any dst &= imm `Arithmetic instructions`_ -0x58 any dst = ntohll(\*(uint64_t \*)(R6->data + src + imm)) `Load and store instructions`_ -0x5c 0x00 dst = (uint32_t)(dst & src) `Arithmetic instructions`_ -0x5d 0x00 if dst != src goto +offset `Jump instructions`_ -0x5e 0x00 if (uint32_t)dst != (uint32_t)src goto +offset `Jump instructions`_ -0x5f 0x00 dst &= src `Arithmetic instructions`_ -0x61 0x00 dst = \*(uint32_t \*)(src + offset) `Load and store instructions`_ -0x62 any \*(uint32_t \*)(dst + offset) = imm `Load and store instructions`_ -0x63 0x00 \*(uint32_t \*)(dst + offset) = src `Load and store instructions`_ -0x64 any dst = (uint32_t)(dst << imm) `Arithmetic instructions`_ -0x65 any if dst s> imm goto +offset `Jump instructions`_ -0x66 any if (int32_t)dst s> (int32_t)imm goto +offset `Jump instructions`_ -0x67 any dst <<= imm `Arithmetic instructions`_ -0x69 0x00 dst = \*(uint16_t \*)(src + offset) `Load and store instructions`_ -0x6a any \*(uint16_t \*)(dst + offset) = imm `Load and store instructions`_ -0x6b 0x00 \*(uint16_t \*)(dst + offset) = src `Load and store instructions`_ -0x6c 0x00 dst = (uint32_t)(dst << src) `Arithmetic instructions`_ -0x6d 0x00 if dst s> src goto +offset `Jump instructions`_ -0x6e 0x00 if (int32_t)dst s> (int32_t)src goto +offset `Jump instructions`_ -0x6f 0x00 dst <<= src `Arithmetic instructions`_ -0x71 0x00 dst = \*(uint8_t \*)(src + offset) `Load and store instructions`_ -0x72 any \*(uint8_t \*)(dst + offset) = imm `Load and store instructions`_ -0x73 0x00 \*(uint8_t \*)(dst + offset) = src `Load and store instructions`_ -0x74 any dst = (uint32_t)(dst >> imm) `Arithmetic instructions`_ -0x75 any if dst s>= imm goto +offset `Jump instructions`_ -0x76 any if (int32_t)dst s>= (int32_t)imm goto +offset `Jump instructions`_ -0x77 any dst >>= imm `Arithmetic instructions`_ -0x79 0x00 dst = \*(uint64_t \*)(src + offset) `Load and store instructions`_ -0x7a any \*(uint64_t \*)(dst + offset) = imm `Load and store instructions`_ -0x7b 0x00 \*(uint64_t \*)(dst + offset) = src `Load and store instructions`_ -0x7c 0x00 dst = (uint32_t)(dst >> src) `Arithmetic instructions`_ -0x7d 0x00 if dst s>= src goto +offset `Jump instructions`_ -0x7e 0x00 if (int32_t)dst s>= (int32_t)src goto +offset `Jump instructions`_ -0x7f 0x00 dst >>= src `Arithmetic instructions`_ -0x84 0x00 dst = (uint32_t)-dst `Arithmetic instructions`_ -0x85 any call imm `Jump instructions`_ -0x87 0x00 dst = -dst `Arithmetic instructions`_ -0x94 any dst = (uint32_t)(dst % imm) `Arithmetic instructions`_ -0x95 0x00 return `Jump instructions`_ -0x97 any dst %= imm `Arithmetic instructions`_ -0x9c 0x00 dst = (uint32_t)(dst % src) `Arithmetic instructions`_ -0x9f 0x00 dst %= src `Arithmetic instructions`_ -0xa4 any dst = (uint32_t)(dst ^ imm) `Arithmetic instructions`_ -0xa5 any if dst < imm goto +offset `Jump instructions`_ -0xa6 any if (uint32_t)dst < imm goto +offset `Jump instructions`_ -0xa7 any dst ^= imm `Arithmetic instructions`_ -0xac 0x00 dst = (uint32_t)(dst ^ src) `Arithmetic instructions`_ -0xad 0x00 if dst < src goto +offset `Jump instructions`_ -0xae 0x00 if (uint32_t)dst < (uint32_t)src goto +offset `Jump instructions`_ -0xaf 0x00 dst ^= src `Arithmetic instructions`_ -0xb4 any dst = (uint32_t) imm `Arithmetic instructions`_ -0xb5 any if dst <= imm goto +offset `Jump instructions`_ -0xa6 any if (uint32_t)dst <= imm goto +offset `Jump instructions`_ -0xb7 any dst = imm `Arithmetic instructions`_ -0xbc 0x00 dst = (uint32_t) src `Arithmetic instructions`_ -0xbd 0x00 if dst <= src goto +offset `Jump instructions`_ -0xbe 0x00 if (uint32_t)dst <= (uint32_t)src goto +offset `Jump instructions`_ -0xbf 0x00 dst = src `Arithmetic instructions`_ -0xc3 0x00 lock \*(uint32_t \*)(dst + offset) += src `Atomic operations`_ -0xc3 0x01 lock:: `Atomic operations`_ - - *(uint32_t *)(dst + offset) += src - src = *(uint32_t *)(dst + offset) -0xc3 0x40 \*(uint32_t \*)(dst + offset) \|= src `Atomic operations`_ -0xc3 0x41 lock:: `Atomic operations`_ - - *(uint32_t *)(dst + offset) |= src - src = *(uint32_t *)(dst + offset) -0xc3 0x50 \*(uint32_t \*)(dst + offset) &= src `Atomic operations`_ -0xc3 0x51 lock:: `Atomic operations`_ - - *(uint32_t *)(dst + offset) &= src - src = *(uint32_t *)(dst + offset) -0xc3 0xa0 \*(uint32_t \*)(dst + offset) ^= src `Atomic operations`_ -0xc3 0xa1 lock:: `Atomic operations`_ - - *(uint32_t *)(dst + offset) ^= src - src = *(uint32_t *)(dst + offset) -0xc3 0xe1 lock:: `Atomic operations`_ - - temp = *(uint32_t *)(dst + offset) - *(uint32_t *)(dst + offset) = src - src = temp -0xc3 0xf1 lock:: `Atomic operations`_ - - temp = *(uint32_t *)(dst + offset) - if *(uint32_t)(dst + offset) == R0 - *(uint32_t)(dst + offset) = src - R0 = temp -0xc4 any dst = (uint32_t)(dst s>> imm) `Arithmetic instructions`_ -0xc5 any if dst s< imm goto +offset `Jump instructions`_ -0xc6 any if (int32_t)dst s< (int32_t)imm goto +offset `Jump instructions`_ -0xc7 any dst s>>= imm `Arithmetic instructions`_ -0xcc 0x00 dst = (uint32_t)(dst s>> src) `Arithmetic instructions`_ -0xcd 0x00 if dst s< src goto +offset `Jump instructions`_ -0xce 0x00 if (int32_t)dst s< (int32_t)src goto +offset `Jump instructions`_ -0xcf 0x00 dst s>>= src `Arithmetic instructions`_ -0xd4 0x10 dst = htole16(dst) `Byte swap instructions`_ -0xd4 0x20 dst = htole32(dst) `Byte swap instructions`_ -0xd4 0x40 dst = htole64(dst) `Byte swap instructions`_ -0xd5 any if dst s<= imm goto +offset `Jump instructions`_ -0xd6 any if (int32_t)dst s<= (int32_t)imm goto +offset `Jump instructions`_ -0xc3 0x00 lock \*(uint64_t \*)(dst + offset) += src `Atomic operations`_ -0xdb 0x01 lock:: `Atomic operations`_ - - *(uint64_t *)(dst + offset) += src - src = *(uint64_t *)(dst + offset) -0xdb 0x40 \*(uint64_t \*)(dst + offset) \|= src `Atomic operations`_ -0xdb 0x41 lock:: `Atomic operations`_ - - *(uint64_t *)(dst + offset) |= src - lock src = *(uint64_t *)(dst + offset) -0xdb 0x50 \*(uint64_t \*)(dst + offset) &= src `Atomic operations`_ -0xdb 0x51 lock:: `Atomic operations`_ - - *(uint64_t *)(dst + offset) &= src - src = *(uint64_t *)(dst + offset) -0xdb 0xa0 \*(uint64_t \*)(dst + offset) ^= src `Atomic operations`_ -0xdb 0xa1 lock:: `Atomic operations`_ - - *(uint64_t *)(dst + offset) ^= src - src = *(uint64_t *)(dst + offset) -0xdb 0xe1 lock:: `Atomic operations`_ - - temp = *(uint64_t *)(dst + offset) - *(uint64_t *)(dst + offset) = src - src = temp -0xdb 0xf1 lock:: `Atomic operations`_ - - temp = *(uint64_t *)(dst + offset) - if *(uint64_t)(dst + offset) == R0 - *(uint64_t)(dst + offset) = src - R0 = temp -0xdc 0x10 dst = htobe16(dst) `Byte swap instructions`_ -0xdc 0x20 dst = htobe32(dst) `Byte swap instructions`_ -0xdc 0x40 dst = htobe64(dst) `Byte swap instructions`_ -0xdd 0x00 if dst s<= src goto +offset `Jump instructions`_ -0xde 0x00 if (int32_t)dst s<= (int32_t)src goto +offset `Jump instructions`_ -====== ==== =================================================== ============= +====== ==== ==== =================================================== ======================================== +opcode imm src description reference +====== ==== ==== =================================================== ======================================== +0x00 any 0x00 (additional immediate value) `64-bit immediate instructions`_ +0x04 any 0x00 dst = (uint32_t)(dst + imm) `Arithmetic instructions`_ +0x05 0x00 0x00 goto +offset `Jump instructions`_ +0x07 any 0x00 dst += imm `Arithmetic instructions`_ +0x0c 0x00 any dst = (uint32_t)(dst + src) `Arithmetic instructions`_ +0x0f 0x00 any dst += src `Arithmetic instructions`_ +0x14 any 0x00 dst = (uint32_t)(dst - imm) `Arithmetic instructions`_ +0x15 any 0x00 if dst == imm goto +offset `Jump instructions`_ +0x16 any 0x00 if (uint32_t)dst == imm goto +offset `Jump instructions`_ +0x17 any 0x00 dst -= imm `Arithmetic instructions`_ +0x18 0x00 0x00 dst = imm64 `64-bit immediate instructions`_ +0x18 0x00 0x01 dst = map_by_fd(imm) `64-bit immediate instructions`_ +0x18 0x00 0x02 dst = mva(map_by_fd(imm)) + next_imm `64-bit immediate instructions`_ +0x18 0x00 0x03 dst = variable_addr(imm) `64-bit immediate instructions`_ +0x18 0x00 0x04 dst = code_addr(imm) `64-bit immediate instructions`_ +0x18 0x00 0x05 dst = mva(map_by_idx(imm)) `64-bit immediate instructions`_ +0x18 0x00 0x06 dst = mva(map_by_idx(imm)) + next_imm `64-bit immediate instructions`_ +0x1c 0x00 any dst = (uint32_t)(dst - src) `Arithmetic instructions`_ +0x1d 0x00 any if dst == src goto +offset `Jump instructions`_ +0x1e 0x00 any if (uint32_t)dst == (uint32_t)src goto +offset `Jump instructions`_ +0x1f 0x00 any dst -= src `Arithmetic instructions`_ +0x20 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x24 any 0x00 dst = (uint32_t)(dst \* imm) `Arithmetic instructions`_ +0x25 any 0x00 if dst > imm goto +offset `Jump instructions`_ +0x26 any 0x00 if (uint32_t)dst > imm goto +offset `Jump instructions`_ +0x27 any 0x00 dst \*= imm `Arithmetic instructions`_ +0x28 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x2c 0x00 any dst = (uint32_t)(dst \* src) `Arithmetic instructions`_ +0x2d 0x00 any if dst > src goto +offset `Jump instructions`_ +0x2e 0x00 any if (uint32_t)dst > (uint32_t)src goto +offset `Jump instructions`_ +0x2f 0x00 any dst \*= src `Arithmetic instructions`_ +0x30 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x34 any 0x00 dst = (uint32_t)((imm != 0) ? (dst / imm) : 0) `Arithmetic instructions`_ +0x35 any 0x00 if dst >= imm goto +offset `Jump instructions`_ +0x36 any 0x00 if (uint32_t)dst >= imm goto +offset `Jump instructions`_ +0x37 any 0x00 dst = (imm != 0) ? (dst / imm) : 0 `Arithmetic instructions`_ +0x38 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x3c 0x00 any dst = (uint32_t)((imm != 0) ? (dst / src) : 0) `Arithmetic instructions`_ +0x3d 0x00 any if dst >= src goto +offset `Jump instructions`_ +0x3e 0x00 any if (uint32_t)dst >= (uint32_t)src goto +offset `Jump instructions`_ +0x3f 0x00 any dst = (src !+ 0) ? (dst / src) : 0 `Arithmetic instructions`_ +0x40 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x44 any 0x00 dst = (uint32_t)(dst \| imm) `Arithmetic instructions`_ +0x45 any 0x00 if dst & imm goto +offset `Jump instructions`_ +0x46 any 0x00 if (uint32_t)dst & imm goto +offset `Jump instructions`_ +0x47 any 0x00 dst \|= imm `Arithmetic instructions`_ +0x48 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x4c 0x00 any dst = (uint32_t)(dst \| src) `Arithmetic instructions`_ +0x4d 0x00 any if dst & src goto +offset `Jump instructions`_ +0x4e 0x00 any if (uint32_t)dst & (uint32_t)src goto +offset `Jump instructions`_ +0x4f 0x00 any dst \|= src `Arithmetic instructions`_ +0x50 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x54 any 0x00 dst = (uint32_t)(dst & imm) `Arithmetic instructions`_ +0x55 any 0x00 if dst != imm goto +offset `Jump instructions`_ +0x56 any 0x00 if (uint32_t)dst != imm goto +offset `Jump instructions`_ +0x57 any 0x00 dst &= imm `Arithmetic instructions`_ +0x58 any any (deprecated, implementation-specific) `Legacy BPF Packet access instructions`_ +0x5c 0x00 any dst = (uint32_t)(dst & src) `Arithmetic instructions`_ +0x5d 0x00 any if dst != src goto +offset `Jump instructions`_ +0x5e 0x00 any if (uint32_t)dst != (uint32_t)src goto +offset `Jump instructions`_ +0x5f 0x00 any dst &= src `Arithmetic instructions`_ +0x61 0x00 any dst = \*(uint32_t \*)(src + offset) `Load and store instructions`_ +0x62 any 0x00 \*(uint32_t \*)(dst + offset) = imm `Load and store instructions`_ +0x63 0x00 any \*(uint32_t \*)(dst + offset) = src `Load and store instructions`_ +0x64 any 0x00 dst = (uint32_t)(dst << imm) `Arithmetic instructions`_ +0x65 any 0x00 if dst s> imm goto +offset `Jump instructions`_ +0x66 any 0x00 if (int32_t)dst s> (int32_t)imm goto +offset `Jump instructions`_ +0x67 any 0x00 dst <<= imm `Arithmetic instructions`_ +0x69 0x00 any dst = \*(uint16_t \*)(src + offset) `Load and store instructions`_ +0x6a any 0x00 \*(uint16_t \*)(dst + offset) = imm `Load and store instructions`_ +0x6b 0x00 any \*(uint16_t \*)(dst + offset) = src `Load and store instructions`_ +0x6c 0x00 any dst = (uint32_t)(dst << src) `Arithmetic instructions`_ +0x6d 0x00 any if dst s> src goto +offset `Jump instructions`_ +0x6e 0x00 any if (int32_t)dst s> (int32_t)src goto +offset `Jump instructions`_ +0x6f 0x00 any dst <<= src `Arithmetic instructions`_ +0x71 0x00 any dst = \*(uint8_t \*)(src + offset) `Load and store instructions`_ +0x72 any 0x00 \*(uint8_t \*)(dst + offset) = imm `Load and store instructions`_ +0x73 0x00 any \*(uint8_t \*)(dst + offset) = src `Load and store instructions`_ +0x74 any 0x00 dst = (uint32_t)(dst >> imm) `Arithmetic instructions`_ +0x75 any 0x00 if dst s>= imm goto +offset `Jump instructions`_ +0x76 any 0x00 if (int32_t)dst s>= (int32_t)imm goto +offset `Jump instructions`_ +0x77 any 0x00 dst >>= imm `Arithmetic instructions`_ +0x79 0x00 any dst = \*(uint64_t \*)(src + offset) `Load and store instructions`_ +0x7a any 0x00 \*(uint64_t \*)(dst + offset) = imm `Load and store instructions`_ +0x7b 0x00 any \*(uint64_t \*)(dst + offset) = src `Load and store instructions`_ +0x7c 0x00 any dst = (uint32_t)(dst >> src) `Arithmetic instructions`_ +0x7d 0x00 any if dst s>= src goto +offset `Jump instructions`_ +0x7e 0x00 any if (int32_t)dst s>= (int32_t)src goto +offset `Jump instructions`_ +0x7f 0x00 any dst >>= src `Arithmetic instructions`_ +0x84 0x00 0x00 dst = (uint32_t)-dst `Arithmetic instructions`_ +0x85 any 0x00 call imm `Jump instructions`_ +0x87 0x00 0x00 dst = -dst `Arithmetic instructions`_ +0x94 any 0x00 dst = (uint32_t)((imm != 0) ? (dst % imm) : imm) `Arithmetic instructions`_ +0x95 0x00 0x00 return `Jump instructions`_ +0x97 any 0x00 dst = (imm != 0) ? (dst % imm) : imm `Arithmetic instructions`_ +0x9c 0x00 any dst = (uint32_t)((src != 0) ? (dst % src) : src) `Arithmetic instructions`_ +0x9f 0x00 any dst = (src != 0) ? (dst % src) : src `Arithmetic instructions`_ +0xa4 any 0x00 dst = (uint32_t)(dst ^ imm) `Arithmetic instructions`_ +0xa5 any 0x00 if dst < imm goto +offset `Jump instructions`_ +0xa6 any 0x00 if (uint32_t)dst < imm goto +offset `Jump instructions`_ +0xa7 any 0x00 dst ^= imm `Arithmetic instructions`_ +0xac 0x00 any dst = (uint32_t)(dst ^ src) `Arithmetic instructions`_ +0xad 0x00 any if dst < src goto +offset `Jump instructions`_ +0xae 0x00 any if (uint32_t)dst < (uint32_t)src goto +offset `Jump instructions`_ +0xaf 0x00 any dst ^= src `Arithmetic instructions`_ +0xb4 any 0x00 dst = (uint32_t) imm `Arithmetic instructions`_ +0xb5 any 0x00 if dst <= imm goto +offset `Jump instructions`_ +0xa6 any 0x00 if (uint32_t)dst <= imm goto +offset `Jump instructions`_ +0xb7 any 0x00 dst = imm `Arithmetic instructions`_ +0xbc 0x00 any dst = (uint32_t) src `Arithmetic instructions`_ +0xbd 0x00 any if dst <= src goto +offset `Jump instructions`_ +0xbe 0x00 any if (uint32_t)dst <= (uint32_t)src goto +offset `Jump instructions`_ +0xbf 0x00 any dst = src `Arithmetic instructions`_ +0xc3 0x00 any lock \*(uint32_t \*)(dst + offset) += src `Atomic operations`_ +0xc3 0x01 any lock:: `Atomic operations`_ + + *(uint32_t *)(dst + offset) += src + src = *(uint32_t *)(dst + offset) +0xc3 0x40 any \*(uint32_t \*)(dst + offset) \|= src `Atomic operations`_ +0xc3 0x41 any lock:: `Atomic operations`_ + + *(uint32_t *)(dst + offset) |= src + src = *(uint32_t *)(dst + offset) +0xc3 0x50 any \*(uint32_t \*)(dst + offset) &= src `Atomic operations`_ +0xc3 0x51 any lock:: `Atomic operations`_ + + *(uint32_t *)(dst + offset) &= src + src = *(uint32_t *)(dst + offset) +0xc3 0xa0 any \*(uint32_t \*)(dst + offset) ^= src `Atomic operations`_ +0xc3 0xa1 any lock:: `Atomic operations`_ + + *(uint32_t *)(dst + offset) ^= src + src = *(uint32_t *)(dst + offset) +0xc3 0xe1 any lock:: `Atomic operations`_ + + temp = *(uint32_t *)(dst + offset) + *(uint32_t *)(dst + offset) = src + src = temp +0xc3 0xf1 any lock:: `Atomic operations`_ + + temp = *(uint32_t *)(dst + offset) + if *(uint32_t)(dst + offset) == R0 + *(uint32_t)(dst + offset) = src + R0 = temp +0xc4 any 0x00 dst = (uint32_t)(dst s>> imm) `Arithmetic instructions`_ +0xc5 any 0x00 if dst s< imm goto +offset `Jump instructions`_ +0xc6 any 0x00 if (int32_t)dst s< (int32_t)imm goto +offset `Jump instructions`_ +0xc7 any 0x00 dst s>>= imm `Arithmetic instructions`_ +0xcc 0x00 any dst = (uint32_t)(dst s>> src) `Arithmetic instructions`_ +0xcd 0x00 any if dst s< src goto +offset `Jump instructions`_ +0xce 0x00 any if (int32_t)dst s< (int32_t)src goto +offset `Jump instructions`_ +0xcf 0x00 any dst s>>= src `Arithmetic instructions`_ +0xd4 0x10 0x00 dst = htole16(dst) `Byte swap instructions`_ +0xd4 0x20 0x00 dst = htole32(dst) `Byte swap instructions`_ +0xd4 0x40 0x00 dst = htole64(dst) `Byte swap instructions`_ +0xd5 any 0x00 if dst s<= imm goto +offset `Jump instructions`_ +0xd6 any 0x00 if (int32_t)dst s<= (int32_t)imm goto +offset `Jump instructions`_ +0xdb 0x00 any lock \*(uint64_t \*)(dst + offset) += src `Atomic operations`_ +0xdb 0x01 any lock:: `Atomic operations`_ + + *(uint64_t *)(dst + offset) += src + src = *(uint64_t *)(dst + offset) +0xdb 0x40 any \*(uint64_t \*)(dst + offset) \|= src `Atomic operations`_ +0xdb 0x41 any lock:: `Atomic operations`_ + + *(uint64_t *)(dst + offset) |= src + lock src = *(uint64_t *)(dst + offset) +0xdb 0x50 any \*(uint64_t \*)(dst + offset) &= src `Atomic operations`_ +0xdb 0x51 any lock:: `Atomic operations`_ + + *(uint64_t *)(dst + offset) &= src + src = *(uint64_t *)(dst + offset) +0xdb 0xa0 any \*(uint64_t \*)(dst + offset) ^= src `Atomic operations`_ +0xdb 0xa1 any lock:: `Atomic operations`_ + + *(uint64_t *)(dst + offset) ^= src + src = *(uint64_t *)(dst + offset) +0xdb 0xe1 any lock:: `Atomic operations`_ + + temp = *(uint64_t *)(dst + offset) + *(uint64_t *)(dst + offset) = src + src = temp +0xdb 0xf1 any lock:: `Atomic operations`_ + + temp = *(uint64_t *)(dst + offset) + if *(uint64_t)(dst + offset) == R0 + *(uint64_t)(dst + offset) = src + R0 = temp +0xdc 0x10 0x00 dst = htobe16(dst) `Byte swap instructions`_ +0xdc 0x20 0x00 dst = htobe32(dst) `Byte swap instructions`_ +0xdc 0x40 0x00 dst = htobe64(dst) `Byte swap instructions`_ +0xdd 0x00 any if dst s<= src goto +offset `Jump instructions`_ +0xde 0x00 any if (int32_t)dst s<= (int32_t)src goto +offset `Jump instructions`_ +====== ==== ==== =================================================== ======================================== diff --git a/isa/kernel.org/linux-historical-notes.rst b/isa/kernel.org/linux-historical-notes.rst new file mode 100644 index 0000000..c0362df --- /dev/null +++ b/isa/kernel.org/linux-historical-notes.rst @@ -0,0 +1,63 @@ +.. contents:: +.. sectnum:: + +===================== +Linux historial notes +===================== + +Legacy BPF Packet access instructions +===================================== + +As mentioned in the `ISA standard documentation `_, +Linux has special eBPF instructions for access to packet data that have been +carried over from classic BPF to retain the performance of legacy socket +filters running in the eBPF interpreter. + +The instructions come in two forms: ``BPF_ABS | | BPF_LD`` and +``BPF_IND | | BPF_LD``. + +These instructions are used to access packet data and can only be used when +the program context is a pointer to a networking packet. ``BPF_ABS`` +accesses packet data at an absolute offset specified by the immediate data +and ``BPF_IND`` access packet data at an offset that includes the value of +a register in addition to the immediate data. + +These instructions have seven implicit operands: + +* Register R6 is an implicit input that must contain a pointer to a + struct sk_buff. +* Register R0 is an implicit output which contains the data fetched from + the packet. +* Registers R1-R5 are scratch registers that are clobbered by the + instruction. + +These instructions have an implicit program exit condition as well. If an +eBPF program attempts access data beyond the packet boundary, the +program execution will be aborted. + +``BPF_ABS | BPF_W | BPF_LD`` (0x20) means:: + + R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + imm)) + +where ``ntohl()`` converts a 32-bit value from network byte order to host byte order. + +``BPF_IND | BPF_W | BPF_LD`` (0x40) means:: + + R0 = ntohl(*(u32 *) ((struct sk_buff *) R6->data + src + imm)) + +Appendix +======== + +For reference, the following table lists legacy Linux-specific opcodes in order by value. + +====== ==== =================================================== ============= +opcode imm description reference +====== ==== =================================================== ============= +0x20 any dst = ntohl(\*(uint32_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ +0x28 any dst = ntohs(\*(uint16_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ +0x30 any dst = (\*(uint8_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ +0x38 any dst = ntohll(\*(uint64_t \*)(R6->data + imm)) `Legacy BPF Packet access instructions`_ +0x40 any dst = ntohl(\*(uint32_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ +0x48 any dst = ntohs(\*(uint16_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ +0x50 any dst = \*(uint8_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_ +0x58 any dst = ntohll(\*(uint64_t \*)(R6->data + src + imm)) `Legacy BPF Packet access instructions`_