]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commit
bpf: Add instructions for atomic_[cmp]xchg
authorBrendan Jackman <jackmanb@google.com>
Thu, 14 Jan 2021 18:17:47 +0000 (18:17 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 15 Jan 2021 02:34:29 +0000 (18:34 -0800)
commit5ffa25502b5ab3d639829a2d1e316cff7f59a41e
treeb3ae91f0bdbcbad21f09cd5ed54b39ee7942c79f
parent5ca419f2864a2c60940dcf4bbaeb69546200e36f
bpf: Add instructions for atomic_[cmp]xchg

This adds two atomic opcodes, both of which include the BPF_FETCH
flag. XCHG without the BPF_FETCH flag would naturally encode
atomic_set. This is not supported because it would be of limited
value to userspace (it doesn't imply any barriers). CMPXCHG without
BPF_FETCH woulud be an atomic compare-and-write. We don't have such
an operation in the kernel so it isn't provided to BPF either.

There are two significant design decisions made for the CMPXCHG
instruction:

 - To solve the issue that this operation fundamentally has 3
   operands, but we only have two register fields. Therefore the
   operand we compare against (the kernel's API calls it 'old') is
   hard-coded to be R0. x86 has similar design (and A64 doesn't
   have this problem).

   A potential alternative might be to encode the other operand's
   register number in the immediate field.

 - The kernel's atomic_cmpxchg returns the old value, while the C11
   userspace APIs return a boolean indicating the comparison
   result. Which should BPF do? A64 returns the old value. x86 returns
   the old value in the hard-coded register (and also sets a
   flag). That means return-old-value is easier to JIT, so that's
   what we use.

Signed-off-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20210114181751.768687-8-jackmanb@google.com
arch/x86/net/bpf_jit_comp.c
include/linux/filter.h
include/uapi/linux/bpf.h
kernel/bpf/core.c
kernel/bpf/disasm.c
kernel/bpf/verifier.c
tools/include/linux/filter.h
tools/include/uapi/linux/bpf.h