-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eBPF.md: Add missing instructions and instruction variants (32-bit jumps, atomic instructions, call and lddw variants) #26
base: master
Are you sure you want to change the base?
Conversation
Now we also want atomic operations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no
The jump-32bit instruction class added support for jumps with 32-bit operands. This is supported in the kernel since commit: d405c7407a54 ("bpf: allocate 0x06 to new eBPF instruction class JMP32")
I updated this PR with more instructions and variants (Cc @dthaler). |
The "load immediate" instruction can have a specific meaning for some values of the source register. If it is set to BPF_PSEUDO_MAP_FD (1), then the verifier considers the immediate as a file descriptor to a map, and replaces by a pointer accordingly. This is supported in the kernel since commit: 0246e64d9a5f ("bpf: handle pseudo BPF_LD_IMM64 insn")
In addition to BPF_PSEUDO_MAP (1), the source register of a "load immediate" instruction can be set to BPF_PSEUDO_MAP_VALUE (2). In that case, the verifier expects: a map file descriptor in the immediate field of the first half of the 128-bit instruction, and an offset in the immediate field of the second half of the instruction (remember that lddw spans over two regular instruction fields, 16 bytes in total). It uses this offset to load an address residing in the value of the first entry of the map referended by the file descriptor, at the provided offset within that value. Currently, only single-entry array maps are supported. Maps with multiple entries might be supported in the future by using the offset fields as indices within the map. This is supported in the kernel since commit: d8eca5bbb2be ("bpf: implement lookup-free direct value access for maps")
When the source register of a "load immediate" instruction is set to 3, then the verifier considers the immediate as a BTF id to a kernel variable, and replaces it by the relevant pointer. This is supported in the kernel since commit: 4976b718c355 ("bpf: Introduce pseudo_btf_id")
When the source register of a "load immediate" instruction is set to 4, the verifier considers the immediate value as an instruction offset for a BPF function in the program. Once loaded into the destination register, this function can be passed to the bpf_for_each_map_elem() helper function and used as a callback. This is supported in the kernel since commit: 69c087ba6225 ("bpf: Add bpf_for_each_map_elem() helper")
7fb75a9
to
9e28eff
Compare
In addition to BPF_PSEUDO_MAP (1) and BPF_PSEUDO_MAP_VALUE (2), the source register of a "load immediate" instruction can have other map-related values: - When set to BPF_PSEUDO_MAP_IDX (5), the verifier expects a map index (not a file descriptor) as the immediate, and replaces it with a pointer to the related map. - When set to BPF_PSEUDO_MAP_VALUE_IDX (6), the verifier behaves like for BPF_PSEUDO_MAP_VALUE, except that it expects a map index instead of a file descriptor. Both values are supported in the kernel since commit: 387544bfa291 ("bpf: Introduce fd_idx")
By default, the call instruction calls into a helper function, one of the specific functions in the kernel that have been created for BPF programs. When the source register of a call instruction is set to BPF_PSEUDO_CALL (1), the call refers to a BPF function instead, for which the offset is passed in the immediate field. This is supported in the kernel since commit: cc8b0b92a169 ("bpf: introduce function calls (function boundaries)")
When the source register of a call instruction is set to BPF_PSEUDO_KFUNC_CALL (2), then the call refers to a kernel function. This is different from a helper function, in that the function is not specific to BPF programs (but it must be explicitly marked as call-able from BPF programs). This is supported in the kernel since commit: e6ac2450d6de ("bpf: Support bpf program calling kernel function")
Atomic add instructions have been available since the early days of eBPF, although BPF_XADD has later been renamed into BPF_ATOMIC. Comes in 32 and 64 bits flavours. This is supported in the kernel since commit: bd4cf0ed331a ("net: filter: rework/optimize internal BPF interpreter's instruction set")
Atomic fetch add instructions are a variant of the "atomic" instructions, when BPF_FETCH (1) and BPF_ADD (0) are added to the immediate field. This is supported in the kernel since commit: 5ca419f2864a ("bpf: Add BPF_FETCH field / create atomic_fetch_add instruction")
Atomic exchange and atomic compare-and-write are selected when the immediate value for an atomic operation is set to BPF_XCHG (0xe0) | BPF_FETCH (1) and BPF_CMPXCHG (0xf0) | BPF_FETCH (1), respectively. This is supported in the kernel since commit: 5ffa25502b5a ("bpf: Add instructions for atomic_[cmp]xchg")
The instructions are selected when the immediate field of an atomic instruction is set to BPF_OR (0x40), BPF_AND (0x50), or BPF_XOR (0xa0), instead of BPF_ADD (0), and can possibly get the BPF_FETCH (1) flag as well. This is supported in the kernel since commit: 981f94c3e921 ("bpf: Add bitwise atomic instructions")
9e28eff
to
1df94e1
Compare
0xcd | jslt dst, src, +off | PC += off if dst < src (signed) | ||
0xd5 | jsle dst, imm, +off | PC += off if dst <= imm (signed) | ||
0xdd | jsle dst, src, +off | PC += off if dst <= src (signed) | ||
0x85 (src = 0) | call imm | Helper function call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we get different mnemonics for each of the call variants?
In bpf_conformance I was proposing:
call [modifier] imm
Where [modifier] is optional and can be one of:
helper -> src = 0
local -> src = 1
runtime -> src = 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback! I don't mind much either way, but let's see what syntax makes it to the Linux docs if the table gets updated, maybe? This PR has been sitting for nearly four years and I updated mostly to help Dave with the eBPF specs, at this point I doubt it will ever get merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's awesome. I didn't realize there was an official set of mnemonics as LLVM and GNU bintools seem to have wildly different disassembly outputs.
I just want to make sure the bpf_conformance tool has the "correct" ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's anything official, but I know @dthaler intended to have the table merged to the kernel docs (Alexei pushed back initially, at least from having them in the official spec - Not sure where things are right now, I haven't been able to follow over the last weeks). If this happens, it would probably make the document in the current repo irrelevant.
Reflecting the recent addition of 32-bit jump instruction class support
to the Linux kernel [0], add the related instructions to the unofficial
spec to keep it up-to-date.
[0] merge commit ae575c8a9868 ("Merge branch 'jmp32-insns'")
Cc: @JiongWang