Add a short exercise for Rust's per-CPU variable API, modelled after lib/percpu_test.c Signed-off-by: Mitchell Levy <levymitchell0@xxxxxxxxx> --- lib/Kconfig.debug | 9 +++++++ lib/Makefile | 1 + lib/percpu_test_rust.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f3d723705879..75a91f1766ce 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2404,6 +2404,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 a8155c972f02..0ea8d414763c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -301,6 +301,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..60df44332d7a --- /dev/null +++ b/lib/percpu_test_rust.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +//! A simple self test for the rust per-CPU API. +use kernel::{ + define_per_cpu, percpu::cpu_guard::*, percpu::*, pr_info, prelude::*, unsafe_get_per_cpu_ref, +}; + +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<Self, Error> { + pr_info!("rust percpu test start\n"); + + let mut native: i64 = 0; + let mut pcpu: PerCpuRef<i64> = unsafe { unsafe_get_per_cpu_ref!(PERCPU, CpuGuard::new()) }; + + native += -1; + *pcpu += -1; + assert!(native == *pcpu && native == -1); + + native += 1; + *pcpu += 1; + assert!(native == *pcpu && native == 0); + + let mut unative: u64 = 0; + let mut upcpu: PerCpuRef<u64> = + unsafe { unsafe_get_per_cpu_ref!(UPERCPU, CpuGuard::new()) }; + + unative += 1; + *upcpu += 1; + assert!(unative == *upcpu && unative == 1); + + unative = unative.wrapping_add((-1i64) as u64); + *upcpu = upcpu.wrapping_add((-1i64) as u64); + assert!(unative == *upcpu && unative == 0); + + unative = unative.wrapping_add((-1i64) as u64); + *upcpu = upcpu.wrapping_add((-1i64) as u64); + assert!(unative == *upcpu && unative == (-1i64) as u64); + + unative = 0; + *upcpu = 0; + + unative = unative.wrapping_sub(1); + *upcpu = upcpu.wrapping_sub(1); + assert!(unative == *upcpu && unative == (-1i64) as u64); + assert!(unative == *upcpu && unative == u64::MAX); + + pr_info!("rust percpu test done\n"); + + // Return Err to unload the module + Result::Err(EINVAL) + } +} + -- 2.34.1