From patchwork Mon Apr 14 19:28:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mitchell Levy X-Patchwork-Id: 14050934 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 88048C369B9 for ; Mon, 14 Apr 2025 19:29:01 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7873D280016; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 73853280014; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5B1EB280016; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 37606280014 for ; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id DAEAC140625 for ; Mon, 14 Apr 2025 19:28:59 +0000 (UTC) X-FDA: 83333637198.11.0A9252E Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) by imf18.hostedemail.com (Postfix) with ESMTP id B72641C000E for ; Mon, 14 Apr 2025 19:28:57 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=NRPfqmcI; spf=pass (imf18.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.214.181 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1744658937; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=IMpKntOoWqOPI4F7pSZs0AGZGaf4Czl/zYkqLuKCY7Q=; b=Ec0c/Lhii3rbZN18qKqvIvwtReNbAni9wFU4egbUr4e6bTLTjYviFuWfFvQ4/tZzFC7jpT 2QsxtxcpHbYnQjA5yMq84NsQD6TDOYotSYdDWMxyCQt0DB/kr4bq9u8l5YnsCQV0Zas5EK KL2IL9q6yxo2UwAqz0Z/+FRVZpEhQoY= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=NRPfqmcI; spf=pass (imf18.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.214.181 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1744658937; a=rsa-sha256; cv=none; b=EutcBgNPiCaWPoZDvzMDlXtbUhxTlvexKh9IPmvmdx3PSE8f4MAmsNGjIynmaTWiqGjLHz 0V9hxaNEZw0TfcP+cDaobBqikRXkzrUDsFIAaaFvsyLKjgxk6N/dc1bvznWHtLLwyEEANS 9aiq/xG5eLFHXX5gjnZJBRcVIGQOdIA= Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-227a8cdd241so57079955ad.3 for ; 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=kvack.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=NRPfqmcIw10zW4tBlAH6ZFrKv6CzxuqyG6nZbxAAAwHUHTheenX9eZezu1slfUQzLh 4eeOOdLKbB7czsVZrGIIHuuUscL3iHBilZ4wK3Mj+BOqN7TuTZK8+zTOCwXZ6lmOmIRW 8j7m9xhSCSdo9fgdfZh40WztLg2aZpPEAkHwfuqbQnrPjlsCpGKTa4T31Sf60eSM9eko ry7Nxu5ag5jTYxOgfdwexl5xHNkZ2KpL2Ep+mZuk8lwLk0YxALt/rRji+WXoo0sOUUoq e/NvmeKIoyQrLAkX1IbqU1J1sNHXvd0fVaQjUxT9Oj+ovAHNa6DFVkfhJwLMWsrJwxn4 PkCw== 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=t6xkRdyLCIOGa8B48VsJJIL6RKwBTQlS/wIhpCewC+GbzPxrrIp1grc4Cb6wqNpRwp ln1cancfyrC6LnFUEvWj26Mr6JZ/zuaG67/FxHIjrzKMxXBCesvwbbzBaqMQph6hjq1J 2S0l2JkbAzSM7SuHqrgDvpTNlzTGDihNmLMdxoBSd/RaxQHUvfJh9oUtIl6KkXrp3kiv JpBcADQy00w9mG0U3jtfhxCtYVty8YcVYAf+8QAMuYEwGvrr8vHfnVsdSGFC6XmbNkqC 1ptiOj+7mvR4R4q+uz3Gs5lDeL+fALp0ofndMejgPAO96TFRyIuNT4c/uGR2ERDuyVuv eWpQ== X-Forwarded-Encrypted: i=1; AJvYcCXKW+zUgWcwvRc8fdCUgjSXiMAupT0tqwJkOIFiI114aBSwuf/dyEYOMQGBGM7lPq5GeXTCc18//Q==@kvack.org X-Gm-Message-State: AOJu0YzWwErm4QjHE+WobpxjYZE8JkjkYMuc4Cocjydcfy0U9t/KHWFy A9Zl5bpxm2u5++IjAQn4Gz3WmSxXk45W0ZUg5MMVj1v0X2Qd+fGv X-Gm-Gg: ASbGncu3KMMH89/xwcZxjUSLl+qutdJhE+kZiPu4IQ5iavgLQkN17OFdY9jF5q4DjG1 4XAWdwaxlfJv8EFUT7D+NZTZZM8y4IVkgEs7XVPdsaEk5iPi7gUF1g2gvCLPYmcprhFxo5/sDSc T9clKIJstA2B7/hF9Nfq6rRMGgMKJn6ot83OQyyjzZ0r0ltUydm0RmZWfdxRmOwjcQ79Nab0E1z MVLGs0MynKO311y9ZtaiVd41DenzJJWkek9z12lkZrLuKWrP23Pp1iRKd8x9IyJg24+dlfIVksg 9q78D6BWP36MpGvUps9rs0c3x8Q9wsYBmFDdKG+PTyemi5/TgVrQiv61g20iMXeD 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 MIME-Version: 1.0 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= X-Rspam-User: X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: B72641C000E X-Stat-Signature: srbaoa8xxbmkbbee5n66yhzjokhawp9z X-HE-Tag: 1744658937-690745 X-HE-Meta: U2FsdGVkX18GbuI8AOnHx90eaDAI5/EnigHZriN8GWhSvlKaa1qQ1vCfZ926A44MFLiuURgUFlqp5FwDIiczmHIysgodonosZzg1neJBYDsb0KK9oqrl+Z8OfJP7SmISGijfj45N2CNgB1xPhiF3F0TAX9Sk4Wc6D/iAd68HXTnUq4qqAeJkPUIig7c9eT9aAuASeX96gIaEEKApiBhU55xEyQagX43pYM5koECAo48VCjF+oy+fg9GbUqyprytr/bq/+ajD8y/sbdUFP9qLRSnzCphdIaHVMNU0tipYII1JgmXNp2OyRYHxccEH4TYD3YeKPvTqQnkqMgl4CW+H/50VK9/k+kjXIecVwjihLPUp12/KPNbCjTDOkJLCQqgF0BKeGCTxMXnmbaWFB7HMqCBV6agubPJUb0ORrSV4yAIsysOVtVhdQhKwO96RbDkqsabR1PS6biLeyS5dsEet5DALd5EHLVcIwfhAtQodEZ25eiXin6vHkapXYi/5oVvFze2kAwvsLtMTLGSOA1jzuX1F5o9g7nS0ULlfD8D2dFysYWtx38qwJOMxNjbpZstC3SwRPHZQMR1UG3qrlBweIrKgWSogJOXI1qXQQFzgZKdEuslBJq+kdpiBafsIiEJegZc9z6p0DfE69serZ5nRkdS9Z8cfB+AuI9OQVbE6FaV4Zzl7Uf6RHFqMaXBr94AnHZcLlmLYcVtlNiFlA911scGYTWV1KnCmZfBg6tbDbUQFISQQTxgkW+R9jj5kclaRq4lwfeQUwnnLn9EB4eMFt++K4eYZL0cHWB/olylff7EuAk4vgb1XxIxY6X7vmUeJUAP5ZvNX5A7fA5ov2NgpFBa6Bgc442bn/Whv7OdwbNi7HhZhK4NcW2KczgZa4jlVM1sIhFdPT8kvxtv2UY1r26H0mD/OWUjAyIdht+Uad3g7ZDf0mkAROsEDn3p+GV8OzDXiv8KUN+mIyBfk27p XVfKRSiU qroDFVTj8h1QpOayA+1Oc7HlTX758LgN0yOueYHTe71lNN+BWVD2G4UPoJ9gvYU3RDzl3JD3rE1xMSCREDc6R5MDHuEoDv9Vv0Tym8ChjqWepe10C5uYqnzgYP9OgQopc55qsRXafPEA+G6bPIrb+iwHLiJ9YFWP+w7EFQanoNMrAjp9Ww/vTBLOiwp9dLnSPYfLRMm3EOP7+lZSy1LBxFDG9zPcS42tOmhJD9Z60swhWwLV7ECO2vxAk2PNymQGmJcmmeMlCRb/51DLvG2odQ79XKPJzbNZ+2m3BeIN+1YD3LgIkx149dXlEq1OASEr23wlDH/2RXmEEK0CUS/9M2N04zPh79EtTelh3RkfNIaJ3+rMfbvxwT3SHO5ZbzSYkrTIdtpEv1SyRoZgpCIzWYJV1kYI+vNoByCgm/1Zs8PXZ9iXr1sUEyX/Zql6nYZMVR/l+tehAIqAshHE= X-Bogosity: Ham, tests=bogofilter, spamicity=0.040035, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: 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 variables 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 static 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-allocated 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 unused. + deref_type: PhantomData, +} + +/// Holds a per-CPU variable. +pub struct PerCpu { + alloc: Arc>, +} + +/// Represents exclusive access to the memory location pointed at by a particular PerCpu. +pub struct PerCpuToken<'a, T> { + _guard: CpuGuard, + pcpu: &'a mut PerCpu, +} + +/// A wrapper used for declaring static per-CPU variables. These symbols are "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 prevents 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 and 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 = unsafe { alloc_percpu(size_of::(), align_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 suitably 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 was a valid pointer into + // the percpu area, and has remained valid by the invariants of 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 = PerCpuAllocation::new()?; + + let arc = 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 = 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, this 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 = + 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 valid 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 = in(reg) this_cpu_off_pcpu.offset, + out = 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-one else has a reference + // to the underlying pcpu variable because of the safety requirements 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 to 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 self` (that is, they must + /// not be `clone()`s of each other or, in the case of statically allocated 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 lifetime 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 underlying 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 requirements 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 = 0); +/// ``` +#[macro_export] +macro_rules! define_per_cpu { + ($vis:vis $id:ident: $ty:ty = $expr:expr) => { + $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 = $expr; + + // SAFETY: StaticPerCpuSymbol is #[repr(transparent)], so we can freely convert from T + #[link_section = ".data..percpu"] + $vis static $id: StaticPerCpuSymbol<$ty> = unsafe { + core::mem::transmute::<$ty, StaticPerCpuSymbol<$ty>>([<__INIT_ $id>]) + }; + } + }; +} + +/// Gets a `PerCpu` from a symbol declared with `define_per_cpu!` or `declare_extern_per_cpu!`. +/// +/// # Safety +/// `$id` must be declared with either `define_per_cpu!` or `declare_extern_per_cpu!`, and the +/// returned value must be stored in a `PerCpu` where `T` matches the declared type of `$id`. +#[macro_export] +macro_rules! unsafe_get_per_cpu { + ($id:ident, $guard:expr) => {{ + let off = core::ptr::addr_of!($id); + $crate::percpu::PerCpu::new_from_allocation($crate::percpu::PerCpuAllocation::new_static( + off as usize, + )) + }}; +} + +/// Declares a StaticPerCpuSymbol corresponding to a per-CPU variable defined in C. Be sure to read +/// the safety requirements of `PerCpu::get`. +#[macro_export] +macro_rules! declare_extern_per_cpu { + ($id:ident: $ty:ty) => { + 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_enable. 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_disable + unsafe { + bindings::preempt_disable(); + } + CpuGuard { _phantom: () } + } +} + +impl Drop for CpuGuard { + fn drop(&mut self) { + // SAFETY: There are no preconditions required to call preempt_enable + unsafe { + bindings::preempt_enable(); + } + } +} From patchwork Mon Apr 14 19:28:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mitchell Levy X-Patchwork-Id: 14050935 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E21DC369B4 for ; Mon, 14 Apr 2025 19:29:04 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 12301280017; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 0825C280014; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E1831280017; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id B165F280014 for ; Mon, 14 Apr 2025 15:28:58 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 7D31680525 for ; Mon, 14 Apr 2025 19:29:00 +0000 (UTC) X-FDA: 83333637240.18.DCF8A8D Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) by imf13.hostedemail.com (Postfix) with ESMTP id 75C412000E for ; Mon, 14 Apr 2025 19:28:58 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=WchUOyt9; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf13.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.210.177 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1744658938; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=9tZ2dPLybpFH5FVRU54a2SFS8qh5x40EXdBFzij59yI=; b=xKi0ES4Ir/he5PGwho6etRHMWhSSlDGzNyur75vq2lsvKNRoaWxgYqSEV8FBowFACDmEZc /BJlZvcsOf3fiPZTB21/OKjqGCU+sshjvJLPJDFAdNzvcION2HO/t0SWU8KWXeF8LeX2it W4UEDXmPGqQyWcVreAvbRt4an5XIExo= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=WchUOyt9; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf13.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.210.177 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1744658938; a=rsa-sha256; cv=none; b=j6VAFt0jPv0rm7mF20ljsf96hBcSTrotHPJ1urM9dZ3nyQHCTSy5/wqsk0dXf0/T5qyfcp mORXuN2i6rneU9Y8cSNHRq7/KjIAmAt2H3nHCrpvXICoJOqm5IdA1FRBwDByzyicVqpA3W 0smTShtESWizP6pX/zhlbKgHT3cGBkU= Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-7390d21bb1cso4637679b3a.2 for ; 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=1744658937; x=1745263737; darn=kvack.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=WchUOyt9gfAHZvkzpOG3PfDXqC14P6eI3upzQX090/8nBohxBWKXjg16+TRWCD3Nj/ FF4MF5oqAWrLSwFoGZZAAnAOwAPONbN4frXNRVAIgbihmSonb/Zi3H9NMw1nKS4dBfUN GU0ZUGpF1HeYnmoK8tBxhg4vvKkwOw2RdFIQui1YMtzot8mo3IW2BkaMEGgHdk2bA4kl yK0euGv5xqJ71j+3TxnF0DNJMJoLTOBzLd3fej+nlmPRgGYT0mRiierGwwy0gJdggbKo eqa/DpwPLJ41xmiZRj4Mu2jnmCVyt35hL41ObM/1JDNzHFvlRLRmuWBlz05n69Oy6oKg H06Q== 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=XvQtIZZp2UubjmW0A6yQQIQc+J3Ks3bL3gs2E2iHLLnrTiuZ5VWiiSy9XVU1ZJln91 dBUTSdcuaDP4Q3AfNOVg5Ev4wyW1g8waSA267ezAD3F26zgXmdASbh5jDvChlfaEDH4R c0WydfO8SyLyh1coZiyBiuhbSUQ9ifpjR4LPaR0urjAxZDLzHsMnkaBmtV+pBoylNA1i NjQzKI6NEVcgSEuXEKGI743cx49DrMo/EkzWAt+nUFnksPMoaK8b1RkgBAwBfkTl1nvK URQw6PKuSAepEIOPYkdH3WHuhpVPIbXg176iDK/Fkh/AkGA3VZz43Q8RheEwzsqa62Yq Sbdw== X-Forwarded-Encrypted: i=1; AJvYcCV9yymYLzlRDs2yqzxHhqjATrWaeu0Y4Ac36s3ItIW7yQCEGGP5zpwKDLvW0kDlWeXx/1zqH+uA9A==@kvack.org X-Gm-Message-State: AOJu0YwiH/c4jvXYEKAw0KwIIYrGpNCXZvDEk4YsnTU3RKMCrPuZv3LG s+sREljGfP9ium8OW4EeTwv2Y8pBsT4vzg19g9ONcdtHkLMTA9tW X-Gm-Gg: ASbGnctXSU6Ba7GeGwhoZoBoxspGYP9erPJQjvr5DwRKx9z0uuW06tczVJFWXCbt8V8 g9xOKRWmgFZRGk2FglgR3T/iB2okjmikuRpyCh2WRyzfwYoVAC3dC8vN3L/PlHtOulSK/qh8lOQ UMnsyItJ0DfD4OjvWOiHmDVb62RcfdUEysT9gtThUq3FGDRFYldOud0dkOjex14Og/2EbUhuUYW KjYF4krBeGRRoS6Gffc4FUXJXioGaUWFuOyXUmomhu0OeSCFNL5liiMc6H4OpFGrBQ58T/MCEV8 orCVKr0JQvcK9ysbgfQIfpa7zTn1c5+6fFEthGW93Sk3r5Ke05RVzURlbYNm8p9o 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 MIME-Version: 1.0 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= X-Rspamd-Server: rspam01 X-Stat-Signature: soqt78xdpbxpaiu14n7iy7zn5ennjtur X-Rspam-User: X-Rspamd-Queue-Id: 75C412000E X-HE-Tag: 1744658938-308922 X-HE-Meta: U2FsdGVkX1+Ad2SckIq+XMLz6QdZdpMRKeiY8tSIR59ncCZcY4hyXm6/pjtI24zEEjC56l2oh3rXFjvUDEApjx79lvSRi+sW61ZyMrUzwTDP2zAgH7GmBPswYv+hnKUMq/oWka9ZJcNbKaHJJJmidkrc45vukfSRIu3QmIjqKxPmpbbWEfGgSI/Nmo1MENP50etgahWIhT775p6G5QeLZNqhbNYK0i37yWL2gCjoC4l5DmYsLZMD3th0F9OBeBc9a+k/m9ouCBjUPWDP+ZaQUZ+VHK0tVtxLi3raca76eX4j1MR9hcgpnpl+kFxWgfs2I9xvdU1MrucVD4HnaU52zd9x5USjH4I6LxI9mFFZHmu22at+JuK2MLajGjiEy2hNuk60uc7yOIXBcnjni3h2dyZ/2bgmcCzIDUZo+1z6m6hKjUQq4qfYHemLRLSv0EA7lhliSXG56wUf2DhUlC1MkO0ndsm+DTpPisdHAoNC+SsNydAI0YB1YwFK47x8uVE1gdNhR6XedDfuC2lS+YR9juGcK0qZn/UDzTf4W/BL/kjktSzluf6jbRtGrNc440wlmovhnNl5krSFuVgPm7hvMQqVGnOA7jV6iPAbLPyZl/ynArT/YYTaf5HkIisULN/PuhjWJ50TZfaKBG/s0lF9VUlh1jbDBGKUP+6UkjgvYnZEuM54zw986NVO1BuLXNIAfIIEP/28eqxKm8fRVqOJL4wpbPhPVPgYV9NduFOA+T0p5BgESNjajkLiLLPVjbt3++v2gBeEvEvXkHO4pjF0sdr1EHrVaQQ1Hsnhl1dASwKi7BsoPKS3s6fS0ScMtrqSJvbbhYL/qQRPu8LrgnkcH1xwwsg2pgLkVrCElxvvF3tqFcec82hZacqwMaI5eefqEZI84Nh2ObYXgJoftLpOmGwZqAS/AIU+CCBJqY8S5c7PR59Qko0/Of3jZDhUuMh66iwNaWBGbkwMs/utzJM HwyMqCUq tNRypIRvMZrHYVpPoPdReeBPhQFVmirRMU4p6rpG1Ib/xyYx++sVoaKgf5fJKR0opTBkQ6d1uYeePKKB5v9rJx4NtN4WiKa+tncleDYdQf+NXq4X3+5oN9igGWqKho1r8qm43Ng0A1vTcw08UO9NEwBObOSDAdTj6Rij1EJedOeMtjOW9LzWVycK/S20x7ebs+OyRtcIxImRIuBYT0NHPMaO8IB9rTDjOynUOQaHePFxpdzB3HTvsfsvlI0fw2ohhxpW8SjEcQexEPzc2+N5w1XbxSkIhzh/UROWjngKEKwsOBcqMgj7nQlS6ROEjFY96BgGqfjTCxUFlLUoVPDisUeK6ygKy46bSii/VDlShwfaH3e32eEkNXnEMjE3OOhVl5m+p6cmKx8U+JQ6b/I90IltMMbM7peX+h5hQehpdQmFFcWuMb6MCOmifjhXGBMeRWBdwFxCpemvHSSk= X-Bogosity: Unsure, tests=bogofilter, spamicity=0.500000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: 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_analyzer.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, external_src, cfgs): # Then, the rest outside of `rust/`. # # We explicitly mention the top-level folders we want to cover. - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) + extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers", "lib")) if external_src is not None: extra_dirs = [external_src] for folder in extra_dirs: From patchwork Mon Apr 14 19:28:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mitchell Levy X-Patchwork-Id: 14050936 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF17CC369B9 for ; Mon, 14 Apr 2025 19:29:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C4CC4280077; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id BD81F280014; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 93B48280077; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 6186F280014 for ; Mon, 14 Apr 2025 15:28:59 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 5204F1C9378 for ; Mon, 14 Apr 2025 19:29:01 +0000 (UTC) X-FDA: 83333637282.18.09AA849 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.182]) by imf26.hostedemail.com (Postfix) with ESMTP id 3D668140008 for ; Mon, 14 Apr 2025 19:28:59 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=WoYDqVj+; spf=pass (imf26.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.210.182 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1744658939; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=R/mennYIPZF3DS9iChk0/U5hjKR2MUh3UXar0f5WEiM=; b=KBzB+8meD26DRzXAEAReeYr2p2brM9yGz70K9c1mMBauJSLDf3mEaW8rPWZmlTXmXCI8/1 d1yWeNimGqFDRkEctPtwYGJLPMik1RDlgzoAmkrm6iW4TN0SSdbLeBocJIfP2zFSoL5YCa R9C8ONmrBp0Byt0yb7X+RHqLStr+Zjs= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1744658939; a=rsa-sha256; cv=none; b=FVaFS/OPYK8WXADF7PHBIaIxb0Wzwa+7Ggo5JGE68kXVhbcdqOClmpapF4QeNHAcQJ8a7F LBNbCzlusKsPsAcFsIeqqyuz+Vd4VWvIYLRdt5SfmtAznh9LnIWw4gU8SdIDECE7vEaQB1 m6KeHlMcGgeCMysMoPEfALY/Fq1G+30= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=WoYDqVj+; spf=pass (imf26.hostedemail.com: domain of levymitchell0@gmail.com designates 209.85.210.182 as permitted sender) smtp.mailfrom=levymitchell0@gmail.com; dmarc=pass (policy=none) header.from=gmail.com Received: by mail-pf1-f182.google.com with SMTP id d2e1a72fcca58-736a7e126c7so4087695b3a.3 for ; 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=kvack.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=WoYDqVj+LT9vSkIDYf/+o8NrTIv2W7V3C+CpJJ/K//YalLbpy3lmu9mXZNdpuzwFJN zuijpKvuDGVhPhBdfq/yLmPWQx8G2H/U1+qlfF7LRsIjHHzoa4X15568MtFMGVIMCmR+ am1jP/tQbXo6HDfrmvUD4x8WiVVmo5BEv/ZGjfd9sc7Ay6rpLRg+GLhK6kZenkHedxls 5ckjESHZnF3EUvWm6ISlbYkSUxU8bpFjupi9KTNBXWeof6nvXARu0MRto68HhCsjAGua Meu0xGTWxTyv3GcXymm3I6UPtXW7WEoe22WEA8KZKxmnxRCJMLIOfnSbYcNh0I2i0ZvX J9xg== 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=skyiWeWSuXWVAdZZl+R/a9A61+gRJEbBCACVyqSRgGxb7H7qarNHgOmZGwjtnH6YSb 2wNWz8uw6CD3VAvf59vAtBJ54rvEXYcXh8jVumlk8GtuV9c7TX7ibY7EVLOizmDXKBxr JoxAx1OMC5EMs0GCRKvqcsXLBQ8wD0NcNi3pyturxEC4Lwx8YvO3hLMMUsq3iy0aDiUf uREHF3stbLCW2HkQKXvgEzBMjfwJgQNLWBJqAwoom8eLVBlHKCKP5B99zKfvE9NtQVP7 /RHNcOdHQ/pz1XQUIg49lP58kALJcMF0ypX7ZzlRTZ88dIzU69vovguJZssFXms0W0EU zt+g== X-Forwarded-Encrypted: i=1; AJvYcCXbInruKclH5Pw4AEaOFS/BHAR+cBjmzT5EjQeUrXLgVrr4WY+9VXufkHW/ViBoTGD+i8rN37lbDg==@kvack.org X-Gm-Message-State: AOJu0Yxg7lDvEb1J1LIAeAMRvnlgfuhldeUfNF+U0zaC+EMGiqePNx4o ojwgq6naT/gnYeQS2BeCNIroLMrdrsrlG5KBEMO65ldOtBSEg3iG X-Gm-Gg: ASbGncsj+grjvALLk2KuouLETDu0aYPJtlS89FtGt0BEcgIfgc4Vy5TS3LBnpLNAFLt pLjlJrf4sx5+ByMa4z87Kck1weKhwM/ZZk0vmNyRwrbw7qMHdBmvYjOd+W2+hkMV6KZ4M7ItySx xMArz0UQ3T5g7Mt3hmvp0QGs4HQdpkL39n3q6tQ4/c1witjLBWHj/OI4MEldEnQviMG9Uzoswal xAkSpiafbewZ7y+rq5tJYMfe02G6joqNya5cnabvqol4aMirBP2LQAYN2BqdQo4T65LgBFRpP9t uhdUKFQfkwH25Qz5kgWLL0fSFN5YhSuhbFsWxEelWestLl0MvYQxBvhcfwKMAdkU 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 MIME-Version: 1.0 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= X-Stat-Signature: ynq6zunetttqbqmufkkd84sec88i68y8 X-Rspam-User: X-Rspamd-Queue-Id: 3D668140008 X-Rspamd-Server: rspam08 X-HE-Tag: 1744658939-44984 X-HE-Meta: U2FsdGVkX1/cucMtnNsJ/Per3bIa5KKqrRA6eNqQEfOm7qdTT2H/01tmBOK+hPIRwVMidIux2sn5pQR9rsNPkGHlZa6bmadT7SJX/vTk9OR9g49KWTKSKghsD9rp34tVVaPmT9d4BNa9dTjhVph3AZU7dt1ZYOHEt8+ZOPYdT8StZG+yrTqfw3rObtojldw254LgM2XMfIkoD4qM44pKx393xxJaaA1Cko5IkEe3Zf575a2CARRfNMfz9xlKsbuvqDp5hqGbralVR3CKHbvee0GlFmq+XyhSNMcXfWIasrq/y1hpiCxmX0lI9VGYMsMeUUOxsyjCMonFEfgMcMSGeu4YDT/XViGgKYmyZxOZLlRyuFJzSAmhellupggWXSaXQguTYmvYQB70onoNWZg2gZrszrGSDNQFM0/UdghUKPlRBMQ+45xMisP9GpfG7BCcUga9A4C9Ow8m4Q83xIN5fY3qZv0xOva3cbKZTNmlOoaPnTb2U0eRw5RwEsNkHx2kU5TMUC6Mzh0kkAh+gppx5JyawXk1/CWd6CMmNTR068GIWBtkYo49EhbCvzW7oAtf7TcMewoNDG/1jOmQsh8JFHyhE95S9k/P32PnxcZ/kC8CcGjgTJwT/I9+tZj3baiTDcwlbwhWp0ggd3Z1/1x2SHjRymPO7ftnvr5N/sge/YPlOvqdwkNvbV7ax/4NhHdBjV9Y05AHXQnIwxfZLFJlDfixGAvqe32lT07QgG0IH+cQuSTc1HT7Zc9ucqOfQG1qpVAgoYz5xlex6L0TZFaI6UwJIKAwRqkrJywf4DrHyU4dkBf8eErfjaI00lpUunTqMb1m5P+lx288QuZ9u7nyCIadV836qWofWujCY9/h+ROezKDE1gDCqPD57qoBR1MyWqgchEQsYtuE45HYK4Q2+3zhBaModh9F1ciFx7uVGy6HfwGseQzDyKcRvf38jh5wJk8rbKzbKA1Q+AWjCZz CZs60jwZ LQPNuF+wwmMpD4GPJ/XDfKGXWUEUiJjQCLgCqpwQRkWxgwVwDoQXo+BUyS5Xo1Z+76PZ20t+OETYfmv/b9//4h3gsG6/RhcyRdNeltwN+bWBjzTAGV1xg9EgTIB/UPPJT+PaSehiDGkR8vCKBcR9+baOm02GPuEb69fQ1ORUfrn9r4IRPNQbp25hRFkz2Trs2ZlWRV93fo8LBoRouyNGPmQtcLj/1nep1UbK81hY2e42bAUlsskLVyzTTRlqQdEIn5tFAD77twkFclYvNlOfrl9b4AD6bvj+9IKbA9K2T9RIrj3Pwj7F0eYVtLltwFBeeeWyJzWwWAyuF87tMCX+ibPRMYHPKySDP6xLMGO6Rzp8d3sg+sJQPshVP+H7uD/sIQDopw40jYcoPEvPtDwIitGb2vVQ7QQCQfmp17LPEFgV7TO0cq+MmMbBjMfZuXb954bWW8BZmK28VSNr9w0G+ZUSN1mLLOvQTQtLfLYDU9801h00= X-Bogosity: Ham, tests=bogofilter, spamicity=0.437849, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: 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 If unsure, say N. +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) += rbtree_test.o obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o obj-$(CONFIG_PERCPU_TEST) += percpu_test.o +obj-$(CONFIG_PERCPU_TEST_RUST) += percpu_test_rust.o obj-$(CONFIG_ASN1) += asn1_decoder.o obj-$(CONFIG_ASN1_ENCODER) += 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 = 0); +define_per_cpu!(UPERCPU: u64 = 0); + +impl kernel::Module for PerCpuTestModule { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("rust percpu test start\n"); + + let mut native: i64 = 0; + let mut pcpu: PerCpu = + 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 += -1; + *val += -1; + pr_info!("Native: {}, *pcpu: {}\n", native, val); + assert!(native == *val && native == -1); + + native += 1; + *val += 1; + pr_info!("Native: {}, *pcpu: {}\n", native, val); + assert!(native == *val && native == 0); + }); + + let mut unative: u64 = 0; + let mut upcpu: PerCpu = + 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 += 1; + *val += 1; + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative == *val && unative == 1); + + unative = unative.wrapping_add((-1i64) as u64); + *val = val.wrapping_add((-1i64) as u64); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative == *val && unative == 0); + + unative = unative.wrapping_add((-1i64) as u64); + *val = val.wrapping_add((-1i64) as u64); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative == *val && unative == (-1i64) as u64); + + unative = 0; + *val = 0; + + unative = unative.wrapping_sub(1); + *val = val.wrapping_sub(1); + pr_info!("Unative: {}, *upcpu: {}\n", unative, val); + assert!(unative == *val && unative == (-1i64) as u64); + assert!(unative == *val && unative == u64::MAX); + }); + + pr_info!("rust static percpu test done\n"); + + pr_info!("rust dynamic percpu test start\n"); + let mut test: PerCpu = 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 = 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 += 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 = 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 == 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 #include +#include void __percpu *rust_helper_alloc_percpu(size_t sz, size_t align) { return __alloc_percpu(sz, align); } +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(); +} +