From mboxrd@z Thu Jan 1 00:00:00 1970 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 DEA3AC83F10 for ; Sat, 12 Jul 2025 21:32:15 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CE5116B00C4; Sat, 12 Jul 2025 17:32:11 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id C6F236B00DE; Sat, 12 Jul 2025 17:32:11 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B105A6B00DF; Sat, 12 Jul 2025 17:32:11 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 99F146B00C4 for ; Sat, 12 Jul 2025 17:32:11 -0400 (EDT) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 4A115802C5 for ; Sat, 12 Jul 2025 21:32:11 +0000 (UTC) X-FDA: 83656910862.16.9B9E6CE Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) by imf20.hostedemail.com (Postfix) with ESMTP id 50FF51C000C for ; Sat, 12 Jul 2025 21:32:09 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Mc734+Tx; spf=pass (imf20.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=1752355929; 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=hExQIcvoKTg+0rOcrZXWVdh84oK5KeLOdM+0A3CpbHg=; b=ABninumezDsoKbENcEeoM5ixTfArl63hG5/GsnRUnpHL/YSW8ZIMmKMhZPAvoVuCQdxSuQ FbMLwoSm4rRn2Ka/2i7HHvkWUXbEuRGQYwzdXgW1rvy7+IeHxyFolKtpXKxgfXNFGPm8rP Jivz4ic+Mr1pZ9e9mnyH8kWBAiSOOaM= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1752355929; a=rsa-sha256; cv=none; b=ZQThz7q5Hp3KgFbeNszk3EBVLo9kJ+ZLODjkrkr0pl/EV0t9E4WXf2o1HGaEl/9m/+e2qw YscMLVvnHB4hNR9R+5du+dV/PIUA4z75qNCk4ShqGa3fAtNMv3djndwD3zBpiunWimeuMr N53YnemDYGjt2bk0hdN7MbsH8dFuUvA= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Mc734+Tx; spf=pass (imf20.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 Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-235f9e87f78so31024075ad.2 for ; Sat, 12 Jul 2025 14:32:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752355928; x=1752960728; 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=hExQIcvoKTg+0rOcrZXWVdh84oK5KeLOdM+0A3CpbHg=; b=Mc734+TxnQRMvIZ4imZhR8NGDhmVE/BJGQ6hDKf8xM5NGqACbnzaJ1yRDaRe1LcNxY Qha7Xx3FqRqL7xGtA7kz7dFwAekGyJWKX4gcUc4m/CWsIvXXB/jLPE00vuiQUMmF0tFi ELm7cYecgp6ljduJNj8PX+VHOnPCMkHWpRPNGV1hf1G+H34qv9mRbOfslUvSHxKFLewl diikUeHIJpmHCJ8Qr/D+Yihkny6pPOHv2uMmL2wJBIpti1kTTZma1xTsLZAV7MPfdhVm bFV+/0LfIF/3WHBaY/4mOhUhe83kg2aivDvFXvAndK8NpApF/8FUylmr5mvc//8L6Nte XAeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752355928; x=1752960728; 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=hExQIcvoKTg+0rOcrZXWVdh84oK5KeLOdM+0A3CpbHg=; b=D4ogNHzCwazleDyG2Ur58CFpXfBz373/4w/8M+3PpiBA8hXfpjH4UoV+JA8LnQSMGw CwhgvMM3JQIdzEtsyJRq4O2a0yMu3s8frlw38OmXSXs6NfJ41dWJWRGn14I+oPVgXwex ABGy3lMkSBV284SNKwJUknks5e0Wot81frkNe9lVp2XERIecfWwtsKFuc8dUR5Jo5c2z I1D7E+NBxDhU7vxNqYJU4T8ENIc0WRxM3DHhR4tVT94jBFP7b+rwKmiV3iGrDgfXk7Or yiXfvGOBbTIQvyO7tpm4Scj2s/KTKpCPXQTZUPbX1E8vXnTAf8E6oC5qQ2t17S2Xg26q UBAw== X-Forwarded-Encrypted: i=1; AJvYcCXLX8sxoENggKBOZ+PfL6I6YeNkpQsmo5AMSl5Fil+6IGZ94YJF2T4rSodnQT/ZvxAvL78bLFIX5Q==@kvack.org X-Gm-Message-State: AOJu0YxzjjXBNJth77ewEDNAHheu5gxSMp6xgbwQ66AssdTPyNJp9d6I YdDuidRbct2DftFL+vmwN3MaKVKXORFur2PihHWno0fmwIkmCj0mA5ym X-Gm-Gg: ASbGncupnbryGWmlg8aXm+ZmviDrVGAqFJn757QLLRKejVKujz+DaxDKiTT/uBLhfAX 0S/GK+WFtmFu49KnUSwqkpvEaAoWT9pf2DT+jVxsjdoF4kceWZwsoEtLUW92ACcUPXOSLhntU8y VqE7IyqBsu2/jn29dilSqFW2SM0tA6MCQkB3/CRikOh9b+2uRt+M8ASP4QIm3U1Tg8/OjjC2OMB 4WDKfE0PMjAY4F41QvBamljjnCu/L91Ye1IZA0LQQ1Eft6mvSs6R9lwwGLhN4yV+yA0AhvbQfx1 nEoOaNr7SsUvck+ku/vgiLQFPrTRlHA+aBsx7qSZqqM2vNboqBpwhmHnDt3FR9S54FIzKnNjqug uuDN4z8TmTLQfYJlj0pBaSgLhx3AphanCDynXSFtHJj23lQ== X-Google-Smtp-Source: AGHT+IG61yxEcItnZRLBCpzRu1bY9moREdTEBhg3R8F8LHZq7g2AdMJ+EkH1Plxdpo90qEBetLdPOQ== X-Received: by 2002:a17:903:a8f:b0:22e:5d9b:2ec3 with SMTP id d9443c01a7336-23dede7d432mr121624255ad.30.1752355927891; Sat, 12 Jul 2025 14:32:07 -0700 (PDT) Received: from mitchelllevy.localdomain ([174.127.224.194]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-31c3eb65aa2sm8003935a91.40.2025.07.12.14.32.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Jul 2025 14:32:07 -0700 (PDT) From: Mitchell Levy Date: Sat, 12 Jul 2025 14:31:14 -0700 Subject: [PATCH v2 3/5] rust: percpu: add a rust per-CPU variable test MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20250712-rust-percpu-v2-3-826f2567521b@gmail.com> References: <20250712-rust-percpu-v2-0-826f2567521b@gmail.com> In-Reply-To: <20250712-rust-percpu-v2-0-826f2567521b@gmail.com> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Trevor Gross , Andrew Morton , Dennis Zhou , Tejun Heo , Christoph Lameter , Danilo Krummrich , Benno Lossin 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=1752355923; l=6875; i=levymitchell0@gmail.com; s=20240719; h=from:subject:message-id; bh=J2wN034E1ANJf8z7zTgfPajB+DTsr36981US4k79sBA=; b=ujc/F9znVc9J+1BY7Iu7YhgYa/WWZ1LKlVHVug/z90X/Ix09YeqHueTf5rN3LoU+an3ffOqsi Dl+ePBIO/+ICPEQO8VX7uxHlAnutjF0PL44suFsx/P1hiIJUkvPQVaA X-Developer-Key: i=levymitchell0@gmail.com; a=ed25519; pk=n6kBmUnb+UNmjVkTnDwrLwTJAEKUfs2e8E+MFPZI93E= X-Rspamd-Queue-Id: 50FF51C000C X-Rspam-User: X-Rspamd-Server: rspam09 X-Stat-Signature: by9juqaqsry5nd1chcxff6ua8ksjm9ou X-HE-Tag: 1752355929-826957 X-HE-Meta: U2FsdGVkX1+aSgOSPrT5ccCt0F/uKfYvoLOj+9qevCkcVKR7C7hVtb/M+spaRT1M6E6LCp7da5RQwgANBKnos5D34UNIKEt830uE4Tp2m0Z5WxzNlNSpEzrejWlmzEZ4G4TAbtwk77nnYic0Nl5leCxZfWTXRly1zmFoDixF9sHIH+nH6JUj2C8CHU9AKznYeVyLgCMEgqeNUYfQwdW+qUab/BagQePeHIoJB93UNrayWQd1dCFVYH4K/u2QO4UfjymIgzgcxDOr9x4nus4VVIR3ysAikroFIwl9pFW8b/kI+c5W8OdHVV1pjdLQOfIrtDTCRYamT4+bNuHT6Y4pwtKOsalSwBMM0JYwktuieRRB8AHOxkdJ0TJxyqMiELhsiOKGk81JPm+Um2yjcYt2EFDwsa7mkdWteKFXXwqg995cikKEyQRSDaCEgQmc1QTygaq2X58IizwvyRRIjqXdxzXulLaYDbhyahSuQ7kl1zKkXYPn5UBAAJUWp7at/LP3R+cgq4l82IFhTpQmEEWxzOU2ICQLPv8dQMv+F9YPAqAIxntBVKABCJMq0ltI2m3DwJSIHIC3li5cJMNU0WrgWztZVZ3N4F7HZcag1k6C9EWbUsn+tcqUDxnCpOvgOfaBYCj/IzGy6x8XBq+urm/inh3z7+l6UT+jov36nCh20OmZsfMpJhPx2Q7R/xQXLAJoVCGJoDk0RfRtBKgm6dC8s2ei8phmGz3hzz4qu3bqZ/pP21ABE0vywAlAIUdOuHXLmWEzu92nTqvfxLA2/QeqNJvRMPlT/ndWjhXHaauFMzmzqxV52Ee5o60ILvt27aPYVEXrO+qAOF35hq10WSBZLYepCBP5XZJE2dCrDo5tP0Qi7A6pvyARQ5n7EHOimFWUTpFHOEc82JZeynWQYa695wmBVsm101ZuY8GCam1F7KOjOljj+yanM5H0kziku0713BQh/8k8oFM6vpik0ip 0M/m1YWN KbTHIrRt0kltfUAz0cuC+kW3J8mF3UgCob3TXUPKbam044vEJeP4nosVQ42mHlldXJ/GBSAn7bdCHny61P2k6Xs3WYei3+djMZdY8W/tMDx3WMRuzuzo1FNG0a9gEJeA+fiVNzBOoq3626roVQ5DzQOl0MjS7qMFbBuzvtXJDy3uFsmGzT//LSGs83Va/XLatyVbgV7T6wXE+WNM95iYmGLPyS+Q6yrVbjVEgNcuuZLSMUNqP6v2Z3LaYo//X5vU7yEeKip5XYPNRLlkRe+Z8n2D8ETnjwYQiFgfflZiYyuzMv9aDl7n/vvxBrpLrk76Gxhw38/SU5X+XUyIU3t+0v7KV7aUVwQDixi6v3elcCCGnQQaIr+mQFdO8+IqfFBXU4B8izLWGTU3fGVzZqIYOcafhRn3pB4YMNXma0ZRj/0qwRuBhHKFgM0Fj89JAmaK9vEARM73stScaYDQQPuB8vIB5i1FNaSxsJHMPaGnR26JEKgrwe/b+PJRaL5vTsn4SLoTjUvJyHcOpHNZgG3GZ9WLLJQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, 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 | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ rust/helpers/percpu.c | 11 +++++ 4 files changed, 141 insertions(+) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ebe33181b6e6..959ce156c601 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2418,6 +2418,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 c38582f187dd..ab19106cc22c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -288,6 +288,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..a9652e6ece08 --- /dev/null +++ b/lib/percpu_test_rust.rs @@ -0,0 +1,120 @@ +// 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; + // SAFETY: PERCPU is properly defined + let mut pcpu: StaticPerCpu = unsafe { unsafe_get_per_cpu!(PERCPU) }; + // 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 {}\n", 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; + // SAFETY: UPERCPU is properly defined + let mut upcpu: StaticPerCpu = unsafe { unsafe_get_per_cpu!(UPERCPU) }; + + // 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: DynamicPerCpu = DynamicPerCpu::new(GFP_KERNEL).unwrap(); + + // SAFETY: No prerequisites for on_each_cpu. + 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) + } +} + +extern "C" fn inc_percpu(info: *mut c_void) { + // SAFETY: We know that info is a void *const DynamicPerCpu and DynamicPerCpu is Send. + let mut pcpu = unsafe { (*(info as *const DynamicPerCpu)).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); +} + +extern "C" fn check_percpu(info: *mut c_void) { + // SAFETY: We know that info is a void *const DynamicPerCpu and DynamicPerCpu is Send. + let mut pcpu = unsafe { (*(info as *const DynamicPerCpu)).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(); +} + -- 2.34.1