rust: allocator: add KUnit tests for alignment guarantees

Add a test module to verify memory alignment guarantees for Rust kernel
allocators.  The tests cover `Kmalloc`, `Vmalloc` and `KVmalloc`
allocators with both standard and large page-aligned allocations.

Key features of the tests:
1. Creates alignment-constrained types:
   - 128-byte aligned `Blob`
   - 8192-byte (4-page) aligned `LargeAlignBlob`
2. Validates allocators using `TestAlign` helper which:
   - Checks address alignment masks
   - Supports uninitialized allocations
3. Tests all three allocators with both alignment requirements:
   - Kmalloc with 128B and 8192B
   - Vmalloc with 128B and 8192B
   - KVmalloc with 128B and 8192B

Link: https://lkml.kernel.org/r/d2e3d6454c1435713be0fe3c0dc444d2c60bba51.1753929369.git.zhuhui@kylinos.cn
Co-developed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
Reviewed-by: Kunwu Chan <chentao@kylinos.cn>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Cc: Alex Gaynor <alex.gaynor@gmail.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Andreas Hindborg <a.hindborg@kernel.org>
Cc: Björn Roy Baron <bjorn3_gh@protonmail.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Gary Guo <gary@garyguo.net>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Trevor Gross <tmgross@umich.edu>
Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Hui Zhu 2025-07-31 10:50:05 +08:00 committed by Andrew Morton
parent 5094469205
commit 868ade323e

View File

@ -190,3 +190,59 @@ unsafe fn realloc(
unsafe { ReallocFunc::KVREALLOC.call(ptr, layout, old_layout, flags, nid) }
}
}
#[macros::kunit_tests(rust_allocator)]
mod tests {
use super::*;
use core::mem::MaybeUninit;
use kernel::prelude::*;
#[test]
fn test_alignment() -> Result {
const TEST_SIZE: usize = 1024;
const TEST_LARGE_ALIGN_SIZE: usize = kernel::page::PAGE_SIZE * 4;
// These two structs are used to test allocating aligned memory.
// they don't need to be accessed, so they're marked as dead_code.
#[expect(dead_code)]
#[repr(align(128))]
struct Blob([u8; TEST_SIZE]);
#[expect(dead_code)]
#[repr(align(8192))]
struct LargeAlignBlob([u8; TEST_LARGE_ALIGN_SIZE]);
struct TestAlign<T, A: Allocator>(Box<MaybeUninit<T>, A>);
impl<T, A: Allocator> TestAlign<T, A> {
fn new() -> Result<Self> {
Ok(Self(Box::<_, A>::new_uninit(GFP_KERNEL)?))
}
fn is_aligned_to(&self, align: usize) -> bool {
assert!(align.is_power_of_two());
let addr = self.0.as_ptr() as usize;
addr & (align - 1) == 0
}
}
let ta = TestAlign::<Blob, Kmalloc>::new()?;
assert!(ta.is_aligned_to(128));
let ta = TestAlign::<LargeAlignBlob, Kmalloc>::new()?;
assert!(ta.is_aligned_to(8192));
let ta = TestAlign::<Blob, Vmalloc>::new()?;
assert!(ta.is_aligned_to(128));
let ta = TestAlign::<LargeAlignBlob, Vmalloc>::new()?;
assert!(ta.is_aligned_to(8192));
let ta = TestAlign::<Blob, KVmalloc>::new()?;
assert!(ta.is_aligned_to(128));
let ta = TestAlign::<LargeAlignBlob, KVmalloc>::new()?;
assert!(ta.is_aligned_to(8192));
Ok(())
}
}