From nobody Mon Feb 9 04:28:49 2026 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (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 59F9428B512; Mon, 14 Apr 2025 19:28:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658939; cv=none; b=uFyQX2DSF7XuhQfyMQLzhHR6tkqx6nkSDsoRrvKyAHFL/Rp4jn1BALXkNLq20ljBVFgSaHjsbNRaGUx3LV1lXS4CUTT+wweFPfgsAvECYNkeTnIuo2E6FOGPYBxTMludjwjkS7IRotY41/Vz7gXpJ/Au/IJ5fvFBoDZas3xmSqU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658939; c=relaxed/simple; bh=nIqel8sF5aGOeh5Zf3p9yAVGtxyjMWnYFGuVyV7v7Ew=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JBiyxRbTZCR4P+ZF8VdmjIa1sAJraZGtRJaztfMxL07peEdlx37ynDHS/YhukwMxOOuVdgdo2MZX8KxiI/qVQgEfkvj+Pop/DpW/o5J1YNtiCtf9lG0IX3S+aBOqcRwejuAVjJfrqfq5oDMeEvYF/hOxvNh7SiReDdSaiAtPFHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KZdWI7B9; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KZdWI7B9" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-2243803b776so70436695ad.0; Mon, 14 Apr 2025 12:28:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744658936; x=1745263736; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=IMpKntOoWqOPI4F7pSZs0AGZGaf4Czl/zYkqLuKCY7Q=; b=KZdWI7B9BGFMh4AFnbpWDD9jrX9tFP1k9V7gwIIT7Kr4b66s+XzCWi6imb0kiD9QrL 4whdB9aStwaEpENG3fn7ltgLaBG9W1M6FVGQFr2v5Hut+WIhn4PqLVuPPxM0uCeunMTV resgvra0ffHuKepbLpzz6b29I1X0N6ka/ed5qs63VW3L99m54+R5yi/U4p46ebJvlj28 X+fmZPVTzR6WM55aUBdOGpqH01J2MwgzQoPEM4I8NO1CvRlLlAdiRF/gRz2V3YA0vYEU yzRtrN+YOc3eONmW+th5N4kHiVdNj9CFPGjflCj4GuBInDYAa39ACsI9LU1suFUksZtq 67Wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744658936; x=1745263736; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IMpKntOoWqOPI4F7pSZs0AGZGaf4Czl/zYkqLuKCY7Q=; b=NB3yH7RdDTxFWDMYd9e1FhoHF5sbVaVPovYLoti4wif+v/7YMVTJ9rERYxF6Shrz1u D3ZNu5IMz12f8nqvWj7Lj06jkKxBRfVA1jwnuvsWmmobSd4R6+5hvO88OAcOsZmDW4nU j2MJurktElae7kIQpqN/1ZTlStIjqoLb/GoYw3u3TCIrT2SD5kOkDt6g9ZvmmTDo3MiB f7QW910zS38rtvfIiywN5vDQ/TJVGe5I7bRZEh+hEA93ga83v43UsdPT9wPa7yz5UOJ5 GuOkn4Gr5OkZBCEBFTSIuypIMCfk913HmnNfWEBldNWNK2ZlW59mr7wKV6mEpiD1DkUD ix7g== X-Forwarded-Encrypted: i=1; AJvYcCWQiIGkvy8bGAOINK1/fzcdHUGVeAPCZr1ohYrRPbdRHyRQz7IGCaM213PNuckxEP8PbcUuAZPjUiZDE5vhIw==@vger.kernel.org X-Gm-Message-State: AOJu0Yxv2NO2JjCzfV5uGmIyuB5dYb7RUMSWrO7gsHOHwNM3ZGEBpkX/ bOjwRRotNqGrnspgNaZJD4pJaildnqQFmi027jRTTJ/T7pV/FtDs X-Gm-Gg: ASbGncu3+0Dbq2o06ub5YpppvNdZLpRMX2ULq+7lhEtlJwFlaOpYN3DEL1kwRANSAUK 4kqe2gw5Zpbze7Pt+3wVtNhx7iJG6apq9N5idaKRWltvP0Vw/Hxs/DDyPz9aB5b3jl610WLTL2S BEcZtJtCSFw1PWR5N9jNUgM3VNf5nB6vp6xMFr5NXqTaXvYm89SyxgEmC8aAQnLsUFI+qSIbnFe IRoWUnEK1+Z8X+xyqRa93LwWAcPyrltsW57Gb1pi0ckAp+yENTOeH3nMX2Tvr+nJp1eAVKkdnPK vwhTqPFfgWrDdhayrYte7sPdbv/6rU/4DdovlM9bBMV+y7B4/pQQ4Ag8ImL/oWiF X-Google-Smtp-Source: AGHT+IHUJqPv71XqfBEgk7CHyIk9qxNWnHSnPWRNgqr/BnZRpyU2Spq8ltezT/k0DZBEeCi+eGcGwg== X-Received: by 2002:a17:903:1a05:b0:224:256e:5e3f with SMTP id d9443c01a7336-22bea4bd566mr202083455ad.25.1744658936430; Mon, 14 Apr 2025 12:28:56 -0700 (PDT) Received: from mitchelllevy.localdomain ([131.107.174.166]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-73bd22f0f9bsm7223159b3a.104.2025.04.14.12.28.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 12:28:55 -0700 (PDT) From: Mitchell Levy Date: Mon, 14 Apr 2025 12:28:27 -0700 Subject: [PATCH RFC v2 1/3] rust: percpu: introduce a rust API for per-CPU variables Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250414-rust-percpu-v2-1-5ea0d0de13a5@gmail.com> References: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> In-Reply-To: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Andrew Morton , Dennis Zhou , Tejun Heo , Christoph Lameter , Danilo Krummrich Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-mm@kvack.org, Mitchell Levy X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744658935; l=13401; i=levymitchell0@gmail.com; s=20240719; h=from:subject:message-id; bh=nIqel8sF5aGOeh5Zf3p9yAVGtxyjMWnYFGuVyV7v7Ew=; b=vtj/4I/d40UsQeU/uI4V3EplUz1GsyP/yr1B8Vgqs8WIn8iPCtAwX4Vpq9mUNfcz8dklRhEtU Xg+yT3wyreEAwZwIxFAIz1oBDlHanTgy6ghc8aoRTddN/djbgBn0T3n X-Developer-Key: i=levymitchell0@gmail.com; a=ed25519; pk=n6kBmUnb+UNmjVkTnDwrLwTJAEKUfs2e8E+MFPZI93E= Add a CpuGuard type that disables preemption for its lifetime. Add a PerCpuAllocation type used to track and, in the case of dynamic allocations, create and free per-CPU allocations. Add a define_per_cpu! macro to create static per-CPU allocations. Add a PerCpu type that manages PerCpuAllocation's being used from multiple cores, and add a PerCpuToken type used to assert exclusive access to a particular per-CPU variable. Co-developed-by: Boqun Feng Signed-off-by: Boqun Feng Signed-off-by: Mitchell Levy --- rust/helpers/helpers.c | 2 + rust/helpers/percpu.c | 9 ++ rust/helpers/preempt.c | 14 +++ rust/kernel/lib.rs | 3 + rust/kernel/percpu.rs | 239 ++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/percpu/cpu_guard.rs | 29 +++++ 6 files changed, 296 insertions(+) diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index e1c21eba9b15..cff605710f77 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -23,7 +23,9 @@ #include "page.c" #include "platform.c" #include "pci.c" +#include "percpu.c" #include "pid_namespace.c" +#include "preempt.c" #include "rbtree.c" #include "rcu.c" #include "refcount.c" diff --git a/rust/helpers/percpu.c b/rust/helpers/percpu.c new file mode 100644 index 000000000000..a091389f730f --- /dev/null +++ b/rust/helpers/percpu.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void __percpu *rust_helper_alloc_percpu(size_t sz, size_t align) +{ + return __alloc_percpu(sz, align); +} + diff --git a/rust/helpers/preempt.c b/rust/helpers/preempt.c new file mode 100644 index 000000000000..2c7529528ddd --- /dev/null +++ b/rust/helpers/preempt.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_preempt_disable(void) +{ + preempt_disable(); +} + +void rust_helper_preempt_enable(void) +{ + preempt_enable(); +} + diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index de07aadd1ff5..dc88becdb338 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -67,6 +67,9 @@ pub mod page; #[cfg(CONFIG_PCI)] pub mod pci; +// Only x86_64 is supported by percpu for now +#[cfg(CONFIG_X86_64)] +pub mod percpu; pub mod pid_namespace; pub mod platform; pub mod prelude; diff --git a/rust/kernel/percpu.rs b/rust/kernel/percpu.rs new file mode 100644 index 000000000000..ecce8cdaa22a --- /dev/null +++ b/rust/kernel/percpu.rs @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +//! This module contains abstractions for creating and using per-CPU varia= bles from Rust. +//! See the define_per_cpu! macro and the PerCpu type. +pub mod cpu_guard; + +use bindings::{alloc_percpu, free_percpu}; + +use crate::percpu::cpu_guard::CpuGuard; +use crate::prelude::*; +use crate::sync::Arc; + +use core::arch::asm; +use core::marker::PhantomData; + +use ffi::c_void; + +/// Represents an allocation of a per-CPU variable via alloc_percpu or a s= tatic per-CPU +/// allocation. Calls free_percpu when dropped if not a static allocation. +pub struct PerCpuAllocation { + /// Offset into the per-CPU area: either the address of a statically-a= llocated per-CPU variable + /// or a "pointer" returned by alloc_percpu or similar. + offset: usize, + /// Whether `self` is statically allocated + is_static: bool, + /// PhantomData so the compiler doesn't complain about `T` being unuse= d. + deref_type: PhantomData, +} + +/// Holds a per-CPU variable. +pub struct PerCpu { + alloc: Arc>, +} + +/// Represents exclusive access to the memory location pointed at by a par= ticular PerCpu. +pub struct PerCpuToken<'a, T> { + _guard: CpuGuard, + pcpu: &'a mut PerCpu, +} + +/// A wrapper used for declaring static per-CPU variables. These symbols a= re "virtual" in that the +/// linker uses them to generate offsets into each cpu's per-cpu area, but= shouldn't be read +/// from/written to directly. The fact that the statics are immutable prev= ents them being written +/// to (generally), this struct having _val be non-public prevents reading= from them. +/// +/// The end-user of the per-CPU API should make use of the define_per_cpu!= macro instead of +/// declaring variables of this type directly. +#[repr(transparent)] +pub struct StaticPerCpuSymbol { + _val: T, // generate a correctly sized type +} + +impl PerCpuAllocation { + /// Dynamically allocates a space in the per-CPU area suitably sized a= nd aligned to hold a `T`. + /// + /// Returns `None` under the same circumstances the C function `alloc_= percpu` returns `NULL`. + pub fn new() -> Option> { + // SAFETY: No preconditions to call alloc_percpu + let ptr: *mut c_void =3D unsafe { alloc_percpu(size_of::(), ali= gn_of::()) }; + if ptr.is_null() { + return None; + } + + Some(Self { + offset: ptr as usize, + is_static: false, + deref_type: PhantomData, + }) + } + + /// Convert a statically allocated per-CPU variable (via its offset, i= .e., the address of the + /// declared symbol) into a `PerCpuAllocation`. + /// + /// # Safety + /// `offset` must be a valid offset into the per-CPU area that's suita= bly sized and aligned to + /// hold a `T`. + pub unsafe fn new_static(offset: usize) -> PerCpuAllocation { + Self { + offset, + is_static: true, + deref_type: PhantomData, + } + } +} + +impl Drop for PerCpuAllocation { + fn drop(&mut self) { + if !self.is_static { + // SAFETY: self.offset was returned by alloc_percpu, and so wa= s a valid pointer into + // the percpu area, and has remained valid by the invariants o= f PerCpuAllocation. + unsafe { free_percpu(self.offset as *mut c_void) } + } + } +} + +impl PerCpu { + /// Allocates a new per-CPU variable + pub fn new() -> Option { + let alloc: PerCpuAllocation =3D PerCpuAllocation::new()?; + + let arc =3D Arc::new(alloc, GFP_KERNEL).ok()?; + + Some(Self { alloc: arc }) + } + + /// Wraps a `PerCpuAllocation` in a `PerCpu` + pub fn new_from_allocation(alloc: PerCpuAllocation) -> Option= { + let arc =3D Arc::new(alloc, GFP_KERNEL).ok()?; + Some(Self { alloc: arc }) + } + + /// Creates a new PerCpu pointing to the same underlying variable + pub fn clone(&self) -> Self { + Self { + alloc: self.alloc.clone(), + } + } + + /// Get a `&mut T` to the per-CPU variable represented by `&mut self` + /// + /// # Safety + /// The returned `&mut T` must follow Rust's aliasing rules. That is, = no other `&(mut) T` may + /// exist that points to the same location in memory. In practice, thi= s means that any PerCpu + /// holding a reference to the same PerCpuAllocation as `self` mut not= call `get_ref` for as + /// long as the returned reference lives. + unsafe fn get_ref(&mut self) -> &mut T { + // SAFETY: addr_of!(this_cpu_off) is guaranteed to be a valid per-= CPU offset by the per-CPU + // subsystem + let this_cpu_off_pcpu: PerCpuAllocation =3D + unsafe { PerCpuAllocation::new_static(core::ptr::addr_of!(this= _cpu_off) as usize) }; + let mut this_cpu_area: *mut c_void; + // SAFETY: gs + this_cpu_off_pcpu.offset is guaranteed to be a val= id pointer because `gs` + // points to the per-CPU area and this_cpu_off_pcpu is a valid per= -CPU allocation. + unsafe { + asm!( + // For some reason, the asm! parser doesn't like + // mov {out}, [gs:{off_val}] + // so we use the less intuitive prefix version instead + "gs mov {out}, [{off_val}]", + off_val =3D in(reg) this_cpu_off_pcpu.offset, + out =3D out(reg) this_cpu_area, + ) + }; + // SAFETY: this_cpu_area + self.alloc.offset is guaranteed to be a= valid pointer by the + // per-CPU subsystem and the invariant that self.offset is a valid= offset into the per-CPU + // area. + // + // We have exclusive access to self via &mut self, so we know no-o= ne else has a reference + // to the underlying pcpu variable because of the safety requireme= nts of this function. + unsafe { &mut *((this_cpu_area.add(self.alloc.offset)) as *mut T) } + } + + /// Produces a token, asserting that the holder has exclusive access t= o the underlying memory + /// pointed to by `self` + /// + /// # Safety + /// `func` (or its callees that execute on the same CPU) may not call = `get_ref` on another + /// `PerCpu` that represents the same per-CPU variable as `&mut sel= f` (that is, they must + /// not be `clone()`s of each other or, in the case of statically allo= cated variables, + /// additionally can't both have come from the same `define_per_cpu!`)= for the lifetime of the + /// returned token. + /// + /// In particular, this requires that the underlying per-CPU variable = cannot ever be mutated + /// from an interrupt context, unless irqs are disabled for the lifeti= me of the returned + /// `PerCpuToken`. + pub unsafe fn get(&mut self, guard: CpuGuard) -> PerCpuToken<'_, T> { + PerCpuToken { + _guard: guard, + pcpu: self, + } + } +} + +impl PerCpuToken<'_, T> { + /// Immediately invokes `func` with a `&mut T` that points at the unde= rlying per-CPU variable + /// that `&mut self` represents. + pub fn with(&mut self, func: U) + where + U: FnOnce(&mut T), + { + // SAFETY: The existence of a PerCpuToken means that the requireme= nts for get_ref are + // satisfied. + func(unsafe { self.pcpu.get_ref() }); + } +} + +/// define_per_cpu! is analogous to the C DEFINE_PER_CPU macro in that it = lets you create a +/// statically allocated per-CPU variable. +/// +/// # Example +/// ``` +/// use kernel::define_per_cpu; +/// use kernel::percpu::StaticPerCpuSymbol; +/// +/// define_per_cpu!(pub MY_PERCPU: u64 =3D 0); +/// ``` +#[macro_export] +macro_rules! define_per_cpu { + ($vis:vis $id:ident: $ty:ty =3D $expr:expr) =3D> { + $crate::macros::paste! { + // Expand $expr outside of the unsafe block to avoid silently = allowing unsafe code to be + // used without a user-facing unsafe block + static [<__INIT_ $id>]: $ty =3D $expr; + + // SAFETY: StaticPerCpuSymbol is #[repr(transparent)], so w= e can freely convert from T + #[link_section =3D ".data..percpu"] + $vis static $id: StaticPerCpuSymbol<$ty> =3D unsafe { + core::mem::transmute::<$ty, StaticPerCpuSymbol<$ty>>([<__I= NIT_ $id>]) + }; + } + }; +} + +/// Gets a `PerCpu` from a symbol declared with `define_per_cpu!` or `d= eclare_extern_per_cpu!`. +/// +/// # Safety +/// `$id` must be declared with either `define_per_cpu!` or `declare_exter= n_per_cpu!`, and the +/// returned value must be stored in a `PerCpu` where `T` matches the d= eclared type of `$id`. +#[macro_export] +macro_rules! unsafe_get_per_cpu { + ($id:ident, $guard:expr) =3D> {{ + let off =3D core::ptr::addr_of!($id); + $crate::percpu::PerCpu::new_from_allocation($crate::percpu::PerCpu= Allocation::new_static( + off as usize, + )) + }}; +} + +/// Declares a StaticPerCpuSymbol corresponding to a per-CPU variable defi= ned in C. Be sure to read +/// the safety requirements of `PerCpu::get`. +#[macro_export] +macro_rules! declare_extern_per_cpu { + ($id:ident: $ty:ty) =3D> { + extern "C" { + static $id: StaticPerCpuSymbol<$ty>; + } + }; +} + +declare_extern_per_cpu!(this_cpu_off: u64); diff --git a/rust/kernel/percpu/cpu_guard.rs b/rust/kernel/percpu/cpu_guard= .rs new file mode 100644 index 000000000000..6f7d320a5c9a --- /dev/null +++ b/rust/kernel/percpu/cpu_guard.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Contains abstractions for disabling CPU preemption. See CpuGuard. + +/// A RAII guard for bindings::preempt_disable and bindings::preempt_enabl= e. Guarantees preemption +/// is disabled for as long as this object exists. +pub struct CpuGuard { + // Don't make one without using new() + _phantom: (), +} + +impl CpuGuard { + /// Create a new CpuGuard. Disables preemption for its lifetime. + pub fn new() -> Self { + // SAFETY: There are no preconditions required to call preempt_dis= able + unsafe { + bindings::preempt_disable(); + } + CpuGuard { _phantom: () } + } +} + +impl Drop for CpuGuard { + fn drop(&mut self) { + // SAFETY: There are no preconditions required to call preempt_ena= ble + unsafe { + bindings::preempt_enable(); + } + } +} --=20 2.34.1 From nobody Mon Feb 9 04:28:49 2026 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (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 3371828BAA1; Mon, 14 Apr 2025 19:28:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658939; cv=none; b=EyQtvOX6N7mQG+PGOyDNTz3f0TyEetczTmIG+W+zvm92plTCtGzNRyJztI0fTs2u2lMF2Aqm89bxPwiBXKdKtyOB37YQCHaWjJNoOpcqs6h6+031gFnBqM2OprcT0y7urGgFs9dlUq9ltirf+fpBiRoEL5hKh7jlIxdCJM7lMA0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658939; c=relaxed/simple; bh=qMkte7lQcKY3s751CE5wL/z+0AJKVlVS07EzLc0WsFA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tS5ffIeIFp03rDP6EZc9BQdvW4TRcgvoXwR7JkZ8yQN3SL4smF6cbeHILb6eBsuy/lKLqxSFrHHX1h7CLhj81aSJ8vSaWV+dSAYuUqTIL9L6QrWxCOBxRVbqKlk9d5hQOsLQBubQLujnT1WdOvCfZQXzNWKo6I46oPDvl+Huu9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ONUOe5n6; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ONUOe5n6" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-739525d4e12so4294714b3a.3; Mon, 14 Apr 2025 12:28:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744658937; x=1745263737; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=9tZ2dPLybpFH5FVRU54a2SFS8qh5x40EXdBFzij59yI=; b=ONUOe5n6AtmO2+xaKvvIZns5L854QPvwNRLrmbYYfKS2sOw0/3z9WUnOhNoR3VJ1s+ VF/Hjx4BwOfSEHg2XZEkgAxhFmZKk8Du5P2WNTcLM7cRQ3w9ypguCDPrUkutm3Z6KJ9i b5zG92cFr/lMvC+FuA1PC4EguG9A9exr5/HU9ARp/dLwVphcFI8hYenbdnf8FDok8MvN h0Vkfl1gtY4P5y5eVrytDIuTGEHvJs/Sy2Q0mvQ1XQiqf2cNIkWosqVCy8kIjWXs+GFG JMiS4TDQsIVA0GSA8jy6AGK0UCC4LzGaD5Bvupd3g12uC9uovxTfN3MSIC2lW2cmXsNc d4dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744658937; x=1745263737; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9tZ2dPLybpFH5FVRU54a2SFS8qh5x40EXdBFzij59yI=; b=heEbCCM55G2RyYH24ewlXVcmg6lV6R+eUzj5nadHnp9f2BqlxtYHrqy2/w2e6/JDY7 ZjQGaV1I87CVvOabanRjeVSmz3Wu5damfqqcUxJqoyzPIHXInudQnJd7AA9fZ2ql8Owr fl9FpN+P+PJVGH0dCU3fiVT3ZLjxp0M68ve6isbGeAo+bz2OF+l2l0hAjzaqWeq8h78c SlKydUtwjlkFJm8zXfEF0MLufA/wveztgAQVfzTpNObbTiGfrjJ8x+n0AtXkMxC+OeVv kOsW3Jg0vT2MNK1fN9heA9/5vHA+tVLZ9FGmUzQ0uQv1Al4V4C8bOXtwmpDar3f4ODYy dE3A== X-Forwarded-Encrypted: i=1; AJvYcCWNrNPKuP9K+jYH9j11MkTd2+1Z110jJwIY4rzRuvuziaVEhSqDGVs5dxYFH/k9Wm4oQWenUZBPjbXAty7ZnA==@vger.kernel.org X-Gm-Message-State: AOJu0YzV1IMzovaIvpR/uHRSKMRyXLdQvYIgG6SKHVGs9Bp09NFFiJ9T 4HD1Y1E1zpYCcOvDC8ZmJrHn9j4YVj+jT3mDLG2xaHL3wsNt1f1f X-Gm-Gg: ASbGncsPNigZSpZd54OxOp49jt0YmdxvrussnIyjILpIa+mSRvuy4vafPIr7jTy+gy3 KbcPUQIwR0v6vLUmtPqew9xNu1DNJA5Fu5GnVOY6YInx2VmlQXCrTquZBlJcMPyUz5HYfYNJkH0 R5Y9ByXxRltQxuhTqDtmCESIWF2Cqoleifk6TDdSy+fTt1o5d2wKfW/1EO/6n9LWqlETvmTeFxM i482E6Na6dI3oZ9F7FhUpzYltWCWD4vqr5/zWyIwr4LraBGnAGh/9a3IE2sDRBqvVU4dGlZxoPD C81gHy412FKpfM6EOQBTmnGZ0V04PpEzM4RCwrSCQ2w+kPrF3Leb1/qHqyo4EgaX X-Google-Smtp-Source: AGHT+IHNsXgFEF42nADS/UEbwfqqQqsK38WQnUsa1NV3hLJUt4/dinwpHaCiM2CxnuGQt8oLrfB1Qg== X-Received: by 2002:a05:6a00:4608:b0:736:b101:aed3 with SMTP id d2e1a72fcca58-73bd11aa506mr17054183b3a.1.1744658937299; Mon, 14 Apr 2025 12:28:57 -0700 (PDT) Received: from mitchelllevy.localdomain ([131.107.174.166]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-73bd22f0f9bsm7223159b3a.104.2025.04.14.12.28.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 12:28:56 -0700 (PDT) From: Mitchell Levy Date: Mon, 14 Apr 2025 12:28:28 -0700 Subject: [PATCH RFC v2 2/3] rust: rust-analyzer: add lib to dirs searched for crates Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250414-rust-percpu-v2-2-5ea0d0de13a5@gmail.com> References: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> In-Reply-To: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Andrew Morton , Dennis Zhou , Tejun Heo , Christoph Lameter , Danilo Krummrich Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-mm@kvack.org, Mitchell Levy X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744658935; l=916; i=levymitchell0@gmail.com; s=20240719; h=from:subject:message-id; bh=qMkte7lQcKY3s751CE5wL/z+0AJKVlVS07EzLc0WsFA=; b=qV2E9+YzEfKW88KWUTSZdiWloPv2Cl5usdUnZpdm0I2jIxgzKhCyVQEpFKenWhASbeTtyfnQM kAxUKxjrDo5Ddlx6Ndjlgk1ZhpZY5SSKTQl68U8H9o3CPbUXi0Xnq7C X-Developer-Key: i=levymitchell0@gmail.com; a=ed25519; pk=n6kBmUnb+UNmjVkTnDwrLwTJAEKUfs2e8E+MFPZI93E= When generating rust-project.json, also include crates in lib/ Signed-off-by: Mitchell Levy --- scripts/generate_rust_analyzer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_anal= yzer.py index cd41bc906fbd..64c5283a509f 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -144,7 +144,7 @@ def generate_crates(srctree, objtree, sysroot_src, exte= rnal_src, cfgs): # Then, the rest outside of `rust/`. # # We explicitly mention the top-level folders we want to cover. - extra_dirs =3D map(lambda dir: srctree / dir, ("samples", "drivers")) + extra_dirs =3D map(lambda dir: srctree / dir, ("samples", "drivers", "= lib")) if external_src is not None: extra_dirs =3D [external_src] for folder in extra_dirs: --=20 2.34.1 From nobody Mon Feb 9 04:28:49 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (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 E6B4128DEEC; Mon, 14 Apr 2025 19:28:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658940; cv=none; b=Q4/LqT7Cx/+d0hIZLhfUzOPDuSMacJzhhjk0yJVWAfneLbKxxVZVbHCDCMatStWQQ4KHWMZ6KQheF7zjbGMWOZNX7VlrWi+I2LhM6VcapyPoyt0k5igAuDRpPFMKCJeeFm1LiexEnOV1ob9UFIwsXKHS88mvd66bPjz05XTpdaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744658940; c=relaxed/simple; bh=jCbJ9Ju2A01cc4n5ifjcDJwihXlezFkUcuPbDwroyfA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VJnUjO9Fbz6ibu+lQ7W8ohzyumFTzbTfPvurXt+zjOCDe49kQitXbPbLwH8Bp6j0BIJUN0n99S01xt63SDY69JdtB54VHcGhMOsrqa2ov+NQs7L1IwPzSqvhdAxMWJ7iyJNdeA3HpfeWGSr5D1fSuqj1/FCiC2tuo+Embe77hL4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=H/k2Am3r; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="H/k2Am3r" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-73bb647eb23so4221133b3a.0; Mon, 14 Apr 2025 12:28:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744658938; x=1745263738; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=R/mennYIPZF3DS9iChk0/U5hjKR2MUh3UXar0f5WEiM=; b=H/k2Am3rvKnqdK8LFvV9lTBNQU9YPyGgOasHTssOMyQEC9HINa7FKdXpp/dacpx6ZK Ta3gG2QRCkUiW/rwYJFtkfs2ai/wihu0uczr9nlUCt5AjoWyhd+ZChqgIY2q5Xh9l8rv BEz7v1s/wv+EHNg5lPhbsyPK9m8jdguGIdfUj1FGbTW4yx+6HJbDjAcZlTvYm1e3XLor /DbEDskAVUVNflYZC0Zfx97TaTW4f6NGl3HBkkbNY869DwE/XUA7WRQGgwNH5wqvDK2S nhSLRQjjq5jlBopdYz0wzMul3p+TmFO49ozFFk2crPK9TAnxfl24Pu45Ln+fvKtv1dXu WO8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744658938; x=1745263738; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R/mennYIPZF3DS9iChk0/U5hjKR2MUh3UXar0f5WEiM=; b=EFT3I8r9Mtw7u+htXGFPa7nCI9SCAol2ZqX77Vpk9Mt+VWr1Vdw+jtMqCeusmQs8IL hXC8yGGF90ArLOjj6YIISH+T1H2FggUcNxQBtn/RWy5GlarAXlDuRKjnewTcigbGFUGM M1B4CT3zIVNulXOjSfJZdk6n2+U8cV/97uS7jn9EghR/8l6cyP8+C3EOMGmbW9QiZDj3 MIkWEhev+FHT1EDX8Ops+Mj/Iv0ALcM5cnf9VJK/HpOZvl8JuSAy/J9OytjrjCi/iL2R FcFwBLzzmoO59k389sK291Lyj9recK6HPuZMeyXDl87zjc+AAERi777gX2jCiwWMnRaL EZGg== X-Forwarded-Encrypted: i=1; AJvYcCX1lHC8m4W4LqSsn3arEENU48PYgKH1iuIDhy53EbFV+4DMQfL/aj6U+0Ouhtvm6spqI02aeZSzxZ4pQnW+1A==@vger.kernel.org X-Gm-Message-State: AOJu0Yys3kEknoqiDSUprn6WI56unvPiAGXyDGrdtpvhE0LxV7BsBsuJ lBabFg9uY21uQumottvTwPU0/4mhovzn27LAFJd/ru7GYoH+Oqf3 X-Gm-Gg: ASbGnctIC6Wah/uetLgxaKcUM2KhgVX7JO6LjWcEX6cKj4PU/cRPsRXTU1ci4cfr0LV KgAIA/14/XakOJmASt9xD/GmoiCcdma+upBtM8hB0oq4bDcXsTHiDDZI/DBdIoGJEBjcKzpd2Qa EZTphCFBCKAqxprTOaX8d7EPhe2eH3tlAmv6KaXzNorA7O25vw4MRv1uNDF+Elb2BZmZGGy9Vmw KPWX6upeYfpGSpj62IbBFAg2Figf9Y3TBFFndIE4ZxS0SD4NFeGR5rr7CQpzxyAyV2zmWaIiFwy ruYudasHRv5kGduOygrdfNX69D1vYP+zlayrHlk99q6xq3NHe3WK9oMXPLnHlWzB X-Google-Smtp-Source: AGHT+IF2jXebg/XL2QOp/eyO3oOLF0IGjbAWPIX7okQuwLMuQ16NI0xIuE6tUWtNH2OfaY4zanw7xw== X-Received: by 2002:a05:6a00:843:b0:730:d5ca:aee with SMTP id d2e1a72fcca58-73bd12cdb7emr18252533b3a.23.1744658938132; Mon, 14 Apr 2025 12:28:58 -0700 (PDT) Received: from mitchelllevy.localdomain ([131.107.174.166]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-73bd22f0f9bsm7223159b3a.104.2025.04.14.12.28.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 12:28:57 -0700 (PDT) From: Mitchell Levy Date: Mon, 14 Apr 2025 12:28:29 -0700 Subject: [PATCH RFC v2 3/3] rust: percpu: add a rust per-CPU variable test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250414-rust-percpu-v2-3-5ea0d0de13a5@gmail.com> References: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> In-Reply-To: <20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Andrew Morton , Dennis Zhou , Tejun Heo , Christoph Lameter , Danilo Krummrich Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-mm@kvack.org, Mitchell Levy X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744658935; l=6739; i=levymitchell0@gmail.com; s=20240719; h=from:subject:message-id; bh=jCbJ9Ju2A01cc4n5ifjcDJwihXlezFkUcuPbDwroyfA=; b=sGBKWzZWhvyS5Y/xpTGMugCj54OqxHR1MKEJ1uB/Sf4oro6WvMkLggCiGpStCYZjtFSjP7wLR 2FRu+zieWL+Csuvr9gnA3zGbJN53iNA41Izub6f+nh5IdXqDWINfDZ5 X-Developer-Key: i=levymitchell0@gmail.com; a=ed25519; pk=n6kBmUnb+UNmjVkTnDwrLwTJAEKUfs2e8E+MFPZI93E= Add a short exercise for Rust's per-CPU variable API, modelled after lib/percpu_test.c Signed-off-by: Mitchell Levy --- lib/Kconfig.debug | 9 ++++ lib/Makefile | 1 + lib/percpu_test_rust.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++= ++++ rust/helpers/percpu.c | 11 +++++ 4 files changed, 140 insertions(+) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index df9587aa5c5e..e9fa12940cf2 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2425,6 +2425,15 @@ config PERCPU_TEST =20 If unsure, say N. =20 +config PERCPU_TEST_RUST + tristate "Rust per cpu operations test" + depends on m && DEBUG_KERNEL && RUST + help + Enable this option to build a test module which validates Rust per-cpu + operations. + + If unsure, say N. + config ATOMIC64_SELFTEST tristate "Perform an atomic64_t self-test" help diff --git a/lib/Makefile b/lib/Makefile index f07b24ce1b3f..adace4f3ae63 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -289,6 +289,7 @@ obj-$(CONFIG_RBTREE_TEST) +=3D rbtree_test.o obj-$(CONFIG_INTERVAL_TREE_TEST) +=3D interval_tree_test.o =20 obj-$(CONFIG_PERCPU_TEST) +=3D percpu_test.o +obj-$(CONFIG_PERCPU_TEST_RUST) +=3D percpu_test_rust.o =20 obj-$(CONFIG_ASN1) +=3D asn1_decoder.o obj-$(CONFIG_ASN1_ENCODER) +=3D asn1_encoder.o diff --git a/lib/percpu_test_rust.rs b/lib/percpu_test_rust.rs new file mode 100644 index 000000000000..61d8793b1cb0 --- /dev/null +++ b/lib/percpu_test_rust.rs @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +//! A simple self test for the rust per-CPU API. + +use core::ffi::c_void; + +use kernel::{ + bindings::{on_each_cpu, smp_processor_id}, + define_per_cpu, + percpu::{cpu_guard::*, *}, + pr_info, + prelude::*, + unsafe_get_per_cpu, +}; + +module! { + type: PerCpuTestModule, + name: "percpu_test_rust", + author: "Mitchell Levy", + description: "Test code to exercise the Rust Per CPU variable API", + license: "GPL v2", +} + +struct PerCpuTestModule; + +define_per_cpu!(PERCPU: i64 =3D 0); +define_per_cpu!(UPERCPU: u64 =3D 0); + +impl kernel::Module for PerCpuTestModule { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("rust percpu test start\n"); + + let mut native: i64 =3D 0; + let mut pcpu: PerCpu =3D + unsafe { unsafe_get_per_cpu!(PERCPU, CpuGuard::new()).unwrap()= }; + // SAFETY: We only have one PerCpu that points at PERCPU + unsafe { pcpu.get(CpuGuard::new()) }.with(|val: &mut i64| { + pr_info!("The contents of pcpu are {}", val); + + native +=3D -1; + *val +=3D -1; + pr_info!("Native: {}, *pcpu: {}\n", native, val); + assert!(native =3D=3D *val && native =3D=3D -1); + + native +=3D 1; + *val +=3D 1; + pr_info!("Native: {}, *pcpu: {}\n", native, val); + assert!(native =3D=3D *val && native =3D=3D 0); + }); + + let mut unative: u64 =3D 0; + let mut upcpu: PerCpu =3D + unsafe { unsafe_get_per_cpu!(UPERCPU, CpuGuard::new()).unwrap(= ) }; + + // SAFETY: We only have one PerCpu pointing at UPERCPU + unsafe { upcpu.get(CpuGuard::new()) }.with(|val: &mut u64| { + unative +=3D 1; + *val +=3D 1; + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative =3D=3D *val && unative =3D=3D 1); + + unative =3D unative.wrapping_add((-1i64) as u64); + *val =3D val.wrapping_add((-1i64) as u64); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative =3D=3D *val && unative =3D=3D 0); + + unative =3D unative.wrapping_add((-1i64) as u64); + *val =3D val.wrapping_add((-1i64) as u64); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative =3D=3D *val && unative =3D=3D (-1i64) as u64); + + unative =3D 0; + *val =3D 0; + + unative =3D unative.wrapping_sub(1); + *val =3D val.wrapping_sub(1); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative =3D=3D *val && unative =3D=3D (-1i64) as u64); + assert!(unative =3D=3D *val && unative =3D=3D u64::MAX); + }); + + pr_info!("rust static percpu test done\n"); + + pr_info!("rust dynamic percpu test start\n"); + let mut test: PerCpu =3D PerCpu::new().unwrap(); + + unsafe { + on_each_cpu(Some(inc_percpu), (&raw mut test) as *mut c_void, = 0); + on_each_cpu(Some(inc_percpu), (&raw mut test) as *mut c_void, = 0); + on_each_cpu(Some(inc_percpu), (&raw mut test) as *mut c_void, = 0); + on_each_cpu(Some(inc_percpu), (&raw mut test) as *mut c_void, = 1); + on_each_cpu(Some(check_percpu), (&raw mut test) as *mut c_void= , 1); + } + + pr_info!("rust dynamic percpu test done\n"); + + // Return Err to unload the module + Result::Err(EINVAL) + } +} + +unsafe extern "C" fn inc_percpu(info: *mut c_void) { + // SAFETY: We know that info is a void *const PerCpu and PerCpu is Send. + let mut pcpu =3D unsafe { (&*(info as *const PerCpu)).clone() }; + // SAFETY: smp_processor_id has no preconditions + pr_info!("Incrementing on {}\n", unsafe { smp_processor_id() }); + + // SAFETY: We don't have multiple clones of pcpu in scope + unsafe { pcpu.get(CpuGuard::new()) }.with(|val: &mut u64| *val +=3D 1); +} + +unsafe extern "C" fn check_percpu(info: *mut c_void) { + // SAFETY: We know that info is a void *const PerCpu and PerCpu is Send. + let mut pcpu =3D unsafe { (&*(info as *const PerCpu)).clone() }; + // SAFETY: smp_processor_id has no preconditions + pr_info!("Asserting on {}\n", unsafe { smp_processor_id() }); + + // SAFETY: We don't have multiple clones of pcpu in scope + unsafe { pcpu.get(CpuGuard::new()) }.with(|val: &mut u64| assert!(*val= =3D=3D 4)); +} diff --git a/rust/helpers/percpu.c b/rust/helpers/percpu.c index a091389f730f..0e9b2fed3ebd 100644 --- a/rust/helpers/percpu.c +++ b/rust/helpers/percpu.c @@ -1,9 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 =20 #include +#include =20 void __percpu *rust_helper_alloc_percpu(size_t sz, size_t align) { return __alloc_percpu(sz, align); } =20 +void rust_helper_on_each_cpu(smp_call_func_t func, void *info, int wait) +{ + on_each_cpu(func, info, wait); +} + +int rust_helper_smp_processor_id(void) +{ + return smp_processor_id(); +} + --=20 2.34.1