Received: by 2002:ab2:6a05:0:b0:1f8:1780:a4ed with SMTP id w5csp1935985lqo; Mon, 13 May 2024 03:03:36 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCX5NjMeF0iGYEYCM9Zh9sC8/zjk7Swccs16BXskW+gmtWclxHagf86An7tpsybI4H73QZMk2iYN095Lee+1p4FVuMz8YhlfFG1tjUtlfA== X-Google-Smtp-Source: AGHT+IF4Q4zZ6Y1O2FNuz2ZHBijiL6soE3t6MnhxV11kjqrRtP12dpcvn6vNcc8N/LGqSsvUbUzs X-Received: by 2002:a05:6808:aa7:b0:3c9:5e56:b01e with SMTP id 5614622812f47-3c9970b148fmr10241859b6e.40.1715594616050; Mon, 13 May 2024 03:03:36 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715594616; cv=pass; d=google.com; s=arc-20160816; b=cyYyIZfUodFJGwbKCX2jNtHioZXaSRn22vxmD2vN71ZLBONrflJFlGa+IrR450BNqv 1t6ToNLrzexpDQ5MzzIrkDKL1xwW7dcT+mGWaPU05ypacCfj+zlabK3ddKh/yjNFLpo+ Mnc2hfiogvYxfIeCSyW4qNy1x36W2+D602GuAPgsJ1ZCmBWIKG4j4aazlCfquX0A50lC 1AHe9B9wRjgLZeaOCJePQjaTnFM9H3u1t/ib3C8Lko4jg183oFd8ZXCVjLLRKO8fJ1PH ZY8SEEWprb0z0ns9Yp4Lk7Hp9+Cl/FhlamcpijJL1aWPyLe+812mFHiEJ3ZDPDG2U+Tv my+w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from:dkim-signature; bh=5Sk933tArnQzcyLE6LCZm0h+nuIFUQOz/szGZkb9jlw=; fh=jcJ+JrUbA0gSXjnL3anU4K+TKbucWuDM46jQSV9be8Y=; b=CautB0fwp+VsA1iR+XWqz8LQ+q4rT0I5Wk8IFSf+GyboIhVefe6YlLo8c+yWyPMFVi tX1GQSsFhaQTD3Lt2w+rYfUg9dsOVE5SLEiipGfbl8Ux9YYlJfYopnfrRUvw/O4MNBOj zHRo7+jFy6k4O4wEqK7JtXcfAKPRblALoqbP9Es5zDYZpcwyqpESr/+FF/OEGsmlHt5J M2BmZeX6iR0xYc5s68Ci525tqBgJTvZbnng+nLYbQpHPPly6fJ/ULfKCQ4bNeu7yslfe kxFPfoTwBqP32fNr/NdLk2nF0WNZa3uhKkX0AZbCopf6ImBqHvPFw4XKZwuOtzJVaHCB 613g==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=iXWewXdz; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-177437-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-177437-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id 6a1803df08f44-6a15f306064si92800116d6.586.2024.05.13.03.03.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 May 2024 03:03:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-177437-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=iXWewXdz; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-177437-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-177437-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id B1DAF1C21836 for ; Mon, 13 May 2024 10:03:35 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 99B8E149DE0; Mon, 13 May 2024 10:03:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iXWewXdz" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AEE60148FE3; Mon, 13 May 2024 10:03:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715594605; cv=none; b=eJUpTHw1oQb5cca5m7TrQmYSkMBqWzkiUJ9s4QAAA/4CPWbXtctXXGl/me3QDF1WsZHrgtMjBBNerS2nbVjHTO29mBl4nTcS3DZBCIq9LPx5LE8HMSuhVgcm+cGLb1/H1lmjArt6gIcEtGqFEUUFKc0dM+JY1EMmgHzwbn0L558= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715594605; c=relaxed/simple; bh=qPtmsc9aVaRFXH0vxN0wn2tJPuPbcbyFzlsOMSyAdDw=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=KoKx9iMND9dBtCujOzY1fsDxLPff6x1xY3Iz9TajbLGoIweDNvYpQ7YoshH8RgJ11GrIm8gN2Z1+YXjMfpk4miVCAO4gQYQfMSrL7ERroAu9lF1hIpMGJ/5WqIZMTraKK0Jy/5mXZgSWIuIPiMQ6IpLOy6FueZRD+vtJnAr0I0Y= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iXWewXdz; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD32CC113CC; Mon, 13 May 2024 10:03:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1715594604; bh=qPtmsc9aVaRFXH0vxN0wn2tJPuPbcbyFzlsOMSyAdDw=; h=From:To:Cc:Subject:Date:From; b=iXWewXdzUpD2uL70ydPKzG0bHJ7ydLietv9lbpsHyGyca9U5kTSqcrQE513aC4B1P Te0GCtTrCA8qwlPbM01MAFr0y6KulARZCh2GnBe8PmjIsNI5FoG2EUaeSxCTw6rRCr ihN1lHW5rCZeZZXeAZp/WsZ8fytdNXEw7kDaC8jZ4GgT4qwdpNmmpUvA5Ki6swjPZA d39TUrqh8R6aU/2CLpF6zkveRZZvVpD9e9a7RoMyvvwaaswtuLG0pnMBmEAnQt84nf NfnqZLDyWUPmLTT6bSrvjnMDaNklF7yCZdE5Vx90G+tEvXYypKtPVTZEOS8ic7ph/C bbDPur+zXAffA== From: Puranjay Mohan To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , "Naveen N. Rao" , Michael Ellerman , Nicholas Piggin , Christophe Leroy , "Aneesh Kumar K.V" , Hari Bathini , bpf@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, paulmck@kernel.org Cc: puranjay12@gmail.com Subject: [PATCH bpf v3] powerpc/bpf: enforce full ordering for ATOMIC operations with BPF_FETCH Date: Mon, 13 May 2024 10:02:48 +0000 Message-Id: <20240513100248.110535-1-puranjay@kernel.org> X-Mailer: git-send-email 2.40.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The Linux Kernel Memory Model [1][2] requires RMW operations that have a return value to be fully ordered. BPF atomic operations with BPF_FETCH (including BPF_XCHG and BPF_CMPXCHG) return a value back so they need to be JITed to fully ordered operations. POWERPC currently emits relaxed operations for these. We can show this by running the following litmus-test: PPC SB+atomic_add+fetch { 0:r0=x; (* dst reg assuming offset is 0 *) 0:r1=2; (* src reg *) 0:r2=1; 0:r4=y; (* P0 writes to this, P1 reads this *) 0:r5=z; (* P1 writes to this, P0 reads this *) 0:r6=0; 1:r2=1; 1:r4=y; 1:r5=z; } P0 | P1 ; stw r2, 0(r4) | stw r2,0(r5) ; | ; loop:lwarx r3, r6, r0 | ; mr r8, r3 | ; add r3, r3, r1 | sync ; stwcx. r3, r6, r0 | ; bne loop | ; mr r1, r8 | ; | ; lwa r7, 0(r5) | lwa r7,0(r4) ; ~exists(0:r7=0 /\ 1:r7=0) Witnesses Positive: 9 Negative: 3 Condition ~exists (0:r7=0 /\ 1:r7=0) Observation SB+atomic_add+fetch Sometimes 3 9 This test shows that the older store in P0 is reordered with a newer load to a different address. Although there is a RMW operation with fetch between them. Adding a sync before and after RMW fixes the issue: Witnesses Positive: 9 Negative: 0 Condition ~exists (0:r7=0 /\ 1:r7=0) Observation SB+atomic_add+fetch Never 0 9 [1] https://www.kernel.org/doc/Documentation/memory-barriers.txt [2] https://www.kernel.org/doc/Documentation/atomic_t.txt Fixes: 65112709115f ("powerpc/bpf/64: add support for BPF_ATOMIC bitwise operations") Signed-off-by: Puranjay Mohan Acked-by: Paul E. McKenney --- Changes in v2 -> v3: v2: https://lore.kernel.org/all/20240508115404.74823-1-puranjay@kernel.org/ - Emit the sync outside the loop so it doesn't get executed everytime. - Minor coding style changes. Changes in v1 -> v2: v1: https://lore.kernel.org/all/20240507175439.119467-1-puranjay@kernel.org/ - Don't emit `sync` for non-SMP kernels as that adds unessential overhead. --- arch/powerpc/net/bpf_jit_comp32.c | 12 ++++++++++++ arch/powerpc/net/bpf_jit_comp64.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c index 2f39c50ca729..35f64dcfa68e 100644 --- a/arch/powerpc/net/bpf_jit_comp32.c +++ b/arch/powerpc/net/bpf_jit_comp32.c @@ -852,6 +852,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)); @@ -905,6 +914,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 */ diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 79f23974a320..884eef1b3973 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -803,6 +803,15 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code /* Get offset into TMP_REG_1 */ EMIT(PPC_RAW_LI(tmp1_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_u64() 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 TMP_REG_2 */ if (size == BPF_DW) @@ -865,6 +874,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code PPC_BCC_SHORT(COND_NE, tmp_idx); 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, _R0)); /* * Skip unnecessary zero-extension for 32-bit cmpxchg. -- 2.40.1