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(); +} +