summaryrefslogtreecommitdiff
path: root/arch/powerpc/net/bpf_jit_comp32.c
diff options
context:
space:
mode:
authorNeil Armstrong <neil.armstrong@linaro.org>2024-06-06 11:19:47 +0200
committerNeil Armstrong <neil.armstrong@linaro.org>2024-06-06 11:19:47 +0200
commit4c607a73300b756ad1c8001abcfe37bf53b5a5f1 (patch)
tree81b36e4b324925478fe58ddd3cebfd78e1428d11 /arch/powerpc/net/bpf_jit_comp32.c
parent1d1239a1b0e502faffe43b97d530232285b9f061 (diff)
parent5bbe5872fed4497a192556426d75fd9223c5bfeb (diff)
Merge branch 'dt' of https://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm into v6.11/arm64-dt
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Diffstat (limited to 'arch/powerpc/net/bpf_jit_comp32.c')
-rw-r--r--arch/powerpc/net/bpf_jit_comp32.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 43b97032a91c..a0c4f1bde83e 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -900,6 +900,15 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
/* Get offset into TMP_REG */
EMIT(PPC_RAW_LI(tmp_reg, off));
+ /*
+ * Enforce full ordering for operations with BPF_FETCH by emitting a 'sync'
+ * before and after the operation.
+ *
+ * This is a requirement in the Linux Kernel Memory Model.
+ * See __cmpxchg_u32() in asm/cmpxchg.h as an example.
+ */
+ if ((imm & BPF_FETCH) && IS_ENABLED(CONFIG_SMP))
+ EMIT(PPC_RAW_SYNC());
tmp_idx = ctx->idx * 4;
/* load value from memory into r0 */
EMIT(PPC_RAW_LWARX(_R0, tmp_reg, dst_reg, 0));
@@ -953,6 +962,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
/* For the BPF_FETCH variant, get old data into src_reg */
if (imm & BPF_FETCH) {
+ /* Emit 'sync' to enforce full ordering */
+ if (IS_ENABLED(CONFIG_SMP))
+ EMIT(PPC_RAW_SYNC());
EMIT(PPC_RAW_MR(ret_reg, ax_reg));
if (!fp->aux->verifier_zext)
EMIT(PPC_RAW_LI(ret_reg - 1, 0)); /* higher 32-bit */