Per the Linux Kernel Memory Model, value-returning atomic RMW instructions
imply a full barrier. On LoongArch the plain amswap.{w,d} variants do not
provide that ordering; emit amswap_db.{w,d} for BPF_XCHG instead so scalar
atomic exchanges remain sequentially consistent regardless of kptr inlining.

Signed-off-by: Chenguang Zhao <[email protected]>
---
 arch/loongarch/include/asm/inst.h | 2 ++
 arch/loongarch/net/bpf_jit.c      | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/include/asm/inst.h 
b/arch/loongarch/include/asm/inst.h
index 76b723590023..636cfc524b02 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -783,6 +783,8 @@ DEF_EMIT_REG3_FORMAT(amswapb, amswapb_op)
 DEF_EMIT_REG3_FORMAT(amswaph, amswaph_op)
 DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op)
 DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op)
+DEF_EMIT_REG3_FORMAT(amswapdbw, amswapdbw_op)
+DEF_EMIT_REG3_FORMAT(amswapdbd, amswapdbd_op)
 
 #define DEF_EMIT_REG3SA2_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 24913dc7f4e8..f071d913e054 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -482,11 +482,11 @@ static int emit_atomic_rmw(const struct bpf_insn *insn, 
struct jit_ctx *ctx)
                        emit_zext_32(ctx, src, true);
                        break;
                case BPF_W:
-                       emit_insn(ctx, amswapw, src, t1, t3);
+                       emit_insn(ctx, amswapdbw, src, t1, t3);
                        emit_zext_32(ctx, src, true);
                        break;
                case BPF_DW:
-                       emit_insn(ctx, amswapd, src, t1, t3);
+                       emit_insn(ctx, amswapdbd, src, t1, t3);
                        break;
                }
                break;
-- 
2.25.1


Reply via email to