From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E23F622F19 for ; Thu, 20 Feb 2025 01:19:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014399; cv=none; b=gRw7VFxjrIOKB06hbaf8ejClc5OJKObKSlKWucvMOOmGIN6Zzqr9Rf705BF2ButIB0HhIxl5r8oysRRhuazhNyX3w5XYaaMoZB9VeecFhGgXxa2LuE+O3YzueU9nOKNHmKC8oeoc8lwV7GkhsrjgDwvY+2FU8G56/z1aqrz+QtY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014399; c=relaxed/simple; bh=y9TqtEwuxAM59+pRGkNPZtMDonN/O6t9RwUUNszlNTw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=H9S4jrqtrpaYMf6L+Oz1oOPo+z63UZruKHJfnJBCIxlrX+cCooercHRQZ/QSBy4aQjwjGvqIRrkF8tWOhfQtiy3VLhWOiYUax4mzF8OcyG0n4aSH/vThWJlmX4fIwWiPkagZhxjQpVFfaupnctCccUQvcRJjQmSZn2E6Ui5M40g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=YwYCmzhz; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="YwYCmzhz" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-220e1593b85so7231145ad.3 for ; Wed, 19 Feb 2025 17:19:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014397; x=1740619197; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=LUnHgSEounregn05uHGT75nqn32OY7tna6KiTBpIBWU=; b=YwYCmzhzZWgCqBpx3vZER5zzlcVQ7m7ocpnsxeGGcvSoX37Sso43YH/QEThOgxoJRZ gdnGmMTLgo+RzwcVTSDSb2+/iui9mlKQHpUj2kUdlrGFaUsHFHVWhLNdwy87YYVctg0d 5Ghx5zxCLA9Z1sPknlH8proQNJPzIVwLBT7L3cVa5Du57h0Oda0IsuSpUgMfakOTq/rZ 6phmWtnP2F1+1SxqWMgrhEr2pxL/as4dOhkmY48zPBO+kyjrAKZitAw7yC14udwx3RFr leJX6kKrw4Ze9seyrhd8bsnhj1ARgZlKPOqmDkApPL6NPGsvZuvBHpKvrsabvo2UU+r4 oY4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014397; x=1740619197; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=LUnHgSEounregn05uHGT75nqn32OY7tna6KiTBpIBWU=; b=lpGX9ZT6pvAU7HzJJvhzdAzH/SCCNgWkj/svHrG0vgQdM5xofHuNX+qTcGZ587Xp+V XcXcXBFwovR36jeG4MChvqDvRB1xobg2eSiEzYPyd4+N8QN7f2xaUANBc08sL6Vq2W0I yRB1bJfaVPNTgi1D7NrbMVBW+iz//kJa8PlZFy79Ki722E2dP0KgpKWOk6O90u0gzcPe MTtHw25i1ilE0HFmi2PLBXLId6UxCvbIUfPXAMgEwZZNNjJn0Dq5wuAbvHBAZYOahilC ejtujipnDPDX7yjRNzMYdQWf4qaFmRO8hGxXemg7ob55wBufZqt0KeR0ny7g42MWOe/l SFgw== X-Forwarded-Encrypted: i=1; AJvYcCXUMW8rtmkVCi6HjSBowI8cczaRqnHVxUq/EVIzb05tctdbAk2G/FL6aGWmv40f9MVzaWf3Z//ifdw0ipY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx2icaqSW05K0nkgp4kFAZ39Z8OGwOp7juuNR+Vxlb6MvhxE7UJ gLSswK1DcOiVoI+bGjisUTIKATye+hkjW5YEC+k9NjQ/wSYPbuMZZQYSVQ+nCJA0892GH3Ustya NcYlZlzYy/Q== X-Google-Smtp-Source: AGHT+IGMFdx8KCQOyowQ5w7kdzLzapH1OG1g0TKzCE06XDnQiClJ/IBLT/uScVtfAiDmrUICsMmVFXpFWBIDzA== X-Received: from plky4.prod.google.com ([2002:a17:902:7004:b0:220:d272:cfbe]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:ec89:b0:215:6b4c:89fa with SMTP id d9443c01a7336-221040137ffmr260028595ad.8.1740014397157; Wed, 19 Feb 2025 17:19:57 -0800 (PST) Date: Thu, 20 Feb 2025 01:19:53 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <58c5d8d587948922f257ca4735b4eb9518a191cd.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 1/9] bpf/verifier: Factor out atomic_ptr_type_ok() From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Factor out atomic_ptr_type_ok() as a helper function to be used later. Signed-off-by: Peilin Ye --- kernel/bpf/verifier.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e57b7c949860..21658bd5e6d8 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6194,6 +6194,26 @@ static bool is_arena_reg(struct bpf_verifier_env *en= v, int regno) return reg->type =3D=3D PTR_TO_ARENA; } =20 +/* Return false if @regno contains a pointer whose type isn't supported for + * atomic instruction @insn. + */ +static bool atomic_ptr_type_ok(struct bpf_verifier_env *env, int regno, + struct bpf_insn *insn) +{ + if (is_ctx_reg(env, regno)) + return false; + if (is_pkt_reg(env, regno)) + return false; + if (is_flow_key_reg(env, regno)) + return false; + if (is_sk_reg(env, regno)) + return false; + if (is_arena_reg(env, regno)) + return bpf_jit_supports_insn(insn, true); + + return true; +} + static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] =3D { #ifdef CONFIG_NET [PTR_TO_SOCKET] =3D &btf_sock_ids[BTF_SOCK_TYPE_SOCK], @@ -7651,11 +7671,7 @@ static int check_atomic(struct bpf_verifier_env *env= , int insn_idx, struct bpf_i return -EACCES; } =20 - if (is_ctx_reg(env, insn->dst_reg) || - is_pkt_reg(env, insn->dst_reg) || - is_flow_key_reg(env, insn->dst_reg) || - is_sk_reg(env, insn->dst_reg) || - (is_arena_reg(env, insn->dst_reg) && !bpf_jit_supports_insn(insn, tru= e))) { + if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) { verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n", insn->dst_reg, reg_type_str(env, reg_state(env, insn->dst_reg)->type)); --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 191BD22F19 for ; Thu, 20 Feb 2025 01:20:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014453; cv=none; b=LuXEg/ZsGMvKM0ZW6zqqIDyL07xJj1nChplUrLy4Eyljlde1PDJGe9+liZs0V+8TJUIRCB+zr0/QwndWgorI59NDsxII2YL6AHVh4gfFaBnlFrOps9Ues5hOn8RdltBVDoUkZeAbCg1vSp9paso80PG0n/qT0PlV73OORCPwz+o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014453; c=relaxed/simple; bh=8BEtdyFL+la1SWhGjdvnuHQmk94dfd7pWP8oR4rmWzA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T5fgwqP4Xy5eysyNpQRKQjVde7i+6Uv/YFE7CdBTS87TChOZgAkLzO0YXAHNCQLPE1BzWJdD/hkU5OF2ebDC2J6nu/3Do8osdpZ/8qgag4W34yumvRqhKrn1tswScZuTTXeapqI05FdrH0jkw3fv/yr94RQFAA9OjcI8SzHVsNg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tD9ic9Vy; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tD9ic9Vy" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-220c1f88eb4so5434975ad.2 for ; Wed, 19 Feb 2025 17:20:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014451; x=1740619251; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AVw9FAeQI7lCZwFZLEeeKDcfx7NZFxNIup/gnaKUq1Q=; b=tD9ic9VyzQSbZsr3+usJdbzn6jBeZGgu62yH2EqklfdWkTkPsRPQvU9WJ0GnUuaU/t YIJZrjSlHixsEPcaqMkZ7PdmVcy5n1aWH/H5byfayecgwZhnpU8YlLcH/IJYAlk32Cve LcaYSBdZszb4PEMuMKSPf7IcSPVQu64siQEe6uyZhwQN6aT+850cHyJfpfb4cQ9IeLBz R19/ZcEBiLje0LrbIm1s6bOTngS3AJuWVhunr9mHFCDiggzNarqt4Xx2oGuQqdavTRzp /K//8E8KmaIER3D35J5ZWAx7jsh7b2B52/Drja7uy1iB5X00d+yDYTmmsmbXgmlwkP/j LG6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014451; x=1740619251; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AVw9FAeQI7lCZwFZLEeeKDcfx7NZFxNIup/gnaKUq1Q=; b=EvaQtWWWEUX+UFJpKEStVK5ykZazJLvE9hOaEmYNgIbaSVk/04xahAtQVRW8zYhAfu QXfsc0r2Gil9wRkuKiRMRymWfEwhsjdv83SXSNHF+B2AzJhRztKi5IsjLxoYGC8nm7Jl RsMUsYk+Xoex5QGihsURwGzgNl521VX3r/4VDV8R9ePV/34Dnu0K5X3NnMj019c3IWtS eruCdWe2cyVPOGvzcnc+jl8VoC/EijHFVRUWDSyZJXMEEv6vbjLE79BhO3t1gogDM0LF tJM3RdngDGw5I5ZkEyfHt+nJPE+dahb6ffvIC5IZ8OSQugU6sZqAm/8a3xae4vHhallJ PLsQ== X-Forwarded-Encrypted: i=1; AJvYcCV/YfNFzznFwoGGVvBeWYBlPkPHYOKrf0xcMfeA401pV2/3QVeJmXCAgGsOeREK22iGddOasbT6Zo6e0hw=@vger.kernel.org X-Gm-Message-State: AOJu0YzLIC9rPgDxKITpb683WMKHqYlT8ZgmWMrj2vmoVSkJS7QZ7nGE 0qsKLMMivCcSfI9pBgloMGxVo/FuS9hCpcIaUbhZKXM9sNzDdSTmsTGNKqgt+hfMJODvyZc77/2 tht+pywoYEA== X-Google-Smtp-Source: AGHT+IELkZhp3dnu1j1hrZyZSNzylf6/SsN58EX3cCnB9zawb1C1aTd09ns9uhXgPWFn3IcwfNEV46XMOLhkTw== X-Received: from plbbj7.prod.google.com ([2002:a17:902:8507:b0:221:7c80:aeff]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:41c3:b0:220:ef79:aca9 with SMTP id d9443c01a7336-221711c8dd8mr102260065ad.53.1740014451316; Wed, 19 Feb 2025 17:20:51 -0800 (PST) Date: Thu, 20 Feb 2025 01:20:41 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <91e99076cf23e75e4831c75b38f8cfa84d7da34b.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 2/9] bpf/verifier: Factor out check_atomic_rmw() From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, check_atomic() only handles atomic read-modify-write (RMW) instructions. Since we are planning to introduce other types of atomic instructions (i.e., atomic load/store), extract the existing RMW handling logic into its own function named check_atomic_rmw(). Remove the @insn_idx parameter as it is not really necessary. Use 'env->insn_idx' instead, as in other places in verifier.c. Signed-off-by: Peilin Ye --- kernel/bpf/verifier.c | 53 +++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 21658bd5e6d8..63d810bbc26e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7615,28 +7615,12 @@ static int check_mem_access(struct bpf_verifier_env= *env, int insn_idx, u32 regn static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_ty= pe type, bool allow_trust_mismatch); =20 -static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct= bpf_insn *insn) +static int check_atomic_rmw(struct bpf_verifier_env *env, + struct bpf_insn *insn) { int load_reg; int err; =20 - switch (insn->imm) { - case BPF_ADD: - case BPF_ADD | BPF_FETCH: - case BPF_AND: - case BPF_AND | BPF_FETCH: - case BPF_OR: - case BPF_OR | BPF_FETCH: - case BPF_XOR: - case BPF_XOR | BPF_FETCH: - case BPF_XCHG: - case BPF_CMPXCHG: - break; - default: - verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", insn->imm); - return -EINVAL; - } - if (BPF_SIZE(insn->code) !=3D BPF_W && BPF_SIZE(insn->code) !=3D BPF_DW) { verbose(env, "invalid atomic operand size\n"); return -EINVAL; @@ -7698,12 +7682,12 @@ static int check_atomic(struct bpf_verifier_env *en= v, int insn_idx, struct bpf_i /* Check whether we can read the memory, with second call for fetch * case to simulate the register fill. */ - err =3D check_mem_access(env, insn_idx, insn->dst_reg, insn->off, + err =3D check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off, BPF_SIZE(insn->code), BPF_READ, -1, true, false); if (!err && load_reg >=3D 0) - err =3D check_mem_access(env, insn_idx, insn->dst_reg, insn->off, - BPF_SIZE(insn->code), BPF_READ, load_reg, - true, false); + err =3D check_mem_access(env, env->insn_idx, insn->dst_reg, + insn->off, BPF_SIZE(insn->code), + BPF_READ, load_reg, true, false); if (err) return err; =20 @@ -7713,13 +7697,34 @@ static int check_atomic(struct bpf_verifier_env *en= v, int insn_idx, struct bpf_i return err; } /* Check whether we can write into the same memory. */ - err =3D check_mem_access(env, insn_idx, insn->dst_reg, insn->off, + err =3D check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off, BPF_SIZE(insn->code), BPF_WRITE, -1, true, false); if (err) return err; return 0; } =20 +static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *ins= n) +{ + switch (insn->imm) { + case BPF_ADD: + case BPF_ADD | BPF_FETCH: + case BPF_AND: + case BPF_AND | BPF_FETCH: + case BPF_OR: + case BPF_OR | BPF_FETCH: + case BPF_XOR: + case BPF_XOR | BPF_FETCH: + case BPF_XCHG: + case BPF_CMPXCHG: + return check_atomic_rmw(env, insn); + default: + verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", + insn->imm); + return -EINVAL; + } +} + /* When register 'regno' is used to read the stack (either directly or thr= ough * a helper function) make sure that it's within stack boundary and, depen= ding * on the access type and privileges, that all elements of the stack are @@ -19187,7 +19192,7 @@ static int do_check(struct bpf_verifier_env *env) enum bpf_reg_type dst_reg_type; =20 if (BPF_MODE(insn->code) =3D=3D BPF_ATOMIC) { - err =3D check_atomic(env, env->insn_idx, insn); + err =3D check_atomic(env, insn); if (err) return err; env->insn_idx++; --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4492F41C7F for ; Thu, 20 Feb 2025 01:21:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014466; cv=none; b=TMZ18DLO2sphfOt8xzCgY4j3WgOFvskjBk/kxxlSKAFHSYKVKZsgz/IMkbdNtoij9j4UDqP80b8F2fgQNALvYFzgM/nydhNY6ztQo5G5o+n2bmi2GN+mmvdVxudLDV/upa8SJeezUPfL1ofjyUr93KKML/pPf5tEU50OMOyKYJM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014466; c=relaxed/simple; bh=gBOioH+MoGQo4UadYpQBkWbBwjDiFjFSK9/sF/gTzzc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=I6fcs2+XlVizPxaRlsqiTJNzBi/ZY7NS/P/j8pdnoI5UzDOuwKeWz4Elv1gizyPLQJHHjz4m+HHhvuJX6EyqsvTyfcNGbLz4S0y9aweB2SLjX11YrfbT8nOe8cmfw+Wh1lOvUFbtKVbMPiYBDwCGkwADCBEERWNdfRHL+QMBxGY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=o1Xr7c59; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="o1Xr7c59" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-22112e86501so7269515ad.0 for ; Wed, 19 Feb 2025 17:21:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014464; x=1740619264; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=1aLixsgG5yYd8/b4s02+ROe3IhMkQne3dzUxBtDOXqk=; b=o1Xr7c59NceGMNLAgVB4e4fNi5hX8dE8QxDs937IMLekcRJ4Q4M7T7NfWirEJE/cVe k3gIax0JZymRtGJKgnk/K5Cf/udvtEEkfh0q6FKAZaLwyzmjqG/xuR5oqrkE03+NOTta 2k2gxjqVCb6FcdEGbM50fFtS6UZshaXD27mqNJZl5cxUpBhEeqK3aHbYXY49DsUVF90h EKlCfeVk+wL1Qw2uDmKt4mIrzDWflQuNzpuv9s+EIPt2+v+6o3YWILIqZajQKDku7H0k UcEtQ5WnIdSVXwfjxg/aQM3o1CYQoCpJyccoBsR6QOd9dQj5a1nl5L72QixcFnhdArsY U2fQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014464; x=1740619264; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1aLixsgG5yYd8/b4s02+ROe3IhMkQne3dzUxBtDOXqk=; b=Bv2IGSn45hxZuLNcLrJPUg68xfAR1Cauz35jXi9KvB8ccj4QSIM1AGJo+X1d6iOIwd 7LKCzA7vLRv2j/RTZwiiJVjYQwksbK1d1fqa+YObTVgnTCthB++f1bqaYlVTyAaGu7QH JSZUkXNJIZTGZO0XoBN7n9aloqT3vMV0s2e/uCVTorRyp14hgcsUUZeP4Pm7BSjlrBTQ HmtcIJfN41xvbXFp6D799pFP9O4XImc6b3HNvIfqkzj4BgJcndg+6NgOn3cXyM2a6wEn iKUCe+V1DjvtX42/62nEEUc/0+j0L3dj/wBRGKy3V4iFXKYsHRca+XAg+r+5bHx+hpUQ 3GDA== X-Forwarded-Encrypted: i=1; AJvYcCWPOWVJnnPFPgeR31mCMRC1RzWlYdzuW6Z2BLBYNshMJpPzLBcvYlHE5j5c/3eTQiN7NyWEHpxv0QzoHQ0=@vger.kernel.org X-Gm-Message-State: AOJu0YwXikqn6q0jFLTcWAbp0ySggdlQV8ny7V1yFAjHFABx/twTfoWD 8gR4i4hLUPDWSUHUX5Uy5oGdKnI2V/CqZhWr8tawbu0MD+EpCv1It1+vZXgEa4B1O7HfK3T00ii 0GmKZ+GlAmA== X-Google-Smtp-Source: AGHT+IHUV95CcKWgBO0qp2SNUvCYSkhL2FrtNC7aRQZUoxAiCMv56jdPPY4vmUXwTTy3kWwJ9QOGDtLY3sIc/w== X-Received: from pgbfm14.prod.google.com ([2002:a05:6a02:498e:b0:ad5:4477:da5b]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:fc8f:b0:21a:8300:b9ce with SMTP id d9443c01a7336-221906a633cmr7766695ad.49.1740014464427; Wed, 19 Feb 2025 17:21:04 -0800 (PST) Date: Thu, 20 Feb 2025 01:20:55 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <18f624573f4d5cb42ee877655ea0a96248447d7b.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 3/9] bpf/verifier: Factor out check_load_mem() and check_store_reg() From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extract BPF_LDX and most non-ATOMIC BPF_STX instruction handling logic in do_check() into helper functions to be used later. While we are here, make that comment about "reserved fields" more specific. Suggested-by: Eduard Zingerman Acked-by: Eduard Zingerman Signed-off-by: Peilin Ye --- kernel/bpf/verifier.c | 110 +++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 63d810bbc26e..3b20bff1c5eb 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7615,6 +7615,67 @@ static int check_mem_access(struct bpf_verifier_env = *env, int insn_idx, u32 regn static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_ty= pe type, bool allow_trust_mismatch); =20 +static int check_load_mem(struct bpf_verifier_env *env, struct bpf_insn *i= nsn, + bool strict_alignment_once, bool is_ldsx, + bool allow_trust_mismatch, const char *ctx) +{ + struct bpf_reg_state *regs =3D cur_regs(env); + enum bpf_reg_type src_reg_type; + int err; + + /* check src operand */ + err =3D check_reg_arg(env, insn->src_reg, SRC_OP); + if (err) + return err; + + /* check dst operand */ + err =3D check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK); + if (err) + return err; + + src_reg_type =3D regs[insn->src_reg].type; + + /* Check if (src_reg + off) is readable. The state of dst_reg will be + * updated by this call. + */ + err =3D check_mem_access(env, env->insn_idx, insn->src_reg, insn->off, + BPF_SIZE(insn->code), BPF_READ, insn->dst_reg, + strict_alignment_once, is_ldsx); + err =3D err ?: save_aux_ptr_type(env, src_reg_type, + allow_trust_mismatch); + err =3D err ?: reg_bounds_sanity_check(env, ®s[insn->dst_reg], ctx); + + return err; +} + +static int check_store_reg(struct bpf_verifier_env *env, struct bpf_insn *= insn, + bool strict_alignment_once) +{ + struct bpf_reg_state *regs =3D cur_regs(env); + enum bpf_reg_type dst_reg_type; + int err; + + /* check src1 operand */ + err =3D check_reg_arg(env, insn->src_reg, SRC_OP); + if (err) + return err; + + /* check src2 operand */ + err =3D check_reg_arg(env, insn->dst_reg, SRC_OP); + if (err) + return err; + + dst_reg_type =3D regs[insn->dst_reg].type; + + /* Check if (dst_reg + off) is writeable. */ + err =3D check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off, + BPF_SIZE(insn->code), BPF_WRITE, insn->src_reg, + strict_alignment_once, false); + err =3D err ?: save_aux_ptr_type(env, dst_reg_type, false); + + return err; +} + static int check_atomic_rmw(struct bpf_verifier_env *env, struct bpf_insn *insn) { @@ -19162,35 +19223,16 @@ static int do_check(struct bpf_verifier_env *env) return err; =20 } else if (class =3D=3D BPF_LDX) { - enum bpf_reg_type src_reg_type; - - /* check for reserved fields is already done */ - - /* check src operand */ - err =3D check_reg_arg(env, insn->src_reg, SRC_OP); - if (err) - return err; + bool is_ldsx =3D BPF_MODE(insn->code) =3D=3D BPF_MEMSX; =20 - err =3D check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK); - if (err) - return err; - - src_reg_type =3D regs[insn->src_reg].type; - - /* check that memory (src_reg + off) is readable, - * the state of dst_reg will be updated by this func + /* Check for reserved fields is already done in + * resolve_pseudo_ldimm64(). */ - err =3D check_mem_access(env, env->insn_idx, insn->src_reg, - insn->off, BPF_SIZE(insn->code), - BPF_READ, insn->dst_reg, false, - BPF_MODE(insn->code) =3D=3D BPF_MEMSX); - err =3D err ?: save_aux_ptr_type(env, src_reg_type, true); - err =3D err ?: reg_bounds_sanity_check(env, ®s[insn->dst_reg], "ldx"= ); + err =3D check_load_mem(env, insn, false, is_ldsx, true, + "ldx"); if (err) return err; } else if (class =3D=3D BPF_STX) { - enum bpf_reg_type dst_reg_type; - if (BPF_MODE(insn->code) =3D=3D BPF_ATOMIC) { err =3D check_atomic(env, insn); if (err) @@ -19204,25 +19246,7 @@ static int do_check(struct bpf_verifier_env *env) return -EINVAL; } =20 - /* check src1 operand */ - err =3D check_reg_arg(env, insn->src_reg, SRC_OP); - if (err) - return err; - /* check src2 operand */ - err =3D check_reg_arg(env, insn->dst_reg, SRC_OP); - if (err) - return err; - - dst_reg_type =3D regs[insn->dst_reg].type; - - /* check that memory (dst_reg + off) is writeable */ - err =3D check_mem_access(env, env->insn_idx, insn->dst_reg, - insn->off, BPF_SIZE(insn->code), - BPF_WRITE, insn->src_reg, false, false); - if (err) - return err; - - err =3D save_aux_ptr_type(env, dst_reg_type, false); + err =3D check_store_reg(env, insn, false); if (err) return err; } else if (class =3D=3D BPF_ST) { --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30200191F79 for ; Thu, 20 Feb 2025 01:21:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014478; cv=none; b=uu5T6uElXhV7P9YpbMlpCZf4ZF6bL9ss8X3XroGCIQt25fPOMmhSMfg4et+zhrQITKHxBR5iEcb99wD3z2O9J4PXGBsNh4m851G6dfYa6o3ZnqvwUNltaBhvjoRA4FFDbo8M1EUrLMbgcSwffCXURUi3QElRVjAj7j1XdZH7AZ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014478; c=relaxed/simple; bh=urWFTuG+wRZOLclEMwumKQDTBnPNE1NlLYSAEDQhxtY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZqN19SeZq5OzwwYICc3Go3LHq9utpuaXEuHW/jqMYUh8HtbXIPntmVJ3zr/Ww5UGduMUd8k2n71H8OIbjRD4y5WCRiwYiNJZs4tX96Vr6viW5t8XvzVlrb1tqLMTgT26FB44V0MLyxABRKNVX3bYGfw1CKp1h0aAGio6hxtKOew= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eG3N69OT; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eG3N69OT" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2fc1c3b3dc7so799799a91.2 for ; Wed, 19 Feb 2025 17:21:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014475; x=1740619275; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=+BEA4nmaL1BpG7jNtHOlziLeLskEIyo+jY91ovy615w=; b=eG3N69OTI5A4D83Byb2X0+O9aOJ316xyPfIo3Q4mOOH4VDgcdvxvV/x3vFKpXi8pF3 1xVEsTF22j1M49QxqpssrQOcu+s2dOq6DfY+YiMjNQmkQEuRtIy0wUlgGI7+1J/DmV1B eP1n/GJHUHyPRvSA0LKcU9SxbGq0R2sWXSqWOORntks87IWfpObpA/IDV34DCFeA7uSV fz7jbRGPCywmbUNcSkkhL4pQ06lRajlYbo5++AEJCIcf1NVVFibxvZI/5uLlwpnyCxhB ZTR3gcn7xy5MpY60k1DzhxTM0vPUl4D0DmxVfLU3N3hwGp70qEvYQuhjsxhvYTQagSfN oAhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014475; x=1740619275; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+BEA4nmaL1BpG7jNtHOlziLeLskEIyo+jY91ovy615w=; b=P1omQ9hv0w3TJKOHb2GQ2jjDkIYVDGymbmjAZdWB72v5wmY1HdhR7Ssi2LzPrn2LQp yG9eqHiUWnz+aXsVSPAyuazf12LHfJwlcWSlnHj+nFk8p0Hmbq8myl342mhHtdERWZLV +9ETOYdD9t0PYrifPMHY2zJbQXq3BPz1c+iTHNP7QHpxzHuUmVOQn9/7dj7+aC49f2NQ C0frLGSpoP0INeGrORd8BeG/vbfW2KiVTF+Z7UzDfr9Rl814eum2KO2Um28ptXZqws7O XjcSpnrqiJPewc7kTsYeB794h7GtYSdsEchO8ZjLslFWjStbt9Cd/SpfGQRnWJynBHNA wNUg== X-Forwarded-Encrypted: i=1; AJvYcCXW1g5mDb/pv9z5UaLlQteVKRKoLkmOTHBE6mkYGkJpQWyrtTJXog8F3tUV+f2pQbvU03MZAXf7am6IDyc=@vger.kernel.org X-Gm-Message-State: AOJu0YwS99umPVx7G+SNLVAgefezLMtSXjJKy8XPborXHMqd3n2eoCvA pDpX8/7bW1sGLLKs0eNOF1OPi0otpmD/Dt3VC5rMyW/pdCmsVzdFbY6Xyn7GWh8keiScYybnCkw drSHkWZNQDg== X-Google-Smtp-Source: AGHT+IEIWUmVicMWkFB98XQ2yOyp4PvtwY7AwdBnj2SPFWwZdGjFsG4tsdvInNY9Ikt2OAE/aRcVpiWLa0y+Qg== X-Received: from pfbhw8.prod.google.com ([2002:a05:6a00:8908:b0:732:3440:ffcc]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2e97:b0:730:87cf:a7cd with SMTP id d2e1a72fcca58-7329de6ecbdmr10600543b3a.8.1740014475374; Wed, 19 Feb 2025 17:21:15 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:07 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: Subject: [PATCH bpf-next v3 4/9] bpf: Introduce load-acquire and store-release instructions From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce BPF instructions with load-acquire and store-release semantics, as discussed in [1]. Define 2 new flags: #define BPF_LOAD_ACQ 0x100 #define BPF_STORE_REL 0x110 A "load-acquire" is a BPF_STX | BPF_ATOMIC instruction with the 'imm' field set to BPF_LOAD_ACQ (0x100). Similarly, a "store-release" is a BPF_STX | BPF_ATOMIC instruction with the 'imm' field set to BPF_STORE_REL (0x110). Unlike existing atomic read-modify-write operations that only support BPF_W (32-bit) and BPF_DW (64-bit) size modifiers, load-acquires and store-releases also support BPF_B (8-bit) and BPF_H (16-bit). An 8- or 16-bit load-acquire zero-extends the value before writing it to a 32-bit register, just like ARM64 instruction LDARH and friends. Similar to existing atomic read-modify-write operations, misaligned load-acquires/store-releases are not allowed (even if BPF_F_ANY_ALIGNMENT is set). As an example, consider the following 64-bit load-acquire BPF instruction (assuming little-endian): db 10 00 00 00 01 00 00 r0 =3D load_acquire((u64 *)(r1 + 0x0)) opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX imm (0x00000100): BPF_LOAD_ACQ Similarly, a 16-bit BPF store-release: cb 21 00 00 10 01 00 00 store_release((u16 *)(r1 + 0x0), w2) opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX imm (0x00000110): BPF_STORE_REL In arch/{arm64,s390,x86}/net/bpf_jit_comp.c, have bpf_jit_supports_insn(..., /*in_arena=3D*/true) return false for the new instructions, until the corresponding JIT compiler supports them. [1] https://lore.kernel.org/all/20240729183246.4110549-1-yepeilin@google.co= m/ Acked-by: Eduard Zingerman Acked-by: Ilya Leoshkevich Signed-off-by: Peilin Ye --- arch/arm64/net/bpf_jit_comp.c | 4 +++ arch/s390/net/bpf_jit_comp.c | 14 +++++--- arch/x86/net/bpf_jit_comp.c | 4 +++ include/linux/bpf.h | 15 ++++++++ include/linux/filter.h | 2 ++ include/uapi/linux/bpf.h | 3 ++ kernel/bpf/core.c | 63 ++++++++++++++++++++++++++++++---- kernel/bpf/disasm.c | 12 +++++++ kernel/bpf/verifier.c | 45 ++++++++++++++++++++++-- tools/include/uapi/linux/bpf.h | 3 ++ 10 files changed, 152 insertions(+), 13 deletions(-) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 8446848edddb..8c3b47d9e441 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -2667,8 +2667,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bo= ol in_arena) if (!in_arena) return true; switch (insn->code) { + case BPF_STX | BPF_ATOMIC | BPF_B: + case BPF_STX | BPF_ATOMIC | BPF_H: case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_DW: + if (bpf_atomic_is_load_store(insn)) + return false; if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) return false; } diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 9d440a0b729e..0776dfde2dba 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -2919,10 +2919,16 @@ bool bpf_jit_supports_arena(void) =20 bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena) { - /* - * Currently the verifier uses this function only to check which - * atomic stores to arena are supported, and they all are. - */ + if (!in_arena) + return true; + switch (insn->code) { + case BPF_STX | BPF_ATOMIC | BPF_B: + case BPF_STX | BPF_ATOMIC | BPF_H: + case BPF_STX | BPF_ATOMIC | BPF_W: + case BPF_STX | BPF_ATOMIC | BPF_DW: + if (bpf_atomic_is_load_store(insn)) + return false; + } return true; } =20 diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index a43fc5af973d..f0c31c940fb8 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -3771,8 +3771,12 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bo= ol in_arena) if (!in_arena) return true; switch (insn->code) { + case BPF_STX | BPF_ATOMIC | BPF_B: + case BPF_STX | BPF_ATOMIC | BPF_H: case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_DW: + if (bpf_atomic_is_load_store(insn)) + return false; if (insn->imm =3D=3D (BPF_AND | BPF_FETCH) || insn->imm =3D=3D (BPF_OR | BPF_FETCH) || insn->imm =3D=3D (BPF_XOR | BPF_FETCH)) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 15164787ce7f..9be9c586152f 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -991,6 +991,21 @@ static inline bool bpf_pseudo_func(const struct bpf_in= sn *insn) return bpf_is_ldimm64(insn) && insn->src_reg =3D=3D BPF_PSEUDO_FUNC; } =20 +/* 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 instructio= n. + */ +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); diff --git a/include/linux/filter.h b/include/linux/filter.h index a3ea46281595..e36812a5b01f 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -364,6 +364,8 @@ static inline bool insn_is_cast_user(const struct bpf_i= nsn *insn) * BPF_XOR | BPF_FETCH src_reg =3D atomic_fetch_xor(dst_reg + off16= , src_reg); * BPF_XCHG src_reg =3D atomic_xchg(dst_reg + off16, src= _reg) * BPF_CMPXCHG r0 =3D atomic_cmpxchg(dst_reg + off16, r0, s= rc_reg) + * BPF_LOAD_ACQ dst_reg =3D smp_load_acquire(src_reg + off16) + * BPF_STORE_REL smp_store_release(dst_reg + off16, src_reg) */ =20 #define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF) \ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index fff6cdb8d11a..c52946c27822 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -51,6 +51,9 @@ #define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */ #define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */ =20 +#define BPF_LOAD_ACQ 0x100 /* load-acquire */ +#define BPF_STORE_REL 0x110 /* store-release */ + enum bpf_cond_pseudo_jmp { BPF_MAY_GOTO =3D 0, }; diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index a0200fbbace9..323af18d7d49 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1663,14 +1663,17 @@ EXPORT_SYMBOL_GPL(__bpf_call_base); INSN_3(JMP, JSET, K), \ INSN_2(JMP, JA), \ INSN_2(JMP32, JA), \ + /* Atomic operations. */ \ + INSN_3(STX, ATOMIC, B), \ + INSN_3(STX, ATOMIC, H), \ + INSN_3(STX, ATOMIC, W), \ + INSN_3(STX, ATOMIC, DW), \ /* Store instructions. */ \ /* Register based. */ \ INSN_3(STX, MEM, B), \ INSN_3(STX, MEM, H), \ INSN_3(STX, MEM, W), \ INSN_3(STX, MEM, DW), \ - INSN_3(STX, ATOMIC, W), \ - INSN_3(STX, ATOMIC, DW), \ /* Immediate based. */ \ INSN_3(ST, MEM, B), \ INSN_3(ST, MEM, H), \ @@ -2152,24 +2155,33 @@ static u64 ___bpf_prog_run(u64 *regs, const struct = bpf_insn *insn) if (BPF_SIZE(insn->code) =3D=3D BPF_W) \ atomic_##KOP((u32) SRC, (atomic_t *)(unsigned long) \ (DST + insn->off)); \ - else \ + else if (BPF_SIZE(insn->code) =3D=3D BPF_DW) \ atomic64_##KOP((u64) SRC, (atomic64_t *)(unsigned long) \ (DST + insn->off)); \ + else \ + goto default_label; \ break; \ case BOP | BPF_FETCH: \ if (BPF_SIZE(insn->code) =3D=3D BPF_W) \ SRC =3D (u32) atomic_fetch_##KOP( \ (u32) SRC, \ (atomic_t *)(unsigned long) (DST + insn->off)); \ - else \ + else if (BPF_SIZE(insn->code) =3D=3D BPF_DW) \ SRC =3D (u64) atomic64_fetch_##KOP( \ (u64) SRC, \ (atomic64_t *)(unsigned long) (DST + insn->off)); \ + else \ + goto default_label; \ break; =20 STX_ATOMIC_DW: STX_ATOMIC_W: + STX_ATOMIC_H: + STX_ATOMIC_B: switch (IMM) { + /* Atomic read-modify-write instructions support only W and DW + * size modifiers. + */ ATOMIC_ALU_OP(BPF_ADD, add) ATOMIC_ALU_OP(BPF_AND, and) ATOMIC_ALU_OP(BPF_OR, or) @@ -2181,20 +2193,59 @@ static u64 ___bpf_prog_run(u64 *regs, const struct = bpf_insn *insn) SRC =3D (u32) atomic_xchg( (atomic_t *)(unsigned long) (DST + insn->off), (u32) SRC); - else + else if (BPF_SIZE(insn->code) =3D=3D BPF_DW) SRC =3D (u64) atomic64_xchg( (atomic64_t *)(unsigned long) (DST + insn->off), (u64) SRC); + else + goto default_label; break; case BPF_CMPXCHG: if (BPF_SIZE(insn->code) =3D=3D BPF_W) BPF_R0 =3D (u32) atomic_cmpxchg( (atomic_t *)(unsigned long) (DST + insn->off), (u32) BPF_R0, (u32) SRC); - else + else if (BPF_SIZE(insn->code) =3D=3D BPF_DW) BPF_R0 =3D (u64) atomic64_cmpxchg( (atomic64_t *)(unsigned long) (DST + insn->off), (u64) BPF_R0, (u64) SRC); + else + goto default_label; + break; + /* Atomic load and store instructions support all size + * modifiers. + */ + case BPF_LOAD_ACQ: + switch (BPF_SIZE(insn->code)) { +#define LOAD_ACQUIRE(SIZEOP, SIZE) \ + case BPF_##SIZEOP: \ + DST =3D (SIZE)smp_load_acquire( \ + (SIZE *)(unsigned long)(SRC + insn->off)); \ + break; + LOAD_ACQUIRE(B, u8) + LOAD_ACQUIRE(H, u16) + LOAD_ACQUIRE(W, u32) + LOAD_ACQUIRE(DW, u64) +#undef LOAD_ACQUIRE + default: + goto default_label; + } + break; + case BPF_STORE_REL: + switch (BPF_SIZE(insn->code)) { +#define STORE_RELEASE(SIZEOP, SIZE) \ + case BPF_##SIZEOP: \ + smp_store_release( \ + (SIZE *)(unsigned long)(DST + insn->off), (SIZE)SRC); \ + break; + STORE_RELEASE(B, u8) + STORE_RELEASE(H, u16) + STORE_RELEASE(W, u32) + STORE_RELEASE(DW, u64) +#undef STORE_RELEASE + default: + goto default_label; + } break; =20 default: diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c index 309c4aa1b026..974d172d6735 100644 --- a/kernel/bpf/disasm.c +++ b/kernel/bpf/disasm.c @@ -267,6 +267,18 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, BPF_SIZE(insn->code) =3D=3D BPF_DW ? "64" : "", bpf_ldst_string[BPF_SIZE(insn->code) >> 3], insn->dst_reg, insn->off, insn->src_reg); + } else if (BPF_MODE(insn->code) =3D=3D BPF_ATOMIC && + insn->imm =3D=3D BPF_LOAD_ACQ) { + verbose(cbs->private_data, "(%02x) r%d =3D load_acquire((%s *)(r%d %+d)= )\n", + insn->code, insn->dst_reg, + bpf_ldst_string[BPF_SIZE(insn->code) >> 3], + insn->src_reg, insn->off); + } else if (BPF_MODE(insn->code) =3D=3D BPF_ATOMIC && + insn->imm =3D=3D BPF_STORE_REL) { + verbose(cbs->private_data, "(%02x) store_release((%s *)(r%d %+d), r%d)\= n", + insn->code, + bpf_ldst_string[BPF_SIZE(insn->code) >> 3], + insn->dst_reg, insn->off, insn->src_reg); } else { verbose(cbs->private_data, "BUG_%02x\n", insn->code); } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 3b20bff1c5eb..89e06fce5ece 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -579,6 +579,13 @@ static bool is_cmpxchg_insn(const struct bpf_insn *ins= n) insn->imm =3D=3D BPF_CMPXCHG; } =20 +static bool is_atomic_load_insn(const struct bpf_insn *insn) +{ + return BPF_CLASS(insn->code) =3D=3D BPF_STX && + BPF_MODE(insn->code) =3D=3D BPF_ATOMIC && + insn->imm =3D=3D BPF_LOAD_ACQ; +} + static int __get_spi(s32 off) { return (-off - 1) / BPF_REG_SIZE; @@ -3550,7 +3557,7 @@ static bool is_reg64(struct bpf_verifier_env *env, st= ruct bpf_insn *insn, } =20 if (class =3D=3D BPF_STX) { - /* BPF_STX (including atomic variants) has multiple source + /* BPF_STX (including atomic variants) has one or more source * operands, one of which is a ptr. Check whether the caller is * asking about it. */ @@ -4164,7 +4171,7 @@ static int backtrack_insn(struct bpf_verifier_env *en= v, int idx, int subseq_idx, * dreg still needs precision before this insn */ } - } else if (class =3D=3D BPF_LDX) { + } else if (class =3D=3D BPF_LDX || is_atomic_load_insn(insn)) { if (!bt_is_reg_set(bt, dreg)) return 0; bt_clear_reg(bt, dreg); @@ -7765,6 +7772,32 @@ static int check_atomic_rmw(struct bpf_verifier_env = *env, return 0; } =20 +static int check_atomic_load(struct bpf_verifier_env *env, + struct bpf_insn *insn) +{ + if (!atomic_ptr_type_ok(env, insn->src_reg, insn)) { + verbose(env, "BPF_ATOMIC loads from R%d %s is not allowed\n", + insn->src_reg, + reg_type_str(env, reg_state(env, insn->src_reg)->type)); + return -EACCES; + } + + return check_load_mem(env, insn, true, false, false, "atomic_load"); +} + +static int check_atomic_store(struct bpf_verifier_env *env, + struct bpf_insn *insn) +{ + if (!atomic_ptr_type_ok(env, insn->dst_reg, insn)) { + verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n", + insn->dst_reg, + reg_type_str(env, reg_state(env, insn->dst_reg)->type)); + return -EACCES; + } + + return check_store_reg(env, insn, true); +} + static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *ins= n) { switch (insn->imm) { @@ -7779,6 +7812,10 @@ static int check_atomic(struct bpf_verifier_env *env= , struct bpf_insn *insn) case BPF_XCHG: case BPF_CMPXCHG: return check_atomic_rmw(env, insn); + case BPF_LOAD_ACQ: + return check_atomic_load(env, insn); + case BPF_STORE_REL: + return check_atomic_store(env, insn); default: verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", insn->imm); @@ -20558,7 +20595,9 @@ static int convert_ctx_accesses(struct bpf_verifier= _env *env) insn->code =3D=3D (BPF_ST | BPF_MEM | BPF_W) || insn->code =3D=3D (BPF_ST | BPF_MEM | BPF_DW)) { type =3D BPF_WRITE; - } else if ((insn->code =3D=3D (BPF_STX | BPF_ATOMIC | BPF_W) || + } else if ((insn->code =3D=3D (BPF_STX | BPF_ATOMIC | BPF_B) || + insn->code =3D=3D (BPF_STX | BPF_ATOMIC | BPF_H) || + insn->code =3D=3D (BPF_STX | BPF_ATOMIC | BPF_W) || insn->code =3D=3D (BPF_STX | BPF_ATOMIC | BPF_DW)) && env->insn_aux_data[i + delta].ptr_type =3D=3D PTR_TO_ARENA) { insn->code =3D BPF_STX | BPF_PROBE_ATOMIC | BPF_SIZE(insn->code); diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index fff6cdb8d11a..c52946c27822 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -51,6 +51,9 @@ #define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */ #define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */ =20 +#define BPF_LOAD_ACQ 0x100 /* load-acquire */ +#define BPF_STORE_REL 0x110 /* store-release */ + enum bpf_cond_pseudo_jmp { BPF_MAY_GOTO =3D 0, }; --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-oa1-f74.google.com (mail-oa1-f74.google.com [209.85.160.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D84311B85C5 for ; Thu, 20 Feb 2025 01:21:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014485; cv=none; b=pPVwGQEu4p6gRG4UoFBN5x0Jo2xAarc6qRoieRCMYiEpJAY/WdE0FFOU3wjIIk7sUowVF55ZT+ZoTtPQ6fMl3HADv6ioOIfjyfqTWjs+d0un31PWdQc+n0qKZfGhiVg2kfJnXUyTnTkaBQ3k3w3R+afPi0T4i0nqvGqiKJiVICg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014485; c=relaxed/simple; bh=naOgejgL5qt+vPzbgEHxGefAA7ItWVic+i9Fp/7SJCY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qraB4FkXu0MRvezjxg8xqvjhADAVYfee7Z6HZNc9526nEaoTkfrG78vTb9UuT51/LPa5rn2Of+H5powXpxbnKdxKc8Fb8RH29E8Gh2MnyTD+QZSMqi5hbukdzSWU/wSOjsH42dCwhgA8jdNEDQteAbM7lopomsBQn3eRCL1ZGZ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=lFQm5esG; arc=none smtp.client-ip=209.85.160.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lFQm5esG" Received: by mail-oa1-f74.google.com with SMTP id 586e51a60fabf-2b1aa0c87daso105748fac.1 for ; Wed, 19 Feb 2025 17:21:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014483; x=1740619283; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hei31XB5q84gJBI2emRDlm0CWOqQ1amJYg+XT3qGNfs=; b=lFQm5esGjCXiotAtcIcw6jvQ7qxopNXzwqivydMc4EshMwetjI+WwOOaXJej1UTHfS a3kqXjQtOFHq/uNH/saSpKeHT5wJE2fjpmxYOzfCwF8gkYVMMti+P28yk0XDW1QupW9n /SKEGnZJIh4APyrXQ/6WjO+SJ9uh5fkf7fjqtZBC4OU34qk/E+t3Z5phwdnoTTIXcnbF QoZCL7dWT6mCgLjT8MXNOspUuF9MhuCJiUejQ0swxgjG1nzHoIDRaEkZmjFrNMmoR1aw 7sJ1GXUiRMSgBAjVlLxcJeluthI3O7k1qWJpY21FmRszBOt4vkfPr+VrQFwjeMegrqRz 1ypg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014483; x=1740619283; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hei31XB5q84gJBI2emRDlm0CWOqQ1amJYg+XT3qGNfs=; b=p77R6nLt3Yt5Q3Mbn9MTjqy2nkTl0nxl9fY/8nOIK94oHVD/L9GWwAD9GXXzryYZpD 15Z/5+2gApCum92H+iuL/DhDA37ETzuw6Fo+194Z73VDJqJuOx8R64DASUPpg9feLkZ+ UD+QjYAbXkWzKr3isPaISBvL+VtIBMaoDFFzVQHn0SZ1zXKD45chB1t3G/WXNXefR6vC YkK0bErSY8Ebao3FFBHmYA6G92KoH+CZzMxd9/XIuYpLA+zb3zLLsEvr+MYhESIjbYO5 6uiLg712XoS8aZtofPY55i+VbIXCecYtipshCWu3DKgjne3KFYBQIEoztQ7p6eCecCdY ojgg== X-Forwarded-Encrypted: i=1; AJvYcCVLnB5GNhtWhsSCjP5c3idu1P6jdJFe727IFTJ15MkiCYqrsrfvl/DnGmkBU0HpoA1uh0qOvw9YqqjbWaw=@vger.kernel.org X-Gm-Message-State: AOJu0YzqoZa0rCTLI/Ty8Vf03Kme4Be645nFhGZMQihSHfepmBhGpjVw RVozqRFw+/+NzxmYnzafkWNSPE9q5tZhk576EzzSXwr1qrYVCrxAgOaMK/AvY1GVwPoKg4vne72 P+LB8ca3VDQ== X-Google-Smtp-Source: AGHT+IGd2vxuU1amb7+qDvbCnYAoKOoMiZRrGABm5B0rQidw0j6221m951cHdyKwGYS7pdZw4DijvpwPVgm+Og== X-Received: from oablm17.prod.google.com ([2002:a05:6870:3d91:b0:2bc:69a2:abd1]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6870:fbaa:b0:29e:5de2:cffb with SMTP id 586e51a60fabf-2bc99b721admr13444186fac.17.1740014482734; Wed, 19 Feb 2025 17:21:22 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:19 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <6888a87af6ea47ea29d429b91a57cb146d1f69c8.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 5/9] arm64: insn: Add BIT(23) to {load,store}_ex's mask From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We are planning to add load-acquire (LDAR{,B,H}) and store-release (STLR{,B,H}) instructions to insn.{c,h}; add BIT(23) to mask of load_ex and store_ex to prevent aarch64_insn_is_{load,store}_ex() from returning false-positives for load-acquire and store-release instructions. Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a, ID032224), * C6.2.228 LDXR * C6.2.165 LDAXR * C6.2.161 LDAR * C6.2.393 STXR * C6.2.360 STLXR * C6.2.353 STLR Signed-off-by: Peilin Ye Acked-by: Xu Kuohai --- arch/arm64/include/asm/insn.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index e390c432f546..2d8316b3abaf 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -351,8 +351,8 @@ __AARCH64_INSN_FUNCS(ldr_imm, 0x3FC00000, 0x39400000) __AARCH64_INSN_FUNCS(ldr_lit, 0xBF000000, 0x18000000) __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000) __AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000) -__AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000) -__AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000) +__AARCH64_INSN_FUNCS(load_ex, 0x3FC00000, 0x08400000) +__AARCH64_INSN_FUNCS(store_ex, 0x3FC00000, 0x08000000) __AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400) __AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000) __AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000) --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF8F41AC88B for ; Thu, 20 Feb 2025 01:21:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014495; cv=none; b=X6FoASWBgo5H0hVvSocCyD97AoxfARd6XD8RLANjXd6Gqku71kxxJOUBxgbNlbPOOVSFEHwDpUx/kY6oNGFIofseTHDMFBaT3DW6tbIIsCTOtgD9hPjR6vl1Imac5ssgIl1rrh1wsKDL5jvidRAuaA/W0fzNu8IUXAKdU8iySM8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014495; c=relaxed/simple; bh=gF7uoug7KIdG4iVdYIiLh1+x0bJcYmr2AWleOtXDkqo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pli7noCW6YwrsUra6KXLE1a/NsZa+JX023ri/oEkuIKD/Cus2ghOisdTXIjThLfjiw+p+X8sJT6tl6flMP3n/KeQZYgzMAkM3F/53CjGMH6hE+jE6aWx8YSoMPNg3ceGx+lP1TGIl3jp6QoNBaF+SzSVD1HqwgdGDo1hJNhAqaI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=k9D3XmE5; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="k9D3XmE5" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2fc1e7efe00so1061128a91.2 for ; Wed, 19 Feb 2025 17:21:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014492; x=1740619292; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=OkZLa2X4XrqPLAsbeivrvq2/n6STf/0Lx6m+57nkDis=; b=k9D3XmE5Om1s6MteEcCvhchR6B808b3aGlt+zPdFuZRU2xhjlXR2rGRAcChUkBUpzM BKU2qq9ktXXecgPYv2e57UXMvaaUOr4z83J80VZUnhblkKEPbvKDGk1zVh18iCqa68Qk ohbw8efw4IB9rFNUtDqi/pklN6XL2C3fTiIDlgGAO3ozk1yEcSbbLDpNBMwelqU9MD3s cg0xZiaQ/p+gB7cKmeu69mnvAGJ/F+GA6VQyfJJvydl53BV/mxM4GO5GTW36Xxjrmol6 owE6zM1DNTh50oD//nbUHUIah2k833L/01STWPtgQPkf9Zc5a3A06nKGIhM3OKrEZaku YIkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014492; x=1740619292; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OkZLa2X4XrqPLAsbeivrvq2/n6STf/0Lx6m+57nkDis=; b=NZQYXW+dVioMaJbdAAjkC3bILX8X+N5V1Ovj4ahAD5SsVnns4SmL8AdMs51gTBhVdo 8eHGyW7BaHAmC1ONyxv9aulWR8tvnjM9DrOCciYJm3m/CngZkotNuRXrjyd/TiyAh18X Nnci0aIuLAZxU2mXeYQ2XCJJmFGmZZmOjPiHBfpTbgVlp+Dy3BMvpts90QUleCiHag2y NzJWaIMWBYXYTsTcOz9snIyzG9M0ku1Lc65+aog6AynavLP3gcFRUbzg9ZJW8QnRPwBE PDGqfiLTsvgnkqqTSFusiEMjUVGLFNFeoSzG892fDI5Qym+3pBDQuj3nC7SjspXU+C58 ZwUQ== X-Forwarded-Encrypted: i=1; AJvYcCUny8/Rzudoz0u+T1f7Mq3Y205Vk4AxjzFPHVmOljVh3yHfZurtKJ2/HEtI55qEuGuySXouD8GHEnb827M=@vger.kernel.org X-Gm-Message-State: AOJu0YwdNzGIysNllntKnoaQ5m1PyX2RumQA4EJMf7m4iDVqnSFKHlCO R3987w5qeF45o/ge+J5DUgu+pEwy8KWbjDxqjl6vK3K4ociYgew6QEnRt4br5CAeOzUeh78fAQr HC6f8hyEwKA== X-Google-Smtp-Source: AGHT+IFBxisbnr8xuVdH6zyqBX5cRFTXzSlnuc/uizTOJqWix9sLLV310uViRu8QUCqCKsN5Tzuuv6azaPxpIg== X-Received: from pjbhl4.prod.google.com ([2002:a17:90b:1344:b0:2fa:a101:755]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2d8d:b0:2ee:f076:20fb with SMTP id 98e67ed59e1d1-2fc40f22db2mr35640374a91.17.1740014492129; Wed, 19 Feb 2025 17:21:32 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:28 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: Subject: [PATCH bpf-next v3 6/9] arm64: insn: Add load-acquire and store-release instructions From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add load-acquire ("load_acq", LDAR{,B,H}) and store-release ("store_rel", STLR{,B,H}) instructions. Breakdown of encoding: size L (Rs) o0 (Rt2) Rn Rt mask (0x3fdffc00): 00 111111 1 1 0 11111 1 11111 00000 00000 value, load_acq (0x08dffc00): 00 001000 1 1 0 11111 1 11111 00000 00000 value, store_rel (0x089ffc00): 00 001000 1 0 0 11111 1 11111 00000 00000 As suggested by Xu [1], include all Should-Be-One (SBO) bits ("Rs" and "Rt2" fields) in the "mask" and "value" numbers. It is worth noting that we are adding the "no offset" variant of STLR instead of the "pre-index" variant, which has a different encoding. Reference: Arm Architecture Reference Manual (ARM DDI 0487K.a, ID032224), * C6.2.161 LDAR * C6.2.353 STLR [1] https://lore.kernel.org/bpf/4e6641ce-3f1e-4251-8daf-4dd4b77d08c4@huawei= cloud.com/ Signed-off-by: Peilin Ye Acked-by: Xu Kuohai --- arch/arm64/include/asm/insn.h | 8 ++++++++ arch/arm64/lib/insn.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 2d8316b3abaf..39577f1d079a 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -188,8 +188,10 @@ enum aarch64_insn_ldst_type { AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX, AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX, AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX, + AARCH64_INSN_LDST_LOAD_ACQ, AARCH64_INSN_LDST_LOAD_EX, AARCH64_INSN_LDST_LOAD_ACQ_EX, + AARCH64_INSN_LDST_STORE_REL, AARCH64_INSN_LDST_STORE_EX, AARCH64_INSN_LDST_STORE_REL_EX, AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET, @@ -351,6 +353,8 @@ __AARCH64_INSN_FUNCS(ldr_imm, 0x3FC00000, 0x39400000) __AARCH64_INSN_FUNCS(ldr_lit, 0xBF000000, 0x18000000) __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000) __AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000) +__AARCH64_INSN_FUNCS(load_acq, 0x3FDFFC00, 0x08DFFC00) +__AARCH64_INSN_FUNCS(store_rel, 0x3FDFFC00, 0x089FFC00) __AARCH64_INSN_FUNCS(load_ex, 0x3FC00000, 0x08400000) __AARCH64_INSN_FUNCS(store_ex, 0x3FC00000, 0x08000000) __AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400) @@ -602,6 +606,10 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn= _register reg1, int offset, enum aarch64_insn_variant variant, enum aarch64_insn_ldst_type type); +u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg, + enum aarch64_insn_register base, + enum aarch64_insn_size_type size, + enum aarch64_insn_ldst_type type); u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg, enum aarch64_insn_register base, enum aarch64_insn_register state, diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c index b008a9b46a7f..9bef696e2230 100644 --- a/arch/arm64/lib/insn.c +++ b/arch/arm64/lib/insn.c @@ -540,6 +540,35 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn= _register reg1, offset >> shift); } =20 +u32 aarch64_insn_gen_load_acq_store_rel(enum aarch64_insn_register reg, + enum aarch64_insn_register base, + enum aarch64_insn_size_type size, + enum aarch64_insn_ldst_type type) +{ + u32 insn; + + switch (type) { + case AARCH64_INSN_LDST_LOAD_ACQ: + insn =3D aarch64_insn_get_load_acq_value(); + break; + case AARCH64_INSN_LDST_STORE_REL: + insn =3D aarch64_insn_get_store_rel_value(); + break; + default: + pr_err("%s: unknown load-acquire/store-release encoding %d\n", + __func__, type); + return AARCH64_BREAK_FAULT; + } + + insn =3D aarch64_insn_encode_ldst_size(size, insn); + + insn =3D aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, + reg); + + return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, + base); +} + u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg, enum aarch64_insn_register base, enum aarch64_insn_register state, --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB6681CB501 for ; Thu, 20 Feb 2025 01:21:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014503; cv=none; b=Hc+Cgpm2qsDYWm1xEqcULOsMM/h9s+IMlyQPIFaSaU9pZ/bme0avL+lET+Or4YcJw5pB9zDvIOtrF/bhYTavkSaSGpbQOYKxiDq/1AtccqOHRDc23oBZ0PpAC7SUAeKd4+GdQ7ibtFP9CaKbwS+ESL89eHRwSuNHQFHl8qhn+zg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014503; c=relaxed/simple; bh=pBgZ7GKTEPrPJCVSTvUQ4t2AiqJ8Dxb9uCGJNugBe/U=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TtBX68bBhD3dB84CRa+c2t1crVf9WKXm5eywOCgGCM60AgFaRk4dtuDET+vhG13fW4o7Y/ukqPu060cyq/Xu1e2y2WbqYi+eynv59+RXbZp/ltVLLKEMcFi8t47Sr/eiL6b9fSq61m8CTS/e/bqdIGUKTpQfsau/Wur5oaAcPDY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=rHgEMd65; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="rHgEMd65" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2f83e54432dso1339685a91.2 for ; Wed, 19 Feb 2025 17:21:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014501; x=1740619301; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=HRokBdFyIsxwjYyPuPoZnXl/i3coJFiDhEdaQIrdZxE=; b=rHgEMd65TY9JbZgLTD5wXj7+GHQH4ny8nnNd5vOCQ7XmaDN3BPGcJXOfwgXHsoaS+j nFPIxMDsbXH0E7g5BUYIzD6x3NIDDTdDmkXOkDdALguEmeyO+bY+qWz1qgH/zIYMZSlk W9ZEOhko75KNZjQh+vvZrsqzhvLOQxDRHf5T34OeKq/HPZjaOGbYbXM6Ln0tJtUUDvmQ QT4p8BHqFh50J7uIiW7GPP1/wjPO4k5W3w7jL17M4R7xPi2rUq6gkhOQKC6PCWvZgBTD t9qhMsPAi0zd7rRjhvk1zmWK+MR9rNqmiLf0qrb6JHeMNv1n7XqtVAMj2SxU2rWVsN9X npKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014501; x=1740619301; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=HRokBdFyIsxwjYyPuPoZnXl/i3coJFiDhEdaQIrdZxE=; b=Xu+xHHUOvqYbPPQ4Zdf3Ity7JlpdAmOUgZcPCDcr/J5CwZpsr7XNP7dv9q8ybaP3Xh hI0PPZi5Ysg5D37kPqmojx1/mVCgHwkXsQJ/pUKZfnyO5aQZ1KmCQaBUkHv8Vge1uDgS USmupbLV+fgNlq/O7YoQzM+pFwgLhW4Gfb3JaB/C4ZA5K/uiB1vggTCf2z3BDxQpDlJ3 lQkt9bykhNOtJY46N6arEjoOJOCvCNsvNw+YK/eS6ZEp8mONyDhxtbB8TNy7tNk9r0Z0 KhZZ346eUcb4lVAPfc0tc2mCqx3RQRhmWvJsO2zeOMOif21JqtLrastk1FQ34dZoHnsl CMlg== X-Forwarded-Encrypted: i=1; AJvYcCXCp0MK/ywE6t3xlf7ZPvsd7pmG+7rmf/c8KA1gOSqh0CobYfVWdggB5oiJP3c2DthhO6PWkKWijRolDHs=@vger.kernel.org X-Gm-Message-State: AOJu0YyMnhekKK4JglBKR5WjkAqWmW5tEsPhmgm1eU83HA7m/Actvnai oRuc2AEZ2hTTmVSUYDOQIp0mmLFeudvDX7JHWxcf59AQEZTfvvuKsp4dIW6ylJxm1uI18Y002dw fD2BuvI5mmg== X-Google-Smtp-Source: AGHT+IFNurd9b6UniiPQLF2lFzdu8tbb5a5iv/5j1Y0Yr/iEYINiKPo7tMlFdpW6vp701jUL0SJcizCVoiFt1Q== X-Received: from pfbbx18.prod.google.com ([2002:a05:6a00:4292:b0:734:cc8:a107]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2e14:b0:730:74f8:25c1 with SMTP id d2e1a72fcca58-7329df228bbmr9065900b3a.15.1740014500927; Wed, 19 Feb 2025 17:21:40 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:35 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <2a45e43866e9ff2e53e3efd2675c0b027aa07aac.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 7/9] bpf, arm64: Support load-acquire and store-release instructions From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support BPF load-acquire (BPF_LOAD_ACQ) and store-release (BPF_STORE_REL) instructions in the arm64 JIT compiler. For example (assuming little-endian): db 10 00 00 00 01 00 00 r0 =3D load_acquire((u64 *)(r1 + 0x0)) 95 00 00 00 00 00 00 00 exit opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX imm (0x00000100): BPF_LOAD_ACQ The JIT compiler would emit an LDAR instruction for the above, e.g.: ldar x7, [x0] Similarly, consider the following 16-bit store-release: cb 21 00 00 10 01 00 00 store_release((u16 *)(r1 + 0x0), w2) 95 00 00 00 00 00 00 00 exit opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX imm (0x00000110): BPF_STORE_REL An STLRH instruction would be emitted, e.g.: stlrh w1, [x0] For a complete mapping: load-acquire 8-bit LDARB (BPF_LOAD_ACQ) 16-bit LDARH 32-bit LDAR (32-bit) 64-bit LDAR (64-bit) store-release 8-bit STLRB (BPF_STORE_REL) 16-bit STLRH 32-bit STLR (32-bit) 64-bit STLR (64-bit) Arena accesses are supported. bpf_jit_supports_insn(..., /*in_arena=3D*/true) always returns true for BPF_LOAD_ACQ and BPF_STORE_REL instructions, as they don't depend on ARM64_HAS_LSE_ATOMICS. Signed-off-by: Peilin Ye Acked-by: Xu Kuohai --- arch/arm64/net/bpf_jit.h | 20 ++++++++ arch/arm64/net/bpf_jit_comp.c | 91 ++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h index b22ab2f97a30..a3b0e693a125 100644 --- a/arch/arm64/net/bpf_jit.h +++ b/arch/arm64/net/bpf_jit.h @@ -119,6 +119,26 @@ aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \ AARCH64_INSN_LDST_STORE_REL_EX) =20 +/* Load-acquire & store-release */ +#define A64_LDAR(Rt, Rn, size) \ + aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \ + AARCH64_INSN_LDST_LOAD_ACQ) +#define A64_STLR(Rt, Rn, size) \ + aarch64_insn_gen_load_acq_store_rel(Rt, Rn, AARCH64_INSN_SIZE_##size, \ + AARCH64_INSN_LDST_STORE_REL) + +/* Rt =3D [Rn] (load acquire) */ +#define A64_LDARB(Wt, Xn) A64_LDAR(Wt, Xn, 8) +#define A64_LDARH(Wt, Xn) A64_LDAR(Wt, Xn, 16) +#define A64_LDAR32(Wt, Xn) A64_LDAR(Wt, Xn, 32) +#define A64_LDAR64(Xt, Xn) A64_LDAR(Xt, Xn, 64) + +/* [Rn] =3D Rt (store release) */ +#define A64_STLRB(Wt, Xn) A64_STLR(Wt, Xn, 8) +#define A64_STLRH(Wt, Xn) A64_STLR(Wt, Xn, 16) +#define A64_STLR32(Wt, Xn) A64_STLR(Wt, Xn, 32) +#define A64_STLR64(Xt, Xn) A64_STLR(Xt, Xn, 64) + /* * LSE atomics * diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 8c3b47d9e441..25562bdb8eb5 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -647,6 +647,82 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) return 0; } =20 +static int emit_atomic_load_store(const struct bpf_insn *insn, + struct jit_ctx *ctx) +{ + const s32 imm =3D insn->imm; + const s16 off =3D insn->off; + const u8 code =3D insn->code; + const bool arena =3D BPF_MODE(code) =3D=3D BPF_PROBE_ATOMIC; + const u8 arena_vm_base =3D bpf2a64[ARENA_VM_START]; + const u8 dst =3D bpf2a64[insn->dst_reg]; + const u8 src =3D bpf2a64[insn->src_reg]; + const u8 tmp =3D bpf2a64[TMP_REG_1]; + u8 reg; + + switch (imm) { + case BPF_LOAD_ACQ: + reg =3D src; + break; + case BPF_STORE_REL: + reg =3D dst; + break; + default: + pr_err_once("unknown atomic load/store op code %02x\n", imm); + return -EINVAL; + } + + if (off) { + emit_a64_add_i(1, tmp, reg, tmp, off, ctx); + reg =3D tmp; + } + if (arena) { + emit(A64_ADD(1, tmp, reg, arena_vm_base), ctx); + reg =3D tmp; + } + + switch (imm) { + case BPF_LOAD_ACQ: + switch (BPF_SIZE(code)) { + case BPF_B: + emit(A64_LDARB(dst, reg), ctx); + break; + case BPF_H: + emit(A64_LDARH(dst, reg), ctx); + break; + case BPF_W: + emit(A64_LDAR32(dst, reg), ctx); + break; + case BPF_DW: + emit(A64_LDAR64(dst, reg), ctx); + break; + } + break; + case BPF_STORE_REL: + switch (BPF_SIZE(code)) { + case BPF_B: + emit(A64_STLRB(src, reg), ctx); + break; + case BPF_H: + emit(A64_STLRH(src, reg), ctx); + break; + case BPF_W: + emit(A64_STLR32(src, reg), ctx); + break; + case BPF_DW: + emit(A64_STLR64(src, reg), ctx); + break; + } + break; + default: + pr_err_once("unexpected atomic load/store op code %02x\n", + imm); + return -EINVAL; + } + + return 0; +} + #ifdef CONFIG_ARM64_LSE_ATOMICS static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ct= x) { @@ -1641,11 +1717,17 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, return ret; break; =20 + case BPF_STX | BPF_ATOMIC | BPF_B: + case BPF_STX | BPF_ATOMIC | BPF_H: case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_DW: + case BPF_STX | BPF_PROBE_ATOMIC | BPF_B: + case BPF_STX | BPF_PROBE_ATOMIC | BPF_H: case BPF_STX | BPF_PROBE_ATOMIC | BPF_W: case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW: - if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) + if (bpf_atomic_is_load_store(insn)) + ret =3D emit_atomic_load_store(insn, ctx); + else if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) ret =3D emit_lse_atomic(insn, ctx); else ret =3D emit_ll_sc_atomic(insn, ctx); @@ -2667,13 +2749,10 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, b= ool in_arena) if (!in_arena) return true; switch (insn->code) { - case BPF_STX | BPF_ATOMIC | BPF_B: - case BPF_STX | BPF_ATOMIC | BPF_H: case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_DW: - if (bpf_atomic_is_load_store(insn)) - return false; - if (!cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) + if (!bpf_atomic_is_load_store(insn) && + !cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) return false; } return true; --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAB411BC07A for ; Thu, 20 Feb 2025 01:21:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014510; cv=none; b=GiN/w+i9K60YHdWR1/fNb+IN107wAsIot6Lhj/DmOAVedjRze4l+GhooEMq2R9duRqyDQsDcYtdFLrBtcjACMNYSIKuhaQcAbSu9qKYoKFQCK8QTZ+5pko2mIrfDwWMIYA3MUpZmkC5WuRgYckrJDQGXe2hHrLQkoKZmpMugLz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014510; c=relaxed/simple; bh=oTL/B4LEjWt3HVMp1OAK/nQ/K3AZSQc4JImyefedYt4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=e8p+vZtCqOaYMR/rAprCyNcEz2tWOU9KN6Jx2dUcknzLuBc70SryPkah2bhtPJP2r+m2buzdWR4YqJVBEkJ9x5WJUCtPzUk4xBzNKB6qTwzmd0mcOLy/OZFQpPz0TjPThAmer01AB9Fbtp0F1K0NakLJZLku3FAD3lucYktVoQs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nwi/cFus; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nwi/cFus" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-22114b800f0so11405415ad.1 for ; Wed, 19 Feb 2025 17:21:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014508; x=1740619308; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=YaAZC4Y9cb3/9hc1IyGufxM8kYldP/qANSMBUuWnSg0=; b=nwi/cFusrfvqazrRy3gGh6vDKzul+p+Un5adakI2MS8H9fuGVzweGKAq/BPxQiUGqc l/RmkzUpvZI0oz6hdHHNkjrywD0pGVAJIe7ZY/OquofJPd2ha3L/w3rXHa876s3M/DUG fn1Bc5J8mO0Rl4yAjubcF/POgWMefw4AthSrxMbk83npLVDfyue7i7BnuM39KBibfRik 1SSMwgFiiO6OyUTZ+F0Q9YXcNyH747upx9gnR/t720OK0PMiR1oI2Ut3H6QAKxgcXJzw Bib1stafvA5Ibkif0oDqVY3eA+AM2xzki0NEWPw+fxGsNS+vTmsHSiKCrQ5U9JYGBwpy 42VQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014508; x=1740619308; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YaAZC4Y9cb3/9hc1IyGufxM8kYldP/qANSMBUuWnSg0=; b=ZHB6HUmX4ViJ4rvvjkW1vT95s8i7KKvDCgCPzcKQIXzsN8q6rZRPEvIthf9/idTVe6 BJZwTn11I98B5QYZWtotTApyUF5bWjQ4/I6JbXkybrV+ee5fOU2vchl6U/ZSDTrdq1XX /jzLrj+pRIngTaN3azxLsp6TcZtTDu7ahVWg3M0yCl8TyyrliQyAUgFL058kJ3OHcIuu hMTb9DLjUQNaK5JFKtsZRZC+CZx3AyJbatI4kJXZlu7jkzEvv/ZGIAge68X3XdmjnqSn +vEgjHpdIiV+eNGIoeMFRCimmMZ8n8gzA/2ER4bK8uA2PjabCGdR4Ze0Um7BU95YA1qp trrg== X-Forwarded-Encrypted: i=1; AJvYcCUzDxROMzsg3mlaEQzNJGKDbQueUNhkVTVpoSGl03x5uZTyuZpip/4alsye/xW+RdIuMOc7eJ97cCNDHKc=@vger.kernel.org X-Gm-Message-State: AOJu0YyBituHeE9UrHPCDzNU0o851dbvPwn0SkOQa7pywSndPD5J6zHW /4yxN+hVIs1y9bfrb27R/k3Yrg9DgVzC98CV+PKDECs7OqqqU3vEJHxm992hGvKi3t+2VyjorAA 17PEZCOsfjA== X-Google-Smtp-Source: AGHT+IGLO29s6ui06UjI5Ru9wluZ+OUR3czf94i4Ult1q4q382vNrnp8hbjQyN4TATCIvmSxQw9JZCaOHf/F6Q== X-Received: from pjm15.prod.google.com ([2002:a17:90b:2fcf:b0:2f9:c3f4:dd36]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:d502:b0:21f:859a:9eab with SMTP id d9443c01a7336-221040a9a34mr314585215ad.37.1740014507878; Wed, 19 Feb 2025 17:21:47 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:44 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <4c48522a8bfa38b42a419560b2fb5a4eda89ce45.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 8/9] selftests/bpf: Add selftests for load-acquire and store-release instructions From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add several ./test_progs tests: - arena_atomics/load_acquire - arena_atomics/store_release - verifier_load_acquire/* - verifier_store_release/* - verifier_precision/bpf_load_acquire - verifier_precision/bpf_store_release The last two tests are added to check if backtrack_insn() handles the new instructions correctly. Additionally, the last test also makes sure that the verifier "remembers" the value (in src_reg) we store-release into e.g. a stack slot. For example, if we take a look at the test program: #0: r1 =3D 8; /* store_release((u64 *)(r10 - 8), r1); */ #1: .8byte %[store_release]; #2: r1 =3D *(u64 *)(r10 - 8); #3: r2 =3D r10; #4: r2 +=3D r1; #5: r0 =3D 0; #6: exit; At #1, if the verifier doesn't remember that we wrote 8 to the stack, then later at #4 we would be adding an unbounded scalar value to the stack pointer, which would cause the program to be rejected: VERIFIER LOG: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ... math between fp pointer and register with unbounded min value is not allo= wed For easier CI integration, instead of using built-ins like __atomic_{load,store}_n() which depend on the new __BPF_FEATURE_LOAD_ACQ_STORE_REL pre-defined macro, manually craft load-acquire/store-release instructions using __imm_insn(), as suggested by Eduard. All new tests depend on: (1) Clang major version >=3D 18, and (2) ENABLE_ATOMICS_TESTS is defined (currently implies -mcpu=3Dv3 or v4), and (3) JIT supports load-acquire/store-release (currently only arm64) In .../progs/arena_atomics.c: /* 8-byte-aligned */ __u8 __arena_global load_acquire8_value =3D 0x12; /* 1-byte hole */ __u16 __arena_global load_acquire16_value =3D 0x1234; That 1-byte hole in the .addr_space.1 ELF section caused clang-17 to crash: fatal error: error in backend: unable to write nop sequence of 1 bytes To work around such llvm-17 CI job failures, conditionally define __arena_global variables as 64-bit if __clang_major__ < 18, to make sure .addr_space.1 has no holes. Ideally we should avoid compiling this file using clang-17 at all (arena tests depend on __BPF_FEATURE_ADDR_SPACE_CAST, and are skipped for llvm-17 anyway), but that is a separate topic. Acked-by: Eduard Zingerman Signed-off-by: Peilin Ye --- .../selftests/bpf/prog_tests/arena_atomics.c | 66 ++++- .../selftests/bpf/prog_tests/verifier.c | 4 + .../selftests/bpf/progs/arena_atomics.c | 118 +++++++- .../bpf/progs/verifier_load_acquire.c | 197 +++++++++++++ .../selftests/bpf/progs/verifier_precision.c | 48 ++++ .../bpf/progs/verifier_store_release.c | 264 ++++++++++++++++++ 6 files changed, 694 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/verifier_load_acquire= .c create mode 100644 tools/testing/selftests/bpf/progs/verifier_store_releas= e.c diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools= /testing/selftests/bpf/prog_tests/arena_atomics.c index 26e7c06c6cb4..d98577a6babc 100644 --- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c +++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c @@ -162,6 +162,66 @@ static void test_uaf(struct arena_atomics *skel) ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails"); } =20 +static void test_load_acquire(struct arena_atomics *skel) +{ + LIBBPF_OPTS(bpf_test_run_opts, topts); + int err, prog_fd; + + if (skel->data->skip_lacq_srel_tests) { + printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support= addr_space_cast, and/or JIT doesn't support load-acquire\n", + __func__); + test__skip(); + return; + } + + /* No need to attach it, just run it directly */ + prog_fd =3D bpf_program__fd(skel->progs.load_acquire); + err =3D bpf_prog_test_run_opts(prog_fd, &topts); + if (!ASSERT_OK(err, "test_run_opts err")) + return; + if (!ASSERT_OK(topts.retval, "test_run_opts retval")) + return; + + ASSERT_EQ(skel->arena->load_acquire8_result, 0x12, + "load_acquire8_result"); + ASSERT_EQ(skel->arena->load_acquire16_result, 0x1234, + "load_acquire16_result"); + ASSERT_EQ(skel->arena->load_acquire32_result, 0x12345678, + "load_acquire32_result"); + ASSERT_EQ(skel->arena->load_acquire64_result, 0x1234567890abcdef, + "load_acquire64_result"); +} + +static void test_store_release(struct arena_atomics *skel) +{ + LIBBPF_OPTS(bpf_test_run_opts, topts); + int err, prog_fd; + + if (skel->data->skip_lacq_srel_tests) { + printf("%s:SKIP: ENABLE_ATOMICS_TESTS not defined, Clang doesn't support= addr_space_cast, and/or JIT doesn't support store-release\n", + __func__); + test__skip(); + return; + } + + /* No need to attach it, just run it directly */ + prog_fd =3D bpf_program__fd(skel->progs.store_release); + err =3D bpf_prog_test_run_opts(prog_fd, &topts); + if (!ASSERT_OK(err, "test_run_opts err")) + return; + if (!ASSERT_OK(topts.retval, "test_run_opts retval")) + return; + + ASSERT_EQ(skel->arena->store_release8_result, 0x12, + "store_release8_result"); + ASSERT_EQ(skel->arena->store_release16_result, 0x1234, + "store_release16_result"); + ASSERT_EQ(skel->arena->store_release32_result, 0x12345678, + "store_release32_result"); + ASSERT_EQ(skel->arena->store_release64_result, 0x1234567890abcdef, + "store_release64_result"); +} + void test_arena_atomics(void) { struct arena_atomics *skel; @@ -171,7 +231,7 @@ void test_arena_atomics(void) if (!ASSERT_OK_PTR(skel, "arena atomics skeleton open")) return; =20 - if (skel->data->skip_tests) { + if (skel->data->skip_all_tests) { printf("%s:SKIP:no ENABLE_ATOMICS_TESTS or no addr_space_cast support in= clang", __func__); test__skip(); @@ -198,6 +258,10 @@ void test_arena_atomics(void) test_xchg(skel); if (test__start_subtest("uaf")) test_uaf(skel); + if (test__start_subtest("load_acquire")) + test_load_acquire(skel); + if (test__start_subtest("store_release")) + test_store_release(skel); =20 cleanup: arena_atomics__destroy(skel); diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/test= ing/selftests/bpf/prog_tests/verifier.c index 8a0e1ff8a2dc..cfe47b529e01 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -45,6 +45,7 @@ #include "verifier_ldsx.skel.h" #include "verifier_leak_ptr.skel.h" #include "verifier_linked_scalars.skel.h" +#include "verifier_load_acquire.skel.h" #include "verifier_loops1.skel.h" #include "verifier_lwt.skel.h" #include "verifier_map_in_map.skel.h" @@ -80,6 +81,7 @@ #include "verifier_spill_fill.skel.h" #include "verifier_spin_lock.skel.h" #include "verifier_stack_ptr.skel.h" +#include "verifier_store_release.skel.h" #include "verifier_subprog_precision.skel.h" #include "verifier_subreg.skel.h" #include "verifier_tailcall_jit.skel.h" @@ -173,6 +175,7 @@ void test_verifier_int_ptr(void) { RUN(ver= ifier_int_ptr); } void test_verifier_iterating_callbacks(void) { RUN(verifier_iterating_cal= lbacks); } void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not= _null); } void test_verifier_jit_convergence(void) { RUN(verifier_jit_convergen= ce); } +void test_verifier_load_acquire(void) { RUN(verifier_load_acquire)= ; } void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); } void test_verifier_ldsx(void) { RUN(verifier_ldsx); } void test_verifier_leak_ptr(void) { RUN(verifier_leak_ptr); } @@ -211,6 +214,7 @@ void test_verifier_sockmap_mutate(void) { RUN(ver= ifier_sockmap_mutate); } void test_verifier_spill_fill(void) { RUN(verifier_spill_fill); } void test_verifier_spin_lock(void) { RUN(verifier_spin_lock); } void test_verifier_stack_ptr(void) { RUN(verifier_stack_ptr); } +void test_verifier_store_release(void) { RUN(verifier_store_release= ); } void test_verifier_subprog_precision(void) { RUN(verifier_subprog_preci= sion); } void test_verifier_subreg(void) { RUN(verifier_subreg); } void test_verifier_tailcall_jit(void) { RUN(verifier_tailcall_jit)= ; } diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/test= ing/selftests/bpf/progs/arena_atomics.c index 40dd57fca5cc..12de414156e1 100644 --- a/tools/testing/selftests/bpf/progs/arena_atomics.c +++ b/tools/testing/selftests/bpf/progs/arena_atomics.c @@ -6,6 +6,8 @@ #include #include #include "bpf_arena_common.h" +#include "../../../include/linux/filter.h" +#include "bpf_misc.h" =20 struct { __uint(type, BPF_MAP_TYPE_ARENA); @@ -19,9 +21,16 @@ struct { } arena SEC(".maps"); =20 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST) -bool skip_tests __attribute((__section__(".data"))) =3D false; +bool skip_all_tests __attribute((__section__(".data"))) =3D false; #else -bool skip_tests =3D true; +bool skip_all_tests =3D true; +#endif + +#if defined(ENABLE_ATOMICS_TESTS) && \ + defined(__BPF_FEATURE_ADDR_SPACE_CAST) && defined(__TARGET_ARCH_arm64) +bool skip_lacq_srel_tests __attribute((__section__(".data"))) =3D false; +#else +bool skip_lacq_srel_tests =3D true; #endif =20 __u32 pid =3D 0; @@ -274,4 +283,109 @@ int uaf(const void *ctx) return 0; } =20 +#if __clang_major__ >=3D 18 +__u8 __arena_global load_acquire8_value =3D 0x12; +__u16 __arena_global load_acquire16_value =3D 0x1234; +__u32 __arena_global load_acquire32_value =3D 0x12345678; +__u64 __arena_global load_acquire64_value =3D 0x1234567890abcdef; + +__u8 __arena_global load_acquire8_result =3D 0; +__u16 __arena_global load_acquire16_result =3D 0; +__u32 __arena_global load_acquire32_result =3D 0; +__u64 __arena_global load_acquire64_result =3D 0; +#else +/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around + * this issue by defining the below variables as 64-bit. + */ +__u64 __arena_global load_acquire8_value; +__u64 __arena_global load_acquire16_value; +__u64 __arena_global load_acquire32_value; +__u64 __arena_global load_acquire64_value; + +__u64 __arena_global load_acquire8_result; +__u64 __arena_global load_acquire16_result; +__u64 __arena_global load_acquire32_result; +__u64 __arena_global load_acquire64_result; +#endif + +SEC("raw_tp/sys_enter") +int load_acquire(const void *ctx) +{ +#if defined(ENABLE_ATOMICS_TESTS) && \ + defined(__BPF_FEATURE_ADDR_SPACE_CAST) && defined(__TARGET_ARCH_arm64) + +#define LOAD_ACQUIRE_ARENA(SIZEOP, SIZE, SRC, DST) \ + { asm volatile ( \ + "r1 =3D %[" #SRC "] ll;" \ + "r1 =3D addr_space_cast(r1, 0x0, 0x1);" \ + ".8byte %[load_acquire_insn];" \ + "r3 =3D %[" #DST "] ll;" \ + "r3 =3D addr_space_cast(r3, 0x0, 0x1);" \ + "*(" #SIZE " *)(r3 + 0) =3D r2;" \ + : \ + : __imm_addr(SRC), \ + __imm_insn(load_acquire_insn, \ + BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_LOAD_ACQ, \ + BPF_REG_2, BPF_REG_1, 0)), \ + __imm_addr(DST) \ + : __clobber_all); } \ + + LOAD_ACQUIRE_ARENA(B, u8, load_acquire8_value, load_acquire8_result) + LOAD_ACQUIRE_ARENA(H, u16, load_acquire16_value, + load_acquire16_result) + LOAD_ACQUIRE_ARENA(W, u32, load_acquire32_value, + load_acquire32_result) + LOAD_ACQUIRE_ARENA(DW, u64, load_acquire64_value, + load_acquire64_result) +#undef LOAD_ACQUIRE_ARENA + +#endif + return 0; +} + +#if __clang_major__ >=3D 18 +__u8 __arena_global store_release8_result =3D 0; +__u16 __arena_global store_release16_result =3D 0; +__u32 __arena_global store_release32_result =3D 0; +__u64 __arena_global store_release64_result =3D 0; +#else +/* clang-17 crashes if the .addr_space.1 ELF section has holes. Work around + * this issue by defining the below variables as 64-bit. + */ +__u64 __arena_global store_release8_result; +__u64 __arena_global store_release16_result; +__u64 __arena_global store_release32_result; +__u64 __arena_global store_release64_result; +#endif + +SEC("raw_tp/sys_enter") +int store_release(const void *ctx) +{ +#if defined(ENABLE_ATOMICS_TESTS) && \ + defined(__BPF_FEATURE_ADDR_SPACE_CAST) && defined(__TARGET_ARCH_arm64) + +#define STORE_RELEASE_ARENA(SIZEOP, DST, VAL) \ + { asm volatile ( \ + "r1 =3D " VAL ";" \ + "r2 =3D %[" #DST "] ll;" \ + "r2 =3D addr_space_cast(r2, 0x0, 0x1);" \ + ".8byte %[store_release_insn];" \ + : \ + : __imm_addr(DST), \ + __imm_insn(store_release_insn, \ + BPF_ATOMIC_OP(BPF_##SIZEOP, BPF_STORE_REL, \ + BPF_REG_2, BPF_REG_1, 0)) \ + : __clobber_all); } \ + + STORE_RELEASE_ARENA(B, store_release8_result, "0x12") + STORE_RELEASE_ARENA(H, store_release16_result, "0x1234") + STORE_RELEASE_ARENA(W, store_release32_result, "0x12345678") + STORE_RELEASE_ARENA(DW, store_release64_result, + "0x1234567890abcdef ll") +#undef STORE_RELEASE_ARENA + +#endif + return 0; +} + char _license[] SEC("license") =3D "GPL"; diff --git a/tools/testing/selftests/bpf/progs/verifier_load_acquire.c b/to= ols/testing/selftests/bpf/progs/verifier_load_acquire.c new file mode 100644 index 000000000000..529756501f10 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_load_acquire.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Google LLC. */ + +#include +#include +#include "../../../include/linux/filter.h" +#include "bpf_misc.h" + +#if __clang_major__ >=3D 18 && defined(ENABLE_ATOMICS_TESTS) && \ + defined(__TARGET_ARCH_arm64) + +SEC("socket") +__description("load-acquire, 8-bit") +__success __success_unpriv __retval(0x12) +__naked void load_acquire_8(void) +{ + asm volatile ( + "w1 =3D 0x12;" + "*(u8 *)(r10 - 1) =3D w1;" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u8 *)(r10 - 1)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -1)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire, 16-bit") +__success __success_unpriv __retval(0x1234) +__naked void load_acquire_16(void) +{ + asm volatile ( + "w1 =3D 0x1234;" + "*(u16 *)(r10 - 2) =3D w1;" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u16 *)(r10 - 2)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_H, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -2)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire, 32-bit") +__success __success_unpriv __retval(0x12345678) +__naked void load_acquire_32(void) +{ + asm volatile ( + "w1 =3D 0x12345678;" + "*(u32 *)(r10 - 4) =3D w1;" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u32 *)(r10 - 4)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -4)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire, 64-bit") +__success __success_unpriv __retval(0x1234567890abcdef) +__naked void load_acquire_64(void) +{ + asm volatile ( + "r1 =3D 0x1234567890abcdef ll;" + "*(u64 *)(r10 - 8) =3D r1;" + ".8byte %[load_acquire_insn];" // r0 =3D load_acquire((u64 *)(r10 - 8)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -8)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire with uninitialized src_reg") +__failure __failure_unpriv __msg("R2 !read_ok") +__naked void load_acquire_with_uninitialized_src_reg(void) +{ + asm volatile ( + ".8byte %[load_acquire_insn];" // r0 =3D load_acquire((u64 *)(r2 + 0)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire with non-pointer src_reg") +__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'") +__naked void load_acquire_with_non_pointer_src_reg(void) +{ + asm volatile ( + "r1 =3D 0;" + ".8byte %[load_acquire_insn];" // r0 =3D load_acquire((u64 *)(r1 + 0)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0)) + : __clobber_all); +} + +SEC("socket") +__description("misaligned load-acquire") +__failure __failure_unpriv __msg("misaligned stack access off") +__flag(BPF_F_ANY_ALIGNMENT) +__naked void load_acquire_misaligned(void) +{ + asm volatile ( + "r1 =3D 0;" + "*(u64 *)(r10 - 8) =3D r1;" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u32 *)(r10 - 5)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_W, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_10, -5)) + : __clobber_all); +} + +SEC("socket") +__description("load-acquire from ctx pointer") +__failure __failure_unpriv __msg("BPF_ATOMIC loads from R1 ctx is not allo= wed") +__naked void load_acquire_from_ctx_pointer(void) +{ + asm volatile ( + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u8 *)(r1 + 0)); + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_1, 0)) + : __clobber_all); +} + +SEC("xdp") +__description("load-acquire from pkt pointer") +__failure __msg("BPF_ATOMIC loads from R2 pkt is not allowed") +__naked void load_acquire_from_pkt_pointer(void) +{ + asm volatile ( + "r2 =3D *(u32 *)(r1 + %[xdp_md_data]);" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u8 *)(r2 + 0)); + "exit;" + : + : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)), + __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0)) + : __clobber_all); +} + +SEC("flow_dissector") +__description("load-acquire from flow_keys pointer") +__failure __msg("BPF_ATOMIC loads from R2 flow_keys is not allowed") +__naked void load_acquire_from_flow_keys_pointer(void) +{ + asm volatile ( + "r2 =3D *(u64 *)(r1 + %[__sk_buff_flow_keys]);" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u8 *)(r2 + 0)); + "exit;" + : + : __imm_const(__sk_buff_flow_keys, + offsetof(struct __sk_buff, flow_keys)), + __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0)) + : __clobber_all); +} + +SEC("sk_reuseport") +__description("load-acquire from sock pointer") +__failure __msg("BPF_ATOMIC loads from R2 sock is not allowed") +__naked void load_acquire_from_sock_pointer(void) +{ + asm volatile ( + "r2 =3D *(u64 *)(r1 + %[sk_reuseport_md_sk]);" + ".8byte %[load_acquire_insn];" // w0 =3D load_acquire((u8 *)(r2 + 0)); + "exit;" + : + : __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)), + __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_B, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_2, 0)) + : __clobber_all); +} + +#else + +SEC("socket") +__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/o= r JIT doesn't support load-acquire, use a dummy test") +__success +int dummy_test(void) +{ + return 0; +} + +#endif + +char _license[] SEC("license") =3D "GPL"; diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools= /testing/selftests/bpf/progs/verifier_precision.c index 6b564d4c0986..793fac62d63b 100644 --- a/tools/testing/selftests/bpf/progs/verifier_precision.c +++ b/tools/testing/selftests/bpf/progs/verifier_precision.c @@ -2,6 +2,7 @@ /* Copyright (C) 2023 SUSE LLC */ #include #include +#include "../../../include/linux/filter.h" #include "bpf_misc.h" =20 SEC("?raw_tp") @@ -90,6 +91,53 @@ __naked int bpf_end_bswap(void) ::: __clobber_all); } =20 +#if defined(ENABLE_ATOMICS_TESTS) && defined(__TARGET_ARCH_arm64) + +SEC("?raw_tp") +__success __log_level(2) +__msg("mark_precise: frame0: regs=3Dr2 stack=3D before 3: (bf) r3 =3D r10") +__msg("mark_precise: frame0: regs=3Dr2 stack=3D before 2: (db) r2 =3D load= _acquire((u64 *)(r10 -8))") +__msg("mark_precise: frame0: regs=3D stack=3D-8 before 1: (7b) *(u64 *)(r1= 0 -8) =3D r1") +__msg("mark_precise: frame0: regs=3Dr1 stack=3D before 0: (b7) r1 =3D 8") +__naked int bpf_load_acquire(void) +{ + asm volatile ( + "r1 =3D 8;" + "*(u64 *)(r10 - 8) =3D r1;" + ".8byte %[load_acquire_insn];" /* r2 =3D load_acquire((u64 *)(r10 - 8)); = */ + "r3 =3D r10;" + "r3 +=3D r2;" /* mark_precise */ + "r0 =3D 0;" + "exit;" + : + : __imm_insn(load_acquire_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_2, BPF_REG_10, -8)) + : __clobber_all); +} + +SEC("?raw_tp") +__success __log_level(2) +__msg("mark_precise: frame0: regs=3Dr1 stack=3D before 3: (bf) r2 =3D r10") +__msg("mark_precise: frame0: regs=3Dr1 stack=3D before 2: (79) r1 =3D *(u6= 4 *)(r10 -8)") +__msg("mark_precise: frame0: regs=3D stack=3D-8 before 1: (db) store_relea= se((u64 *)(r10 -8), r1)") +__msg("mark_precise: frame0: regs=3Dr1 stack=3D before 0: (b7) r1 =3D 8") +__naked int bpf_store_release(void) +{ + asm volatile ( + "r1 =3D 8;" + ".8byte %[store_release_insn];" /* store_release((u64 *)(r10 - 8), r1); */ + "r1 =3D *(u64 *)(r10 - 8);" + "r2 =3D r10;" + "r2 +=3D r1;" /* mark_precise */ + "r0 =3D 0;" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8)) + : __clobber_all); +} + +#endif /* load-acquire, store-release */ #endif /* v4 instruction */ =20 SEC("?raw_tp") diff --git a/tools/testing/selftests/bpf/progs/verifier_store_release.c b/t= ools/testing/selftests/bpf/progs/verifier_store_release.c new file mode 100644 index 000000000000..fd0aded3479e --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_store_release.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Google LLC. */ + +#include +#include +#include "../../../include/linux/filter.h" +#include "bpf_misc.h" + +#if __clang_major__ >=3D 18 && defined(ENABLE_ATOMICS_TESTS) && \ + defined(__TARGET_ARCH_arm64) + +SEC("socket") +__description("store-release, 8-bit") +__success __success_unpriv __retval(0x12) +__naked void store_release_8(void) +{ + asm volatile ( + "w1 =3D 0x12;" + ".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1); + "w0 =3D *(u8 *)(r10 - 1);" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -1)) + : __clobber_all); +} + +SEC("socket") +__description("store-release, 16-bit") +__success __success_unpriv __retval(0x1234) +__naked void store_release_16(void) +{ + asm volatile ( + "w1 =3D 0x1234;" + ".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1); + "w0 =3D *(u16 *)(r10 - 2);" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_H, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -2)) + : __clobber_all); +} + +SEC("socket") +__description("store-release, 32-bit") +__success __success_unpriv __retval(0x12345678) +__naked void store_release_32(void) +{ + asm volatile ( + "w1 =3D 0x12345678;" + ".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1); + "w0 =3D *(u32 *)(r10 - 4);" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -4)) + : __clobber_all); +} + +SEC("socket") +__description("store-release, 64-bit") +__success __success_unpriv __retval(0x1234567890abcdef) +__naked void store_release_64(void) +{ + asm volatile ( + "r1 =3D 0x1234567890abcdef ll;" + ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1); + "r0 =3D *(u64 *)(r10 - 8);" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8)) + : __clobber_all); +} + +SEC("socket") +__description("store-release with uninitialized src_reg") +__failure __failure_unpriv __msg("R2 !read_ok") +__naked void store_release_with_uninitialized_src_reg(void) +{ + asm volatile ( + ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r2); + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_2, -8)) + : __clobber_all); +} + +SEC("socket") +__description("store-release with uninitialized dst_reg") +__failure __failure_unpriv __msg("R2 !read_ok") +__naked void store_release_with_uninitialized_dst_reg(void) +{ + asm volatile ( + "r1 =3D 0;" + ".8byte %[store_release_insn];" // store_release((u64 *)(r2 - 8), r1); + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8)) + : __clobber_all); +} + +SEC("socket") +__description("store-release with non-pointer dst_reg") +__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'") +__naked void store_release_with_non_pointer_dst_reg(void) +{ + asm volatile ( + "r1 =3D 0;" + ".8byte %[store_release_insn];" // store_release((u64 *)(r1 + 0), r1); + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_1, BPF_REG_1, 0)) + : __clobber_all); +} + +SEC("socket") +__description("misaligned store-release") +__failure __failure_unpriv __msg("misaligned stack access off") +__flag(BPF_F_ANY_ALIGNMENT) +__naked void store_release_misaligned(void) +{ + asm volatile ( + "w0 =3D 0;" + ".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 5), w0); + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_0, -5)) + : __clobber_all); +} + +SEC("socket") +__description("store-release to ctx pointer") +__failure __failure_unpriv __msg("BPF_ATOMIC stores into R1 ctx is not all= owed") +__naked void store_release_to_ctx_pointer(void) +{ + asm volatile ( + "w0 =3D 0;" + ".8byte %[store_release_insn];" // store_release((u8 *)(r1 + 0), w0); + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_1, BPF_REG_0, 0)) + : __clobber_all); +} + +SEC("xdp") +__description("store-release to pkt pointer") +__failure __msg("BPF_ATOMIC stores into R2 pkt is not allowed") +__naked void store_release_to_pkt_pointer(void) +{ + asm volatile ( + "w0 =3D 0;" + "r2 =3D *(u32 *)(r1 + %[xdp_md_data]);" + ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); + "exit;" + : + : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)), + __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) + : __clobber_all); +} + +SEC("flow_dissector") +__description("store-release to flow_keys pointer") +__failure __msg("BPF_ATOMIC stores into R2 flow_keys is not allowed") +__naked void store_release_to_flow_keys_pointer(void) +{ + asm volatile ( + "w0 =3D 0;" + "r2 =3D *(u64 *)(r1 + %[__sk_buff_flow_keys]);" + ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); + "exit;" + : + : __imm_const(__sk_buff_flow_keys, + offsetof(struct __sk_buff, flow_keys)), + __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) + : __clobber_all); +} + +SEC("sk_reuseport") +__description("store-release to sock pointer") +__failure __msg("BPF_ATOMIC stores into R2 sock is not allowed") +__naked void store_release_to_sock_pointer(void) +{ + asm volatile ( + "w0 =3D 0;" + "r2 =3D *(u64 *)(r1 + %[sk_reuseport_md_sk]);" + ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); + "exit;" + : + : __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)), + __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) + : __clobber_all); +} + +SEC("socket") +__description("store-release, leak pointer to stack") +__success __success_unpriv __retval(0) +__naked void store_release_leak_pointer_to_stack(void) +{ + asm volatile ( + ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1); + "r0 =3D 0;" + "exit;" + : + : __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8)) + : __clobber_all); +} + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, long long); + __type(value, long long); +} map_hash_8b SEC(".maps"); + +SEC("socket") +__description("store-release, leak pointer to map") +__success __retval(0) +__failure_unpriv __msg_unpriv("R6 leaks addr into map") +__naked void store_release_leak_pointer_to_map(void) +{ + asm volatile ( + "r6 =3D r1;" + "r1 =3D %[map_hash_8b] ll;" + "r2 =3D 0;" + "*(u64 *)(r10 - 8) =3D r2;" + "r2 =3D r10;" + "r2 +=3D -8;" + "call %[bpf_map_lookup_elem];" + "if r0 =3D=3D 0 goto l0_%=3D;" + ".8byte %[store_release_insn];" // store_release((u64 *)(r0 + 0), r6); +"l0_%=3D:" + "r0 =3D 0;" + "exit;" + : + : __imm_addr(map_hash_8b), + __imm(bpf_map_lookup_elem), + __imm_insn(store_release_insn, + BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_0, BPF_REG_6, 0)) + : __clobber_all); +} + +#else + +SEC("socket") +__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/o= r JIT doesn't support store-release, use a dummy test") +__success +int dummy_test(void) +{ + return 0; +} + +#endif + +char _license[] SEC("license") =3D "GPL"; --=20 2.48.1.601.g30ceb7b040-goog From nobody Thu Dec 18 16:14:26 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90B721ADC69 for ; Thu, 20 Feb 2025 01:21:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014520; cv=none; b=lB6f2BnC0iNBECq3eSaJMNHM3UJOEMACbs/GCUx+nRm5k2JcpedUVBbklPxZtrt+VlVvpzH0PNFZ84pMhEUwmVmjSPeQY8wWsQTM9tXcW43YAL5c5GcmWI4zRlGAwKH3UvRc4rm72P0uUQc5Ri+PNc3Z6nW+txwkMXQBn3edPfc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740014520; c=relaxed/simple; bh=bPMoA+CFaJBzUEli+R/wxfQ9GKlfi77k+zzXMDFtLiA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KNSfL2I2Ho2puP8y1JBd4fnudiKbb34XHJqSlYdzH2TGYwQSnIcpG9kG5WcewiYtWi4ooWnD7qB9AdA4CzTO5R7YYVQ3uAX7u/GVNnoBbVcJ4hAaawFFX2sQ0Vk77leX0Fufdmlx9INbXeJUhkv3Yatl94duD4tf22bK40zPfdk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Erh0K0g2; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--yepeilin.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Erh0K0g2" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-22101351b1dso7139285ad.3 for ; Wed, 19 Feb 2025 17:21:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1740014518; x=1740619318; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=GS6vyNS6k+QCogrM+ZqTPx58CsLeQh5Yn8lInF1h/Hk=; b=Erh0K0g2rnAcYd9mni8GAJTqe+RFeGMPn/D3pfZsEWW/zgrKHkVGSiQZMxVXgP2X3y IToH7tqGtk/GroT9lNq0IfNR5Yrcym54g1k2vR3FpcBih0cFlwGSVhYAdcks1dAlNNvE /Q33ODaXf7vXrNLNC8cmUQI0mEMsjK+kNTErSwzy4qHkau2lqQk0jWVdDKAlmvF0gtVV rnIF3I+nluZ3ug+jR6+YORuIQKNC8ymQ9BQqeEzjnoGQxRbC35A0kN8QBWxlTKzO/10d KjLXl+qnClEXyazrb80IJGse9n5QwCvmtrjV+HnoYeMM8miyqoeqhr+JJuzep55JDXgv B7aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740014518; x=1740619318; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=GS6vyNS6k+QCogrM+ZqTPx58CsLeQh5Yn8lInF1h/Hk=; b=toHhXbyaMqYsIETkJ0HuCsSlA+0ej2VQJ9oZRIZaqNfNGWX8wH6RGPKx3DvybmOx20 qTvcIZXpzqJBGvw5s3Ct+4OfLzo3KoG4Ku/kKBSoCT2e9VgfdddDRV0fWp5hysKJA+Yz DbvhjafmaNSldTas24D4QLWo3oGVAzVz3jOur+H3hEOYra1/RWS1NCqKG+Vwz9JHQZ+U WjLxLp9Tfcs1dHxK8blqfRC6IYwWq/qVmPiPp8L0/M+cBv+mpuU428iFw6FNid4OsOYZ Ob/9m5JtWA0Azb1ud+dn+Ob0ShMngrAQ5SYN1h5zRLTtNT9COazTig4xGGMnYq2jrOWU iGUg== X-Forwarded-Encrypted: i=1; AJvYcCUZ9AlFktAdIzS4u8p8NTshWD+V+3FhDcHyFiTaOAxBMHBljnKvUh57ty0i1nFhrlEgBrUWghkVxxMHIns=@vger.kernel.org X-Gm-Message-State: AOJu0Yy20YsuftaprDX7Zec19hM5Vd0qu553+1PL3K7pei8UAXxw6eSJ 6ljhm6/RNAhLNS7SSRQAIgoxN2bpcr45cI00RAlUHCpDZXmUfi5v6AmIjOyigf24AzwivL8Iyp5 jcLDjkxUEpQ== X-Google-Smtp-Source: AGHT+IGJ+ltKK6y+HaMblCOKbNV2LzZDguEqlJAUdmJ+I1P4WWwmJBB8qhJ2SRtkJLX7OgW2ONsd+pG1Ym0kVA== X-Received: from plbkh4.prod.google.com ([2002:a17:903:644:b0:220:e392:340b]) (user=yepeilin job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:c94d:b0:215:6995:1ef3 with SMTP id d9443c01a7336-2217055ddc0mr83991925ad.3.1740014517696; Wed, 19 Feb 2025 17:21:57 -0800 (PST) Date: Thu, 20 Feb 2025 01:21:51 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.601.g30ceb7b040-goog Message-ID: <86e925a5f2bd1d5aa22ff604a505be1d2e88784c.1740009184.git.yepeilin@google.com> Subject: [PATCH bpf-next v3 9/9] bpf, docs: Update instruction-set.rst for load-acquire and store-release instructions From: Peilin Ye To: bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Peilin Ye , bpf@ietf.org, Xu Kuohai , Eduard Zingerman , David Vernet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Jonathan Corbet , "Paul E. McKenney" , Puranjay Mohan , Ilya Leoshkevich , Heiko Carstens , Vasily Gorbik , Catalin Marinas , Will Deacon , Quentin Monnet , Mykola Lysenko , Shuah Khan , Ihor Solodrai , Yingchi Long , Josh Don , Barret Rhoden , Neel Natu , Benjamin Segall , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update documentation for the new load-acquire and store-release instructions. Rename existing atomic operations as "atomic read-modify-write (RMW) operations". Following RFC 9669, section 7.3. "Adding Instructions", create new conformance groups "atomic32v2" and "atomic64v2", where: * atomic32v2: includes all instructions in "atomic32", plus the new 8-bit, 16-bit and 32-bit atomic load-acquire and store-release instructions * atomic64v2: includes all instructions in "atomic64" and "atomic32v2", plus the new 64-bit atomic load-acquire and store-release instructions Cc: bpf@ietf.org Signed-off-by: Peilin Ye --- .../bpf/standardization/instruction-set.rst | 78 +++++++++++++++---- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/Documentation/bpf/standardization/instruction-set.rst b/Docume= ntation/bpf/standardization/instruction-set.rst index ab820d565052..6bd62e79c4ed 100644 --- a/Documentation/bpf/standardization/instruction-set.rst +++ b/Documentation/bpf/standardization/instruction-set.rst @@ -139,8 +139,14 @@ This document defines the following conformance groups: specification unless otherwise noted. * base64: includes base32, plus instructions explicitly noted as being in the base64 conformance group. -* atomic32: includes 32-bit atomic operation instructions (see `Atomic ope= rations`_). -* atomic64: includes atomic32, plus 64-bit atomic operation instructions. +* atomic32: includes 32-bit atomic read-modify-write instructions (see + `Atomic operations`_). +* atomic32v2: includes atomic32, plus 8-bit, 16-bit and 32-bit atomic + load-acquire and store-release instructions. +* atomic64: includes atomic32, plus 64-bit atomic read-modify-write + instructions. +* atomic64v2: unifies atomic32v2 and atomic64, plus 64-bit atomic load-acq= uire + and store-release instructions. * divmul32: includes 32-bit division, multiplication, and modulo instructi= ons. * divmul64: includes divmul32, plus 64-bit division, multiplication, and modulo instructions. @@ -653,20 +659,29 @@ Atomic operations are operations that operate on memo= ry and can not be interrupted or corrupted by other access to the same memory region by other BPF programs or means outside of this specification. =20 -All atomic operations supported by BPF are encoded as store operations -that use the ``ATOMIC`` mode modifier as follows: +All atomic operations supported by BPF are encoded as ``STX`` instructions +that use the ``ATOMIC`` mode modifier, with the 'imm' field encoding the +actual atomic operation. These operations fall into two categories, as +described in the following sections: =20 -* ``{ATOMIC, W, STX}`` for 32-bit operations, which are +* `Atomic read-modify-write operations`_ +* `Atomic load and store operations`_ + +Atomic read-modify-write operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The atomic read-modify-write (RMW) operations are encoded as follows: + +* ``{ATOMIC, W, STX}`` for 32-bit RMW operations, which are part of the "atomic32" conformance group. -* ``{ATOMIC, DW, STX}`` for 64-bit operations, which are +* ``{ATOMIC, DW, STX}`` for 64-bit RMW operations, which are part of the "atomic64" conformance group. -* 8-bit and 16-bit wide atomic operations are not supported. +* 8-bit and 16-bit wide atomic RMW operations are not supported. =20 -The 'imm' field is used to encode the actual atomic operation. -Simple atomic operation use a subset of the values defined to encode -arithmetic operations in the 'imm' field to encode the atomic operation: +Simple atomic RMW operation use a subset of the values defined to encode +arithmetic operations in the 'imm' field to encode the atomic RMW operatio= n: =20 -.. table:: Simple atomic operations +.. table:: Simple atomic read-modify-write operations =20 =3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D imm value description @@ -686,10 +701,10 @@ arithmetic operations in the 'imm' field to encode th= e atomic operation: =20 *(u64 *)(dst + offset) +=3D src =20 -In addition to the simple atomic operations, there also is a modifier and -two complex atomic operations: +In addition to the simple atomic RMW operations, there also is a modifier = and +two complex atomic RMW operations: =20 -.. table:: Complex atomic operations +.. table:: Complex atomic read-modify-write operations =20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D imm value description @@ -699,8 +714,8 @@ two complex atomic operations: CMPXCHG 0xf0 | FETCH atomic compare and exchange =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =20 -The ``FETCH`` modifier is optional for simple atomic operations, and -always set for the complex atomic operations. If the ``FETCH`` flag +The ``FETCH`` modifier is optional for simple atomic RMW operations, and +always set for the complex atomic RMW operations. If the ``FETCH`` flag is set, then the operation also overwrites ``src`` with the value that was in memory before it was modified. =20 @@ -713,6 +728,37 @@ The ``CMPXCHG`` operation atomically compares the valu= e addressed by value that was at ``dst + offset`` before the operation is zero-extended and loaded back to ``R0``. =20 +Atomic load and store operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To encode an atomic load or store operation, the 'imm' field is one of: + +.. table:: Atomic load and store operations + + =3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + imm value description + =3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + LOAD_ACQ 0x100 atomic load-acquire + STORE_REL 0x110 atomic store-release + =3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +``{ATOMIC, , STX}`` with 'imm' =3D LOAD_ACQ means:: + + dst =3D load_acquire((unsigned size *)(src + offset)) + +``{ATOMIC, , STX}`` with 'imm' =3D STORE_REL means:: + + store_release((unsigned size *)(dst + offset), src) + +Where '' is one of: ``B``, ``H``, ``W``, or ``DW``, and 'unsigned si= ze' +is one of: u8, u16, u32, or u64. + +8-bit, 16-bit and 32-bit atomic load-acquire and store-release instructions +are part of the "atomic32v2" conformance group. + +64-bit atomic load-acquire and store-release instructions are part of the +"atomic64v2" conformance group. + 64-bit immediate instructions ----------------------------- =20 --=20 2.48.1.601.g30ceb7b040-goog