mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
bpf, riscv: Add and use bpf_atomic_is_load_acq() helper
A load-acquire is the only BPF_STX class instruction that reads from src_reg into dst_reg, that is, it has the operand roles of a BPF_LDX. JIT code which tells loads from stores apart by instruction class alone has to special case it, for example when deciding which register holds the faulting address and which one to clear from an exception handler. riscv64 already does so, open coded as a bare insn->imm test. Add a bpf_atomic_is_load_acq() helper and convert riscv64 over to it, so that the x86-64 and arm64 JITs can use the same helper in subsequent patches. Unlike bpf_atomic_is_load_store(), which presumes that its argument is already known to be a BPF_ATOMIC instruction, the new helper is called from code which still sees all instruction classes, so it checks class and mode itself. Also, move bpf_atomic_is_load_store() to filter.h next to BPF_ATOMIC_OP, so that both helpers stay together. No functional change intended. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20260806201047.333389-2-daniel@iogearbox.net Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
parent
7db0a00445
commit
e2577cd620
|
|
@ -1994,7 +1994,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||
/* ret can be 1 (skip-zext); extable entry still needs to be added */
|
||||
if (ret >= 0)
|
||||
ret = add_exception_handler(insn,
|
||||
insn->imm == BPF_LOAD_ACQ ? rd : REG_DONT_CLEAR_MARKER,
|
||||
bpf_atomic_is_load_acq(insn) ? rd : REG_DONT_CLEAR_MARKER,
|
||||
ctx) ?: ret;
|
||||
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -1132,21 +1132,6 @@ static inline bool bpf_pseudo_func(const struct bpf_insn *insn)
|
|||
return bpf_is_ldimm64(insn) && insn->src_reg == BPF_PSEUDO_FUNC;
|
||||
}
|
||||
|
||||
/* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
|
||||
* atomic load or store, and false if it is a read-modify-write instruction.
|
||||
*/
|
||||
static inline bool
|
||||
bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
|
||||
{
|
||||
switch (atomic_insn->imm) {
|
||||
case BPF_LOAD_ACQ:
|
||||
case BPF_STORE_REL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct bpf_prog_ops {
|
||||
int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
|
||||
union bpf_attr __user *uattr);
|
||||
|
|
|
|||
|
|
@ -383,6 +383,37 @@ static inline bool insn_is_cast_user(const struct bpf_insn *insn)
|
|||
/* Legacy alias */
|
||||
#define BPF_STX_XADD(SIZE, DST, SRC, OFF) BPF_ATOMIC_OP(SIZE, BPF_ADD, DST, SRC, OFF)
|
||||
|
||||
/*
|
||||
* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
|
||||
* atomic load or store, and false if it is a read-modify-write instruction.
|
||||
*/
|
||||
static inline bool
|
||||
bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
|
||||
{
|
||||
switch (atomic_insn->imm) {
|
||||
case BPF_LOAD_ACQ:
|
||||
case BPF_STORE_REL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A load-acquire is the only BPF_STX class instruction that reads into
|
||||
* dst_reg from src_reg + off16, i.e. it has the operand roles of a BPF_LDX.
|
||||
* Unlike bpf_atomic_is_load_store(), @insn is not assumed to be a BPF_ATOMIC
|
||||
* instruction here, so that callers which walk all instruction classes can
|
||||
* use this directly.
|
||||
*/
|
||||
static inline bool bpf_atomic_is_load_acq(const struct bpf_insn *insn)
|
||||
{
|
||||
return BPF_CLASS(insn->code) == BPF_STX &&
|
||||
(BPF_MODE(insn->code) == BPF_ATOMIC ||
|
||||
BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) &&
|
||||
insn->imm == BPF_LOAD_ACQ;
|
||||
}
|
||||
|
||||
/* Memory store, *(uint *) (dst_reg + off16) = imm32 */
|
||||
|
||||
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user