From nobody Tue Oct 7 01:53:48 2025 Received: from out-180.mta1.migadu.com (out-180.mta1.migadu.com [95.215.58.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78B1626D4E6 for ; Tue, 15 Jul 2025 10:00:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573623; cv=none; b=rGDnJVelUywFCUs4BiRo7lhgNqRn54jGJd64qi1t+qsB0ObivIilMnRc077XPAPXm9YZBokw3K9kScKEXHHkIaz3e2oCh8LsFT4ZUCSw3hHklq7aS2qT8RktCbobutKB2rN2ZyyuljnhevAgSXGlzLJUhR/UiCRTHFjkDAiV/Dg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573623; c=relaxed/simple; bh=FRpIBzJAs+zkjM4eEZtZEnNOq4IpmiLKr2n5/suoW98=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=D30xiGKcQ6GhtDLQPK/GzzOUrVJT0eZiCrMeNdCQpFwOsajZzG9LwdybnCgwfb2YjMjPubY6g79aasa5X0GUFXWVtBpQug4N9nLZAJtUnre9JjVucrWFSAK90g4PpSwfggcgPRAVQv0maEgofzFTfMIBsgBmVhKEu5hBHxzT2Cs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=rR7p1Lyb; arc=none smtp.client-ip=95.215.58.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="rR7p1Lyb" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1752573618; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7JRpjPQtsxOsEKyXUhk8AvHxOa1IbLg4OX688b1Boz8=; b=rR7p1Lybcl+KmgiLw+IM9aWE6ezyxo9p7M0asXbZuZZUxJ/cf9RifiJWj8Ao+X5yMMO432 ybr76/SJIsfcafqjuG86q+3K8tFDt9FvYpy4tnimn3RUeQaY87c7qoXGa1WNngAXsv3cyL nIJfLCRARG+D9H6HsmKJUbE+p5jsNh0= From: Hui Zhu To: Andrew Morton , Uladzislau Rezki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , bjorn3_gh@protonmail.com, Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Geliang Tang , Hui Zhu , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org Subject: [PATCH 1/3] vmalloc: Add vrealloc_align to support allocation of aligned vmap pages Date: Tue, 15 Jul 2025 17:59:46 +0800 Message-Id: <81647cce3b8e7139af47f20dbeba184b7a89b0cc.1752573305.git.zhuhui@kylinos.cn> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Hui Zhu This commit add new function vrealloc_align. vrealloc_align support allocation of aligned vmap pages with __vmalloc_node_noprof. And vrealloc_align will check the old address. If this address does not meet the current alignment requirements, it will also release the old vmap pages and reallocate new vmap pages that satisfy the alignment requirements. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Hui Zhu --- include/linux/vmalloc.h | 5 +++ mm/vmalloc.c | 80 ++++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index fdc9aeb74a44..0ce0c1ea2427 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -201,6 +201,11 @@ void * __must_check vrealloc_noprof(const void *p, siz= e_t size, gfp_t flags) __realloc_size(2); #define vrealloc(...) alloc_hooks(vrealloc_noprof(__VA_ARGS__)) =20 +void * __must_check vrealloc_align_noprof(const void *p, size_t size, + size_t align, gfp_t flags) + __realloc_size(2); +#define vrealloc_align(...) alloc_hooks(vrealloc_align_noprof(__VA_ARGS__)) + extern void vfree(const void *addr); extern void vfree_atomic(const void *addr); =20 diff --git a/mm/vmalloc.c b/mm/vmalloc.c index ab986dd09b6a..41cb3603b3cc 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -4081,9 +4081,11 @@ void *vzalloc_node_noprof(unsigned long size, int no= de) EXPORT_SYMBOL(vzalloc_node_noprof); =20 /** - * vrealloc - reallocate virtually contiguous memory; contents remain unch= anged + * vrealloc_align - reallocate virtually contiguous memory; + * contents remain unchanged * @p: object to reallocate memory for * @size: the size to reallocate + * @align: requested alignment * @flags: the flags for the page level allocator * * If @p is %NULL, vrealloc() behaves exactly like vmalloc(). If @size is = 0 and @@ -4103,7 +4105,8 @@ EXPORT_SYMBOL(vzalloc_node_noprof); * Return: pointer to the allocated memory; %NULL if @size is zero or in c= ase of * failure */ -void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) +void *vrealloc_align_noprof(const void *p, size_t size, size_t align, + gfp_t flags) { struct vm_struct *vm =3D NULL; size_t alloced_size =3D 0; @@ -4116,49 +4119,65 @@ void *vrealloc_noprof(const void *p, size_t size, g= fp_t flags) } =20 if (p) { + if (!is_power_of_2(align)) { + WARN(1, "Trying to vrealloc_align() align is not power of 2 (%ld)\n", + align); + return NULL; + } + vm =3D find_vm_area(p); if (unlikely(!vm)) { - WARN(1, "Trying to vrealloc() nonexistent vm area (%p)\n", p); + WARN(1, "Trying to vrealloc_align() nonexistent vm area (%p)\n", p); return NULL; } =20 alloced_size =3D get_vm_area_size(vm); old_size =3D vm->requested_size; if (WARN(alloced_size < old_size, - "vrealloc() has mismatched area vs requested sizes (%p)\n", p)) + "vrealloc_align() has mismatched area vs requested sizes (%p)\n", p)) return NULL; } =20 - /* - * TODO: Shrink the vm_area, i.e. unmap and free unused pages. What - * would be a good heuristic for when to shrink the vm_area? - */ - if (size <=3D old_size) { - /* Zero out "freed" memory, potentially for future realloc. */ - if (want_init_on_free() || want_init_on_alloc(flags)) - memset((void *)p + size, 0, old_size - size); - vm->requested_size =3D size; - kasan_poison_vmalloc(p + size, old_size - size); - return (void *)p; - } + if (IS_ALIGNED((unsigned long)p, align)) { + /* + * TODO: Shrink the vm_area, i.e. unmap and free unused pages. What + * would be a good heuristic for when to shrink the vm_area? + */ + if (size <=3D old_size) { + /* Zero out "freed" memory, potentially for future realloc. */ + if (want_init_on_free() || want_init_on_alloc(flags)) + memset((void *)p + size, 0, old_size - size); + vm->requested_size =3D size; + kasan_poison_vmalloc(p + size, old_size - size); + return (void *)p; + } =20 - /* - * We already have the bytes available in the allocation; use them. - */ - if (size <=3D alloced_size) { - kasan_unpoison_vmalloc(p + old_size, size - old_size, - KASAN_VMALLOC_PROT_NORMAL); /* - * No need to zero memory here, as unused memory will have - * already been zeroed at initial allocation time or during - * realloc shrink time. + * We already have the bytes available in the allocation; use them. + */ + if (size <=3D alloced_size) { + kasan_unpoison_vmalloc(p + old_size, size - old_size, + KASAN_VMALLOC_PROT_NORMAL); + /* + * No need to zero memory here, as unused memory will have + * already been zeroed at initial allocation time or during + * realloc shrink time. + */ + vm->requested_size =3D size; + return (void *)p; + } + } else { + /* + * p is not aligned with align. + * Allocate a new address to handle it. */ - vm->requested_size =3D size; - return (void *)p; + if (size < old_size) + old_size =3D size; } =20 /* TODO: Grow the vm_area, i.e. allocate and map additional pages. */ - n =3D __vmalloc_noprof(size, flags); + n =3D __vmalloc_node_noprof(size, align, flags, NUMA_NO_NODE, + __builtin_return_address(0)); if (!n) return NULL; =20 @@ -4170,6 +4189,11 @@ void *vrealloc_noprof(const void *p, size_t size, gf= p_t flags) return n; } =20 +void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) +{ + return vrealloc_align_noprof(p, size, 1, flags); +} + #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32) #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL) #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA) --=20 2.43.0 From nobody Tue Oct 7 01:53:48 2025 Received: from out-170.mta1.migadu.com (out-170.mta1.migadu.com [95.215.58.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A640F2D8361 for ; Tue, 15 Jul 2025 10:00:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573627; cv=none; b=U3rFNpK1cu2i8J/PoxiI6pX/H2UELZcMPUEp4oEXuSMSBlDITUT5VF2TUt+DaAc7J1B6cbZby6XWUbFvfDTAb8Ux3ZECzC3QGPo6yHXDh3199+w3nFE1y5UFbVC/iErlnfU7MXDssQYxIE/13ecvAYogcgHfGEouJtstX/Hminc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573627; c=relaxed/simple; bh=FSJsSS3WluCy8KvBbKjXlFYWWv4mZRNGrsBKukZ/cv8=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=REZQ0Pdmvswqk1l3HK5mKICX3LPWE36Y0qlfkA9aB+A48DT+YCZ3UEedK8UWiQnb1zErrNUY2ChRhnUBNqzWubdGKGoHlzfzm0acpIJaSXrWCKog5J0tZIq22YUtgaKP0eVXkUmV0ZobPtUQyaRHLdEqDabAV1/P7CZQF4WquZs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=sbo/b7yt; arc=none smtp.client-ip=95.215.58.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="sbo/b7yt" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1752573623; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sPnzVrWVUWuZIVWV/G/AQlEdfek6Y/tQOREMS8qveAQ=; b=sbo/b7yt/cBXHqBAnLzx1hfGwCbgVqPZpBFzq3KrZgKDKB6pjM4YwdAVIA0blBesWLMLRL ZHgdL9OZLdmYJFzHTZrj7g34pn3Y4NeBXkb/4wGBcx7neU0ffqTkNTSNdHcMGTNUtB2uve pGxfRNSOMreSemw3HuEW2+ql5wzXBdA= From: Hui Zhu To: Andrew Morton , Uladzislau Rezki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , bjorn3_gh@protonmail.com, Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Geliang Tang , Hui Zhu , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org Subject: [PATCH 2/3] rust: allocator: Vmalloc: Support alignments larger than PAGE_SIZE Date: Tue, 15 Jul 2025 17:59:47 +0800 Message-Id: <5e78317d87c42b548929ca386670837ad617fc9d.1752573305.git.zhuhui@kylinos.cn> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Hui Zhu This commit add code to make rust alloc Vmalloc support alignments larger than PAGE_SIZE. It adds a new option element to ReallocFunc. When an object supports aligned reallocation, it can register its alignment-specific realloc function here. During VREALLOC initialization, it sets bindings::vrealloc_align to this element. When ReallocFunc::call executes, if the object supports aligned reallocation and the alignment exceeds PAGE_SIZE, the aligned realloc function is used to support alignment capabilities. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Hui Zhu --- rust/helpers/vmalloc.c | 7 +++++++ rust/kernel/alloc/allocator.rs | 32 ++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/rust/helpers/vmalloc.c b/rust/helpers/vmalloc.c index 80d34501bbc0..3290c4c4c42f 100644 --- a/rust/helpers/vmalloc.c +++ b/rust/helpers/vmalloc.c @@ -7,3 +7,10 @@ rust_helper_vrealloc(const void *p, size_t size, gfp_t fla= gs) { return vrealloc(p, size, flags); } + +void * __must_check __realloc_size(2) +rust_helper_vrealloc_align(const void *p, size_t size, size_t align, + gfp_t flags) +{ + return vrealloc_align(p, size, align, flags); +} diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs index aa2dfa9dca4c..197222e15c26 100644 --- a/rust/kernel/alloc/allocator.rs +++ b/rust/kernel/alloc/allocator.rs @@ -59,17 +59,25 @@ fn aligned_size(new_layout: Layout) -> usize { /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. struct ReallocFunc( unsafe extern "C" fn(*const crate::ffi::c_void, usize, u32) -> *mut cr= ate::ffi::c_void, + Option< + unsafe extern "C" fn( + *const crate::ffi::c_void, + usize, + usize, + u32, + ) -> *mut crate::ffi::c_void, + >, ); =20 impl ReallocFunc { // INVARIANT: `krealloc` satisfies the type invariants. - const KREALLOC: Self =3D Self(bindings::krealloc); + const KREALLOC: Self =3D Self(bindings::krealloc, None); =20 // INVARIANT: `vrealloc` satisfies the type invariants. - const VREALLOC: Self =3D Self(bindings::vrealloc); + const VREALLOC: Self =3D Self(bindings::vrealloc, Some(bindings::vreal= loc_align)); =20 // INVARIANT: `kvrealloc` satisfies the type invariants. - const KVREALLOC: Self =3D Self(bindings::kvrealloc); + const KVREALLOC: Self =3D Self(bindings::kvrealloc, None); =20 /// # Safety /// @@ -108,9 +116,15 @@ unsafe fn call( // GUARANTEE: // - `self.0` is one of `krealloc`, `vrealloc`, `kvrealloc`. // - Those functions provide the guarantees of this function. - let raw_ptr =3D unsafe { - // If `size =3D=3D 0` and `ptr !=3D NULL` the memory behind th= e pointer is freed. - self.0(ptr.cast(), size, flags.0).cast() + // If `size =3D=3D 0` and `ptr !=3D NULL` the memory behind the po= inter is freed. + let raw_ptr =3D if let Some(f) =3D self.1 { + if layout.align() > bindings::PAGE_SIZE { + unsafe { f(ptr.cast(), size, layout.align(), flags.0).cast= () } + } else { + unsafe { self.0(ptr.cast(), size, flags.0).cast() } + } + } else { + unsafe { self.0(ptr.cast(), size, flags.0).cast() } }; =20 let ptr =3D if size =3D=3D 0 { @@ -152,12 +166,6 @@ unsafe fn realloc( old_layout: Layout, flags: Flags, ) -> Result, AllocError> { - // TODO: Support alignments larger than PAGE_SIZE. - if layout.align() > bindings::PAGE_SIZE { - pr_warn!("Vmalloc does not support alignments larger than PAGE= _SIZE yet.\n"); - return Err(AllocError); - } - // SAFETY: If not `None`, `ptr` is guaranteed to point to valid me= mory, which was previously // allocated with this `Allocator`. unsafe { ReallocFunc::VREALLOC.call(ptr, layout, old_layout, flags= ) } --=20 2.43.0 From nobody Tue Oct 7 01:53:48 2025 Received: from out-177.mta1.migadu.com (out-177.mta1.migadu.com [95.215.58.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B0CB26FDA8 for ; Tue, 15 Jul 2025 10:00:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573630; cv=none; b=ayEAQ+qCWAfZbcMZiW6Ldm6f5egGWg5n8YXSvWJ6Miy/NS+GjO+NLqrRvBo7Y750bKkSfOVeFeb98AdGiOJtjIKwjDfNERMBPzYL8j8BwYhXDQbCRuUljz2Xids/DSffky4bw+Tqxj0WcX6ysU1UMo7+IJkU/Ad/Ls/wFXQpu5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752573630; c=relaxed/simple; bh=ZW3RqUJQuINLZ2qkCDUQ3IViyrhHhK2qpkUxP/3iNF4=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=D+PQeWXnWerfR9vzEPotGbgH8jXHbnfTUETk1xjAjzPze6/rx08r6QONJrTaV4T9Y54YRbhGmLeyYgeS7BKxsfvLywbyZvNG3UaFDHxUtCEjOoZs1SWWasgGL4JYngQ2+BVKnbiiKsdeAGR7bcWXoiMuHFrlhefiaOqXFJicMes= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=nSpT6uLY; arc=none smtp.client-ip=95.215.58.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="nSpT6uLY" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1752573626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0hMXD4Bvb1YUfWztWBUy/WVwu1WJGbTx3ryS1MpxlDU=; b=nSpT6uLYE5l6za43VDR0XD6aFfHyA9chbD/+oRLXEvpAOhjkomitJTy5toxr/PXV1urzDF sRuFnKpIof8teSp/n5zjeybvYwzdwtuRcs6T5OEWkRXO0fSEBTwSwLhuOrq0i7f9Ms8I+Q kE7a/y0hwYE+jXc88x75fob7giS9KxQ= From: Hui Zhu To: Andrew Morton , Uladzislau Rezki , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , bjorn3_gh@protonmail.com, Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Geliang Tang , Hui Zhu , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org Subject: [PATCH 3/3] rust: add a sample allocator usage Date: Tue, 15 Jul 2025 17:59:48 +0800 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Hui Zhu Add a sample to the samples memory allocator usage. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Hui Zhu --- samples/rust/Kconfig | 10 ++++ samples/rust/Makefile | 1 + samples/rust/rust_allocator.rs | 104 +++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 samples/rust/rust_allocator.rs diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 7f7371a004ee..79c73f6c5216 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -105,6 +105,16 @@ config SAMPLE_RUST_DRIVER_AUXILIARY =20 If unsure, say N. =20 +config SAMPLE_RUST_ALLOCATOR + tristate "Allocator Test Driver" + help + This option builds the Rust allocator Test driver sample. + + To compile this as a module, choose M here: + the module will be called rust_dma. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index bd2faad63b4f..b378959eab19 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_drive= r_platform.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) +=3D rust_driver_auxiliary.o obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) +=3D rust_configfs.o +obj-$(CONFIG_SAMPLE_RUST_ALLOCATOR) +=3D rust_allocator.o =20 rust_print-y :=3D rust_print_main.o rust_print_events.o =20 diff --git a/samples/rust/rust_allocator.rs b/samples/rust/rust_allocator.rs new file mode 100644 index 000000000000..13d23cc9d682 --- /dev/null +++ b/samples/rust/rust_allocator.rs @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (c) 2025, Kylin Software + +//! Rust allocator sample. + +use core::{alloc::Layout, ptr::NonNull}; +use kernel::alloc::allocator; +use kernel::alloc::Allocator; +use kernel::bindings; +use kernel::prelude::*; + +module! { + type: RustAllocator, + name: "rust_allocator", + authors: ["Rust for Linux Contributors"], + description: "Rust allocator sample", + license: "GPL", +} + +const VMALLOC_ARG: [(usize, usize); 2] =3D [ + (bindings::PAGE_SIZE * 4, bindings::PAGE_SIZE * 2), + (1024, 128), +]; + +struct RustAllocator { + vmalloc_vec: KVec<(usize, Layout)>, +} + +fn vmalloc_align(size: usize, align: usize) -> Result<(NonNull<[u8]>, Layo= ut)> { + let layout =3D Layout::from_size_align(size, align).map_err(|_| EINVAL= )?; + + Ok(( + ::alloc(layout, GFP_KERNEL).map_e= rr(|_| EINVAL)?, + layout, + )) +} + +fn vfree(addr: usize, layout: Layout) { + let vmalloc_ptr =3D NonNull::new(addr as *mut u8); + if let Some(ptr) =3D vmalloc_ptr { + unsafe { + ::free(ptr, layout); + } + } else { + pr_err!("Failed to vfree: pointer is null\n"); + } +} + +fn check_ptr(ptr: NonNull<[u8]>, size: usize, align: usize) -> (usize, boo= l) { + let current_size =3D unsafe { ptr.as_ref().len() }; + if current_size !=3D size { + pr_err!( + "The length to be allocated is {}, and the actually allocated = memory length is {}.\n", + size, + current_size + ); + return (0, false); + } + + let addr =3D ptr.cast::().as_ptr() as usize; + debug_assert!(align.is_power_of_two()); + if addr & (align - 1) !=3D 0 { + pr_err!("Address {:#x} is not aligned with {:#x}.\n", addr, align); + return (0, false); + } + + (addr, true) +} + +fn clear_vmalloc_vec(v: &KVec<(usize, Layout)>) { + for (addr, layout) in v { + vfree(*addr, *layout); + } +} + +impl kernel::Module for RustAllocator { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("Rust allocator sample (init)\n"); + + let mut vmalloc_vec =3D KVec::new(); + for (size, align) in VMALLOC_ARG { + let (ptr, layout) =3D vmalloc_align(size, align)?; + + let (addr, is_ok) =3D check_ptr(ptr, size, align); + if !is_ok { + clear_vmalloc_vec(&vmalloc_vec); + return Err(EINVAL); + } + + vmalloc_vec.push((addr, layout), GFP_KERNEL)?; + } + + Ok(RustAllocator { vmalloc_vec }) + } +} + +impl Drop for RustAllocator { + fn drop(&mut self) { + pr_info!("Rust allocator sample (exit)\n"); + + clear_vmalloc_vec(&self.vmalloc_vec); + } +} --=20 2.43.0