* [PATCH v10 0/3] rust: Add support for reserving of ranges of IDs
@ 2026-10-19 4:29 Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 1/3] rust: use Alignment size constants Eliot Courtney
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Eliot Courtney @ 2026-10-19 4:29 UTC (permalink / raw)
To: Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, rust-for-linux, linux-kernel, nova-gpu, dri-devel,
Eliot Courtney
Add support for reserving of ranges of IDs, with a usage in nova-core
for channel IDs.
The bitmap and `IdPool` parts from earlier versions are in rust-next
now, and this version has the remaining patches: using the `Alignment`
size constants, exact `IdPool` capacities, and `ChannelIdPool`.
Channel ID tracking is needed for allotting ranges of channel IDs to
vGPU guests, and later for regular host channel ID reservation.
nova-core needs allocation of a contiguous sequence of IDs with a
specific length and sometimes a specific alignment [1].
About the tradeoffs between different data structures:
- IDA/xarray do not support allocating a contiguous sequence of IDs
(ida_alloc_range() allocates a single ID within a range, not a contiguous
sequence).
- A maple tree works, but is not as good a fit. The ID space is small
(limited to 2048) and aligned allocation needs an alloc_range()+erase() retry
loop (plus a Mutex around it, or new mas_empty_area() bindings) that
essentially reimplements bitmap_find_next_zero_area(). See the maple tree
version at [2]. For 2048 IDs a bitmap is also considerably faster and smaller
[3].
- The bitmap API natively supports aligned contiguous area allocation
(bitmap_find_next_zero_area()).
This is based on drm-rust-next. It depends on the v9 patches that were
applied to rust-next [5] and on the cv! series [4].
[1]: https://lore.kernel.org/all/84bc8bd2-e292-4b84-9580-a1b5df4c5bdc@nvidia.com/
[2]: https://lore.kernel.org/all/20260710-chid-maple-v1-1-4ee869055268@nvidia.com/
[3]: https://lore.kernel.org/all/20260717053241.916441-1-ynorov@nvidia.com/
[4]: https://lore.kernel.org/all/20261013-cv-v5-0-113a538dfaef@nvidia.com/
[5]: https://lore.kernel.org/all/CANiq72kohkx1-9iendYSD4gML8wv5bF+HrY7RO2vagLhtXYSKQ@mail.gmail.com/
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
Changes in v10:
- Drop the patches that were applied to rust-next
- Rebase on drm-rust-next (plus pre-reqs)
- Use a capacity of 1 instead of 0 in the grow_request() example in
patch #2 (Yury)
- Convert the remaining Alignment::new() users in nova-core in patch #1
- Link to v9: https://patch.msgid.link/20260930-chid-v9-0-0d6cca376cff@nvidia.com
Changes in v9:
- Rebase on drm-rust-next
- Moved cv! to a separate series which this now depends on
- Reference Link: tag from the text + indent code in patch #4 commit
message (Miguel)
- Add reviewed-by tags
- Link to v8: https://patch.msgid.link/20260827-chid-v8-0-bc74c77d0214@nvidia.com
Changes in v8:
- Clarify overflow cases in patch #2 (Alex)
- Replace nz! with generalized cv! macro (Gary)
- Add cv! macro to prelude
- Split SizeConstants and adding new constants patch (Alex)
- Move alignment size constants conersions patch (Alex)
- Drop NonZero on IdPool, fix grow_request instead (Alice, Alex)
- Add shrink/grow doctests (Burak)
- Link to v7: https://patch.msgid.link/20260817-chid-v7-0-a5872e64d8f4@nvidia.com
Changes in v7:
- Add nz! macro for compile time NonZero
- Implement SizeConstants for Alignment + add sub 1k size constants
- Use Alignment constants + nz! in this series
- Add final patch converting existing callers to use Alignment constants
- Rename alloc_area/release_area -> reserve_ids / release_ids
- Link to v6: https://patch.msgid.link/20260813-chid-v6-0-160be5dfb5bd@nvidia.com
Changes in v6:
- Take a NonZero nbits in `next_zero_area_off`, `set` and `clear` (Yury)
- Remove `UnusedArea`, `IdPool::alloc_area` now allocates directly (Yury)
- Add patch: take a NonZero capacity in `IdPool::with_capacity()`
- Add patch: do not round the capacity up to `BitmapVec::MAX_INLINE_LEN`,
which also removes the bounds check in `ChannelIdPool::alloc_area`
- Add more testing of Drop for `ChannelIdPool` (Yury)
- Link to v5: https://patch.msgid.link/20260812-chid-v5-0-6c767770b3f4@nvidia.com
Changes in v5:
- `bitmap_assert!` i32::MAX length for Bitmap::from_raw* (Yury)
- Only run overflow check on 32-bit (Yury)
- Link to v4: https://patch.msgid.link/20260810-chid-v4-0-c9f206fdcb97@nvidia.com
Changes in v4:
- Add `next_zero_area_off` to match C code (Yury)
- Replace overflow checks to match C code in bitmap-for-next.
- Tighten `Bitmap` unsafe contract to disallow Bitmaps larger than i32::MAX
- Link to v3: https://patch.msgid.link/20260729-chid-v3-0-20cc08032bbc@nvidia.com
Changes in v3:
- Use `Alignment` type in id_pool and bitmap (Alice)
- Remove hang check on the basis that it's extraordinarily rare.
- Link to v2: https://patch.msgid.link/20260723-chid-v2-0-c35e5e9fb3d9@nvidia.com
Changes in v2:
- Collected Alice's Reviewed-by on patch 1.
- Address Yury's comments w.r.t. using __bitmap_set etc directly.
- Address Yury's comments w.r.t. following the C names
- Additionally check for an overflow case that causes a hang
- Added more info to cover letter + patch 4 w.r.t. channel ID allottment
requirements
- Add align parameter to ChannelIdPool::alloc_area() plus an aligned
allocation test
- Add missing INVARIANT comment when constructing UnusedArea
- Link to v1:
https://patch.msgid.link/20260703-chid-v1-0-84fe8259e46e@nvidia.com
---
Eliot Courtney (3):
rust: use Alignment size constants
rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN
gpu: nova-core: add ChannelIdPool
drivers/gpu/nova-core/fb.rs | 10 +-
drivers/gpu/nova-core/fb/hal/gb100.rs | 2 +-
drivers/gpu/nova-core/fsp.rs | 4 +-
drivers/gpu/nova-core/gpu.rs | 9 +-
drivers/gpu/nova-core/gpu/channel.rs | 198 ++++++++++++++++++++++++++++++
drivers/gpu/nova-core/gsp/fw.rs | 12 +-
drivers/gpu/nova-core/mm.rs | 2 +-
drivers/gpu/nova-core/mm/bar_user.rs | 7 +-
drivers/gpu/nova-core/mm/pagetable/map.rs | 7 +-
drivers/gpu/nova-core/mm/pramin.rs | 6 +-
drivers/gpu/nova-core/vbios.rs | 7 +-
rust/kernel/gpu/buddy.rs | 26 ++--
rust/kernel/id_pool.rs | 38 +++++-
rust/kernel/io.rs | 5 +-
14 files changed, 279 insertions(+), 54 deletions(-)
---
base-commit: 3497a403264b094ebd61b8b755165d56e7d9dc37
change-id: 20260608-chid-18fa943c6d6c
prerequisite-change-id: 20260828-cv-8d4e952fc14c:v5
prerequisite-patch-id: 26927fa5f94065327024bc2b0c97272f8c0ccc1d
prerequisite-patch-id: 01ec2e5a44b393a7ce1ee820654750dd4743fcb5
Best regards,
--
Eliot Courtney <ecourtney@nvidia.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v10 1/3] rust: use Alignment size constants
2026-10-19 4:29 [PATCH v10 0/3] rust: Add support for reserving of ranges of IDs Eliot Courtney
@ 2026-10-19 4:29 ` Eliot Courtney
2026-10-19 4:41 ` sashiko-bot
2026-10-19 4:29 ` [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool Eliot Courtney
2 siblings, 1 reply; 7+ messages in thread
From: Eliot Courtney @ 2026-10-19 4:29 UTC (permalink / raw)
To: Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, rust-for-linux, linux-kernel, nova-gpu, dri-devel,
Eliot Courtney
Use `SizeConstants` for Alignment that are implemented now.
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
drivers/gpu/nova-core/fb.rs | 10 +++++-----
drivers/gpu/nova-core/fb/hal/gb100.rs | 2 +-
drivers/gpu/nova-core/fsp.rs | 4 ++--
drivers/gpu/nova-core/gpu.rs | 7 ++-----
drivers/gpu/nova-core/gsp/fw.rs | 12 +++---------
drivers/gpu/nova-core/mm.rs | 2 +-
drivers/gpu/nova-core/mm/bar_user.rs | 7 ++++---
drivers/gpu/nova-core/mm/pagetable/map.rs | 7 +++++--
drivers/gpu/nova-core/mm/pramin.rs | 6 +++---
drivers/gpu/nova-core/vbios.rs | 7 +++++--
rust/kernel/gpu/buddy.rs | 26 +++++++++++++-------------
rust/kernel/io.rs | 5 +++--
12 files changed, 47 insertions(+), 48 deletions(-)
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index b0c0b8fe6008..5ceb7760c78e 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -219,7 +219,7 @@ pub(crate) fn new(
};
let frts = {
- const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>();
+ const FRTS_DOWN_ALIGN: Alignment = Alignment::SZ_128K;
let frts_size: u64 = hal.frts_size();
let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - frts_size;
@@ -227,7 +227,7 @@ pub(crate) fn new(
};
let boot = {
- const BOOTLOADER_DOWN_ALIGN: Alignment = Alignment::new::<SZ_4K>();
+ const BOOTLOADER_DOWN_ALIGN: Alignment = Alignment::SZ_4K;
let bootloader_size = u64::from_safe_cast(gsp_fw.bootloader.ucode.size());
let bootloader_base = (frts.start - bootloader_size).align_down(BOOTLOADER_DOWN_ALIGN);
@@ -235,7 +235,7 @@ pub(crate) fn new(
};
let fw_image = {
- const FW_IMAGE_DOWN_ALIGN: Alignment = Alignment::new::<SZ_64K>();
+ const FW_IMAGE_DOWN_ALIGN: Alignment = Alignment::SZ_64K;
let fw_image_size = u64::from_safe_cast(gsp_fw.size());
let fw_image_addr = (boot.start - fw_image_size).align_down(FW_IMAGE_DOWN_ALIGN);
@@ -245,7 +245,7 @@ pub(crate) fn new(
let (vf_partition_count, wpr2_heap_size) = wpr2_heap_params(chipset, vgpu_state, fb.end)?;
let wpr2_heap = {
- const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::new::<SZ_1M>();
+ const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::SZ_1M;
let wpr2_heap_addr = fw_image
.start
.checked_sub(wpr2_heap_size)
@@ -256,7 +256,7 @@ pub(crate) fn new(
};
let wpr2 = {
- const WPR2_DOWN_ALIGN: Alignment = Alignment::new::<SZ_1M>();
+ const WPR2_DOWN_ALIGN: Alignment = Alignment::SZ_1M;
let wpr2_addr = (wpr2_heap.start - u64::from_safe_cast(size_of::<gsp::GspFwWprMeta>()))
.align_down(WPR2_DOWN_ALIGN);
diff --git a/drivers/gpu/nova-core/fb/hal/gb100.rs b/drivers/gpu/nova-core/fb/hal/gb100.rs
index 612f70333c11..37b2ae762df4 100644
--- a/drivers/gpu/nova-core/fb/hal/gb100.rs
+++ b/drivers/gpu/nova-core/fb/hal/gb100.rs
@@ -80,7 +80,7 @@ fn write_sysmem_flush_page_gb100(hshub0: Mmio<'_, regs::Hshub0Registers>, addr:
// This PMU reservation size is r570-specific.
pub(super) const fn pmu_reserved_size_gb100() -> u32 {
- cv!(const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::new::<SZ_128K>()).unwrap())
+ cv!(const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::SZ_128K).unwrap())
}
impl FbHal for Gb100 {
diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
index 3a4a10487f33..637a00b2c951 100644
--- a/drivers/gpu/nova-core/fsp.rs
+++ b/drivers/gpu/nova-core/fsp.rs
@@ -20,7 +20,7 @@
Alignable,
Alignment, //
},
- sizes::SZ_2M,
+ sizes::SizeConstants,
time::Delta,
transmute::{
AsBytes,
@@ -259,7 +259,7 @@ fn frts_vidmem_offset(hal: &dyn hal::FspHal, fb_info: &FbSizes) -> Result<u64> {
if fb_info.pmu_reserved_size != 0 {
offset = (offset + u64::from(fb_info.pmu_reserved_size))
// The 2 MiB alignment is r570-specific.
- .align_up(Alignment::new::<SZ_2M>())
+ .align_up(Alignment::SZ_2M)
.ok_or(EINVAL)?;
}
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 4e59072cab50..9a91cff01e78 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -12,10 +12,7 @@
pci,
prelude::*,
ptr::Alignment,
- sizes::{
- SizeConstants,
- SZ_4K, //
- },
+ sizes::SizeConstants,
uapi, //
};
@@ -568,7 +565,7 @@ pub(crate) fn new<'a>(
let buddy_params = GpuBuddyParams {
base_offset: usable_vram.start,
size: usable_vram.end - usable_vram.start,
- chunk_size: Alignment::new::<SZ_4K>(),
+ chunk_size: Alignment::SZ_4K,
};
GpuMm::new(
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index 1b548bbf146e..b4866ad21f6e 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -25,10 +25,7 @@
Alignment,
KnownSize, //
},
- sizes::{
- SizeConstants,
- SZ_128K, //
- },
+ sizes::SizeConstants,
transmute::{
AsBytes,
FromBytes, //
@@ -63,7 +60,7 @@
enum GspFwHeapParams {}
/// Minimum required alignment for the GSP heap.
-const GSP_HEAP_ALIGNMENT: Alignment = Alignment::new::<{ 1 << 20 }>();
+const GSP_HEAP_ALIGNMENT: Alignment = Alignment::SZ_1M;
impl GspFwHeapParams {
/// Returns the amount of GSP-RM heap memory used during GSP-RM boot and initialization (up to
@@ -207,10 +204,7 @@ pub(crate) fn from_ranges<'a>(
bootBinOffset: ranges.boot.start,
frtsOffset: ranges.frts.start,
frtsSize: ranges.frts.len(),
- gspFwWprEnd: ranges
- .vga_workspace
- .start
- .align_down(Alignment::new::<SZ_128K>()),
+ gspFwWprEnd: ranges.vga_workspace.start.align_down(Alignment::SZ_128K),
gspFwHeapVfPartitionCount: ranges.vf_partition_count,
fbSize: ranges.fb.len(),
vgaWorkspaceOffset: ranges.vga_workspace.start,
diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs
index 8a934c55169f..f53886f9ed91 100644
--- a/drivers/gpu/nova-core/mm.rs
+++ b/drivers/gpu/nova-core/mm.rs
@@ -317,7 +317,7 @@ pub(crate) fn run(
let base = usable_fb_regions.iter().find_map(|region| {
// Tests rely on this being 8 byte aligned for checking misalignment handling.
- let base = region.start.align_up(Alignment::new::<8>())?;
+ let base = region.start.align_up(Alignment::SZ_8)?;
(base.checked_add(SELFTEST_SPAN)? <= region.end).then_some(base)
});
let Some(base) = base else {
diff --git a/drivers/gpu/nova-core/mm/bar_user.rs b/drivers/gpu/nova-core/mm/bar_user.rs
index 6e9384f06f43..2e8bd2a8ed91 100644
--- a/drivers/gpu/nova-core/mm/bar_user.rs
+++ b/drivers/gpu/nova-core/mm/bar_user.rs
@@ -195,6 +195,7 @@ pub(crate) fn run_self_test(
},
ptr::Alignment,
sizes::{
+ SizeConstants,
SZ_16K,
SZ_32K,
SZ_4K,
@@ -222,7 +223,7 @@ pub(crate) fn run_self_test(
mm.buddy().alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_4K.into_safe_cast(),
- Alignment::new::<SZ_4K>(),
+ Alignment::SZ_4K,
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
@@ -299,7 +300,7 @@ pub(crate) fn run_self_test(
mm.buddy().alloc_blocks(
GpuBuddyAllocMode::Range(range_base + sz_16k..range_base + sz_16k + sz_4k),
SZ_4K.into_safe_cast(),
- Alignment::new::<SZ_4K>(),
+ Alignment::SZ_4K,
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
@@ -311,7 +312,7 @@ pub(crate) fn run_self_test(
mm.buddy().alloc_blocks(
GpuBuddyAllocMode::Range(range_base..range_base + sz_32k_4k),
SZ_32K.into_safe_cast(),
- Alignment::new::<SZ_4K>(),
+ Alignment::SZ_4K,
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
diff --git a/drivers/gpu/nova-core/mm/pagetable/map.rs b/drivers/gpu/nova-core/mm/pagetable/map.rs
index 77431c509a89..f7774b9cc972 100644
--- a/drivers/gpu/nova-core/mm/pagetable/map.rs
+++ b/drivers/gpu/nova-core/mm/pagetable/map.rs
@@ -17,7 +17,10 @@
RBTree,
RBTreeNode, //
},
- sizes::SZ_4K, //
+ sizes::{
+ SizeConstants,
+ SZ_4K, //
+ }, //
};
use super::{
@@ -84,7 +87,7 @@ fn alloc_and_zero_page(mm: &mut GpuMm<'_>, level: PageTableLevel) -> Result<Prep
mm.buddy().alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_4K.into_safe_cast(),
- Alignment::new::<SZ_4K>(),
+ Alignment::SZ_4K,
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
diff --git a/drivers/gpu/nova-core/mm/pramin.rs b/drivers/gpu/nova-core/mm/pramin.rs
index 7f89c093d591..c83b1681d241 100644
--- a/drivers/gpu/nova-core/mm/pramin.rs
+++ b/drivers/gpu/nova-core/mm/pramin.rs
@@ -19,8 +19,8 @@
Alignment, //
},
sizes::{
- SZ_1M,
- SZ_64K, //
+ SizeConstants,
+ SZ_1M, //
},
};
@@ -103,7 +103,7 @@ fn drop(&mut self) {
impl<'gpu> Pramin<'gpu> {
/// Alignment required by the PRAMIN window.
- const BASE_ALIGN: Alignment = Alignment::new::<SZ_64K>();
+ const BASE_ALIGN: Alignment = Alignment::SZ_64K;
/// Creates the window manager for the given VRAM region.
pub(super) fn new(
diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs
index 9c214b9f4dd9..a2d2d170b501 100644
--- a/drivers/gpu/nova-core/vbios.rs
+++ b/drivers/gpu/nova-core/vbios.rs
@@ -11,7 +11,10 @@
Alignment, //
},
register,
- sizes::SZ_4K,
+ sizes::{
+ SizeConstants,
+ SZ_4K, //
+ },
sync::aref::ARef,
};
@@ -291,7 +294,7 @@ fn next(&mut self) -> Option<Self::Item> {
// Advance to next image (aligned to 512 bytes).
self.current_offset += image_size;
- self.current_offset = self.current_offset.align_up(Alignment::new::<512>())?;
+ self.current_offset = self.current_offset.align_up(Alignment::SZ_512)?;
Some(Ok(full_image))
}
diff --git a/rust/kernel/gpu/buddy.rs b/rust/kernel/gpu/buddy.rs
index d502ada6ebbd..691bb40629d4 100644
--- a/rust/kernel/gpu/buddy.rs
+++ b/rust/kernel/gpu/buddy.rs
@@ -31,11 +31,11 @@
//! let buddy = GpuBuddy::new(GpuBuddyParams {
//! base_offset: 0,
//! size: SZ_1G as u64,
-//! chunk_size: Alignment::new::<SZ_4K>(),
+//! chunk_size: Alignment::SZ_4K,
//! })?;
//!
//! assert_eq!(buddy.size(), SZ_1G as u64);
-//! assert_eq!(buddy.chunk_size(), Alignment::new::<SZ_4K>());
+//! assert_eq!(buddy.chunk_size(), Alignment::SZ_4K);
//! let initial_free = buddy.avail();
//!
//! // Allocate 16MB. Block lands at the top of the address range.
@@ -43,7 +43,7 @@
//! buddy.alloc_blocks(
//! GpuBuddyAllocMode::Simple,
//! SZ_16M as u64,
-//! Alignment::new::<SZ_16M>(),
+//! Alignment::SZ_16M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -74,14 +74,14 @@
//! # let buddy = GpuBuddy::new(GpuBuddyParams {
//! # base_offset: 0,
//! # size: SZ_1G as u64,
-//! # chunk_size: Alignment::new::<SZ_4K>(),
+//! # chunk_size: Alignment::SZ_4K,
//! # })?;
//! # let initial_free = buddy.avail();
//! let topdown = KBox::pin_init(
//! buddy.alloc_blocks(
//! GpuBuddyAllocMode::TopDown,
//! SZ_16M as u64,
-//! Alignment::new::<SZ_16M>(),
+//! Alignment::SZ_16M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -114,7 +114,7 @@
//! # let buddy = GpuBuddy::new(GpuBuddyParams {
//! # base_offset: 0,
//! # size: SZ_1G as u64,
-//! # chunk_size: Alignment::new::<SZ_4K>(),
+//! # chunk_size: Alignment::SZ_4K,
//! # })?;
//! # let initial_free = buddy.avail();
//! // Create fragmentation by allocating 4MB blocks at [0,4M) and [8M,12M).
@@ -122,7 +122,7 @@
//! buddy.alloc_blocks(
//! GpuBuddyAllocMode::Range(0..SZ_4M as u64),
//! SZ_4M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -133,7 +133,7 @@
//! buddy.alloc_blocks(
//! GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
//! SZ_4M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -145,7 +145,7 @@
//! buddy.alloc_blocks(
//! GpuBuddyAllocMode::Range(0..SZ_16M as u64),
//! SZ_8M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -178,14 +178,14 @@
//! let small = GpuBuddy::new(GpuBuddyParams {
//! base_offset: 0,
//! size: SZ_16M as u64,
-//! chunk_size: Alignment::new::<SZ_4K>(),
+//! chunk_size: Alignment::SZ_4K,
//! })?;
//!
//! let _hole1 = KBox::pin_init(
//! small.alloc_blocks(
//! GpuBuddyAllocMode::Range(0..SZ_4M as u64),
//! SZ_4M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -195,7 +195,7 @@
//! small.alloc_blocks(
//! GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
//! SZ_4M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlags::default(),
//! ),
//! GFP_KERNEL,
@@ -206,7 +206,7 @@
//! small.alloc_blocks(
//! GpuBuddyAllocMode::Simple,
//! SZ_8M as u64,
-//! Alignment::new::<SZ_4M>(),
+//! Alignment::SZ_4M,
//! GpuBuddyAllocFlag::Contiguous,
//! ),
//! GFP_KERNEL,
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index de8ef8e2aec4..5712478a5461 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -19,7 +19,8 @@
ptr::{
Alignment,
KnownSize, //
- }, //
+ },
+ sizes::SizeConstants, //
};
#[cfg(CONFIG_HAS_IOMEM)]
@@ -90,7 +91,7 @@ pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Sel
impl<const SIZE: usize> KnownSize for Region<SIZE> {
const MIN_SIZE: usize = SIZE;
// Alignment of 4 is the most common; different base types can be added once required.
- const MIN_ALIGN: Alignment = Alignment::new::<4>();
+ const MIN_ALIGN: Alignment = Alignment::SZ_4;
#[inline(always)]
fn size(p: *const Self) -> usize {
--
2.56.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN
2026-10-19 4:29 [PATCH v10 0/3] rust: Add support for reserving of ranges of IDs Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 1/3] rust: use Alignment size constants Eliot Courtney
@ 2026-10-19 4:29 ` Eliot Courtney
2026-10-19 4:37 ` sashiko-bot
2026-10-19 4:29 ` [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool Eliot Courtney
2 siblings, 1 reply; 7+ messages in thread
From: Eliot Courtney @ 2026-10-19 4:29 UTC (permalink / raw)
To: Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, rust-for-linux, linux-kernel, nova-gpu, dri-devel,
Eliot Courtney
Current code in IdPool::with_capacity rounds the capacity up to
BitmapVec::MAX_INLINE_LEN, but BitmapVec::new works fine with values
smaller than this and still uses an inline representation. Remove this
behaviour.
This allows specifying a real capacity of 0, which was not previously
possible. This breaks `grow_request` in this case, so change it to grow
to at least `BitmapVec::MAX_INLINE_LEN`, mirroring the capacity floor in
`shrink_request`.
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
rust/kernel/id_pool.rs | 38 ++++++++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/rust/kernel/id_pool.rs b/rust/kernel/id_pool.rs
index 06a4c71c4c6c..a6d69df02805 100644
--- a/rust/kernel/id_pool.rs
+++ b/rust/kernel/id_pool.rs
@@ -112,13 +112,8 @@ pub fn new() -> Self {
}
/// Constructs a new [`IdPool`] with space for a specific number of bits.
- ///
- /// A capacity below [`MAX_INLINE_LEN`] is adjusted to [`MAX_INLINE_LEN`].
- ///
- /// [`MAX_INLINE_LEN`]: BitmapVec::MAX_INLINE_LEN
#[inline]
pub fn with_capacity(num_ids: usize, flags: Flags) -> Result<Self, AllocError> {
- let num_ids = usize::max(num_ids, BitmapVec::MAX_INLINE_LEN);
let map = BitmapVec::new(num_ids, flags)?;
Ok(Self { map })
}
@@ -152,6 +147,13 @@ pub fn capacity(&self) -> usize {
/// let resizer = alloc_request.realloc(GFP_KERNEL)?;
/// pool.shrink(resizer);
/// assert_eq!(pool.capacity(), BitmapVec::MAX_INLINE_LEN);
+ ///
+ /// // A pool at the `MAX_INLINE_LEN` floor cannot shrink further.
+ /// assert!(pool.shrink_request().is_none());
+ ///
+ /// // Neither can a pool with a capacity below `MAX_INLINE_LEN`.
+ /// let small = IdPool::with_capacity(8, GFP_KERNEL)?;
+ /// assert!(small.shrink_request().is_none());
/// # Ok::<(), AllocError>(())
/// ```
#[inline]
@@ -198,12 +200,36 @@ pub fn shrink(&mut self, mut resizer: PoolResizer) {
/// Returns a [`ReallocRequest`] for growing this [`IdPool`], if possible.
///
+ /// Grows to at least [`MAX_INLINE_LEN`].
/// The capacity of an [`IdPool`] cannot be grown above [`MAX_LEN`].
///
+ /// [`MAX_INLINE_LEN`]: BitmapVec::MAX_INLINE_LEN
/// [`MAX_LEN`]: BitmapVec::MAX_LEN
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::{
+ /// alloc::AllocError,
+ /// bitmap::BitmapVec,
+ /// id_pool::IdPool, //
+ /// };
+ ///
+ /// // Grow goes to at least BitmapVec::MAX_INLINE_LEN.
+ /// let mut pool = IdPool::with_capacity(1, GFP_KERNEL)?;
+ /// let resizer = pool.grow_request().ok_or(AllocError)?.realloc(GFP_KERNEL)?;
+ /// pool.grow(resizer);
+ /// assert_eq!(pool.capacity(), BitmapVec::MAX_INLINE_LEN);
+ ///
+ /// // Grow doubles if at least BitmapVec::MAX_INLINE_LEN.
+ /// let resizer = pool.grow_request().ok_or(AllocError)?.realloc(GFP_KERNEL)?;
+ /// pool.grow(resizer);
+ /// assert_eq!(pool.capacity(), 2 * BitmapVec::MAX_INLINE_LEN);
+ /// # Ok::<(), AllocError>(())
+ /// ```
#[inline]
pub fn grow_request(&self) -> Option<ReallocRequest> {
- let num_ids = self.capacity() * 2;
+ let num_ids = usize::max(BitmapVec::MAX_INLINE_LEN, self.capacity() * 2);
if num_ids > BitmapVec::MAX_LEN {
return None;
}
--
2.56.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool
2026-10-19 4:29 [PATCH v10 0/3] rust: Add support for reserving of ranges of IDs Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 1/3] rust: use Alignment size constants Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN Eliot Courtney
@ 2026-10-19 4:29 ` Eliot Courtney
2026-10-19 4:37 ` sashiko-bot
2 siblings, 1 reply; 7+ messages in thread
From: Eliot Courtney @ 2026-10-19 4:29 UTC (permalink / raw)
To: Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, rust-for-linux, linux-kernel, nova-gpu, dri-devel,
Eliot Courtney
Add `ChannelIdPool` which adds automatic tracking and releasing of
channel IDs on top of `IdPool`. This is necessary for apportioning
ranges of channel IDs to be used in e.g. vGPU.
Channel IDs are allocated as a contiguous sequence with a specific
length and sometimes a specific alignment [1] for vGPU. The ID space is
small (limited to 2048) and allocation is not on a hot path, so a
bitmap-backed `IdPool` is a better fit than IDA/xarray (which allocate a
single ID within a range, not a contiguous sequence) or a maple tree
(where aligned allocation needs an alloc_range()+erase() retry loop that
essentially reimplements bitmap_find_next_zero_area()) [2]. It is
also faster than maple tree [3].
Link: https://lore.kernel.org/all/84bc8bd2-e292-4b84-9580-a1b5df4c5bdc@nvidia.com/ # [1]
Link: https://lore.kernel.org/all/20260710-chid-maple-v1-1-4ee869055268@nvidia.com/ # [2]
Link: https://lore.kernel.org/all/20260717053241.916441-1-ynorov@nvidia.com/ # [3]
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 2 +
drivers/gpu/nova-core/gpu/channel.rs | 198 +++++++++++++++++++++++++++++++++++
2 files changed, 200 insertions(+)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 9a91cff01e78..c8ffb427e2d8 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -53,6 +53,8 @@
vgpu::VgpuManager, //
};
+#[cfg_attr(not(CONFIG_KUNIT = "y"), expect(dead_code))]
+mod channel;
mod hal;
mod regs;
diff --git a/drivers/gpu/nova-core/gpu/channel.rs b/drivers/gpu/nova-core/gpu/channel.rs
new file mode 100644
index 000000000000..485efaba059d
--- /dev/null
+++ b/drivers/gpu/nova-core/gpu/channel.rs
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Channel ID allocation.
+
+use core::{
+ num::NonZero,
+ ops::{
+ Deref,
+ Range, //
+ }, //
+};
+
+use kernel::{
+ id_pool::IdPool,
+ prelude::*,
+ ptr::Alignment,
+ sync::{
+ new_mutex,
+ Mutex, //
+ }, //
+};
+
+/// Pool for tracking reservations of channel IDs.
+#[pin_data]
+pub(crate) struct ChannelIdPool {
+ #[pin]
+ inner: Mutex<IdPool>,
+}
+
+impl ChannelIdPool {
+ /// Creates a pool managing `num_chids` channel IDs.
+ pub(crate) fn new(num_chids: NonZero<usize>) -> impl PinInit<Self, Error> {
+ try_pin_init!(Self {
+ inner <- new_mutex!(IdPool::with_capacity(num_chids.get(), GFP_KERNEL)?),
+ })
+ }
+
+ /// Reserves a contiguous area of `count` channel IDs starting at a multiple of `align`,
+ /// returning a guard that releases the area on drop.
+ pub(crate) fn reserve_ids(
+ &self,
+ count: NonZero<usize>,
+ align: Alignment,
+ ) -> Result<ChannelIdReservation<'_>> {
+ let mut ids = self.inner.lock();
+ let range = ids.reserve_ids(0, count, align).ok_or(ENOSPC)?;
+ Ok(ChannelIdReservation { pool: self, range })
+ }
+}
+
+/// A reserved contiguous area of channel IDs.
+///
+/// Releases the whole area back to its [`ChannelIdPool`] when dropped. Releasing locks a
+/// sleeping [`Mutex`], so the area must be dropped in a context that is allowed to sleep.
+#[must_use = "the channel ID reservation is released immediately when unused"]
+pub(crate) struct ChannelIdReservation<'a> {
+ pool: &'a ChannelIdPool,
+ range: Range<usize>,
+}
+
+impl Drop for ChannelIdReservation<'_> {
+ fn drop(&mut self) {
+ self.pool.inner.lock().release_ids(&self.range);
+ }
+}
+
+impl Deref for ChannelIdReservation<'_> {
+ type Target = Range<usize>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.range
+ }
+}
+
+#[kunit_tests(nova_core_channel)]
+mod tests {
+ use super::*;
+ use kernel::sizes::SizeConstants;
+
+ #[test]
+ fn chid_reservation() -> Result {
+ let pool = KBox::pin_init(ChannelIdPool::new(cv!(2048)), GFP_KERNEL)?;
+
+ let first = pool.reserve_ids(cv!(48), Alignment::SZ_1)?;
+ assert_eq!(0, first.start);
+ assert_eq!(48, first.len());
+ assert_eq!(48, first.end);
+
+ let second = pool.reserve_ids(cv!(48), Alignment::SZ_1)?;
+ assert!(first.end <= second.start || second.end <= first.start);
+
+ let first_start = first.start;
+ drop(first);
+ assert_eq!(
+ first_start,
+ pool.reserve_ids(cv!(48), Alignment::SZ_1)?.start
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn chid_reservation_drop() -> Result {
+ let pool = KBox::pin_init(ChannelIdPool::new(cv!(8)), GFP_KERNEL)?;
+
+ let a = pool.reserve_ids(cv!(3), Alignment::SZ_1)?;
+ let b = pool.reserve_ids(cv!(3), Alignment::SZ_1)?;
+ let c = pool.reserve_ids(cv!(2), Alignment::SZ_1)?;
+ assert_eq!(0, a.start);
+ assert_eq!(3, b.start);
+ assert_eq!(6, c.start);
+
+ drop(b);
+
+ // Only have space for 3 IDs right now.
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(4), Alignment::SZ_1).map(|_| ())
+ );
+ let b = pool.reserve_ids(cv!(3), Alignment::SZ_1)?;
+ assert_eq!(3, b.start);
+
+ drop(a);
+ drop(c);
+ drop(b);
+
+ // Everything was dropped so the pool should be empty.
+ assert_eq!(0, pool.reserve_ids(cv!(8), Alignment::SZ_1)?.start);
+ Ok(())
+ }
+
+ #[test]
+ fn chid_bounded_by_num_chids() -> Result {
+ let pool = KBox::pin_init(ChannelIdPool::new(cv!(4)), GFP_KERNEL)?;
+
+ {
+ let a = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ let b = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ let c = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ let d = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ assert_eq!(0, a.start);
+ assert_eq!(1, b.start);
+ assert_eq!(2, c.start);
+ assert_eq!(3, d.start);
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(1), Alignment::SZ_1).map(|_| ())
+ );
+ }
+
+ assert_eq!(0, pool.reserve_ids(cv!(4), Alignment::SZ_1)?.start);
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(5), Alignment::SZ_1).map(|_| ())
+ );
+
+ let head = pool.reserve_ids(cv!(3), Alignment::SZ_1)?;
+ assert_eq!(0, head.start);
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(2), Alignment::SZ_1).map(|_| ())
+ );
+ assert_eq!(3, pool.reserve_ids(cv!(1), Alignment::SZ_1)?.start);
+ Ok(())
+ }
+
+ #[test]
+ fn chid_reservation_aligned() -> Result {
+ let pool = KBox::pin_init(ChannelIdPool::new(cv!(16)), GFP_KERNEL)?;
+
+ // Alloc 0 so the first fit for the next area is unaligned.
+ let pad = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ assert_eq!(0, pad.start);
+
+ let a = pool.reserve_ids(cv!(4), Alignment::SZ_4)?;
+ assert_eq!(4, a.start);
+
+ // The area skipped over by the aligned allocation should still be available.
+ let b = pool.reserve_ids(cv!(1), Alignment::SZ_1)?;
+ assert_eq!(1, b.start);
+
+ let c = pool.reserve_ids(cv!(8), Alignment::SZ_8)?;
+ assert_eq!(8, c.start);
+
+ // Only 2 IDs left.
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(4), Alignment::SZ_4).map(|_| ())
+ );
+ assert_eq!(
+ Err(ENOSPC),
+ pool.reserve_ids(cv!(1), Alignment::SZ_32).map(|_| ())
+ );
+
+ assert_eq!(2, pool.reserve_ids(cv!(2), Alignment::SZ_1)?.start);
+ Ok(())
+ }
+}
--
2.56.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool
2026-10-19 4:29 ` [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool Eliot Courtney
@ 2026-10-19 4:37 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-19 4:37 UTC (permalink / raw)
To: Eliot Courtney, Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
Tamir Duberstein, Alexandre Courbot, Onur Özkan,
David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, nova-gpu, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] gpu: nova-core: call to missing IdPool::reserve_ids() and release_ids()
--
commit 086e60d9f7e7ac9b6628a571ed585382eb5212a9
Author: Eliot Courtney <ecourtney@nvidia.com>
gpu: nova-core: add ChannelIdPool
This commit introduces ChannelIdPool on top of IdPool to automatically
track and release contiguous ranges of channel IDs for nova-core.
Link: https://lore.kernel.org/all/84bc8bd2-e292-4b84-9580-a1b5df4c5bdc@nvidia.com/ # [1]
Link: https://lore.kernel.org/all/20260710-chid-maple-v1-1-4ee869055268@nvidia.com/ # [2]
Link: https://lore.kernel.org/all/20260717053241.916441-1-ynorov@nvidia.com/ # [3]
> diff --git a/drivers/gpu/nova-core/gpu/channel.rs b/drivers/gpu/nova-core/gpu/channel.rs
> new file mode 100644
> index 0000000000000..485efaba059d9
> --- /dev/null
> +++ b/drivers/gpu/nova-core/gpu/channel.rs
> @@ -0,0 +1,198 @@
[ ... ]
> +impl ChannelIdPool {
> + /// Creates a pool managing `num_chids` channel IDs.
> + pub(crate) fn new(num_chids: NonZero<usize>) -> impl PinInit<Self, Error> {
> + try_pin_init!(Self {
> + inner <- new_mutex!(IdPool::with_capacity(num_chids.get(), GFP_KERNEL)?),
> + })
> + }
> +
> + /// Reserves a contiguous area of `count` channel IDs starting at a multiple of `align`,
> + /// returning a guard that releases the area on drop.
> + pub(crate) fn reserve_ids(
> + &self,
> + count: NonZero<usize>,
> + align: Alignment,
> + ) -> Result<ChannelIdReservation<'_>> {
> + let mut ids = self.inner.lock();
> + let range = ids.reserve_ids(0, count, align).ok_or(ENOSPC)?;
> + Ok(ChannelIdReservation { pool: self, range })
> + }
> +}
> +
> +/// A reserved contiguous area of channel IDs.
> +///
> +/// Releases the whole area back to its [`ChannelIdPool`] when dropped. Releasing locks a
> +/// sleeping [`Mutex`], so the area must be dropped in a context that is allowed to sleep.
> +#[must_use = "the channel ID reservation is released immediately when unused"]
> +pub(crate) struct ChannelIdReservation<'a> {
> + pool: &'a ChannelIdPool,
> + range: Range<usize>,
> +}
> +
> +impl Drop for ChannelIdReservation<'_> {
> + fn drop(&mut self) {
> + self.pool.inner.lock().release_ids(&self.range);
> + }
> +}
[Severity: Low]
Does this fail to build under CONFIG_NOVA_CORE due to a missing prerequisite
patch for IdPool?
In drivers/gpu/nova-core/gpu/channel.rs, ChannelIdPool::reserve_ids() calls
ids.reserve_ids(0, count, align), and <ChannelIdReservation as Drop>::drop()
calls release_ids(&self.range).
However, in rust/kernel/id_pool.rs, kernel::id_pool::IdPool only defines
single-ID operations:
pub fn find_unused_id(&mut self, offset: usize) -> Option<usize> {
self.map.next_zero_bit(offset).map(|id| {
self.map.set_bit(id);
id
})
}
pub fn release_id(&mut self, id: usize) {
self.map.clear_bit(id);
}
Neither IdPool::reserve_ids() nor IdPool::release_ids() exists in the tree yet.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019-chid-v10-0-67de9180b4ed@nvidia.com?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN
2026-10-19 4:29 ` [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN Eliot Courtney
@ 2026-10-19 4:37 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-19 4:37 UTC (permalink / raw)
To: Eliot Courtney, Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
Tamir Duberstein, Alexandre Courbot, Onur Özkan,
David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, nova-gpu, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] rust: id_pool: panic in find_unused_id() on small or zero capacity pools
--
commit 018a4fbd0a161c3060c7581d4c4fd80bc70dcd41
Author: Eliot Courtney <ecourtney@nvidia.com>
rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN
This commit stops rounding small capacities up to BitmapVec::MAX_INLINE_LEN
in IdPool::with_capacity() so that capacities smaller than MAX_INLINE_LEN,
including 0, can be used directly. It also updates IdPool::grow_request() to
grow to at least BitmapVec::MAX_INLINE_LEN.
> diff --git a/rust/kernel/id_pool.rs b/rust/kernel/id_pool.rs
> index 384753fe0e44a..7bb8bb89297f0 100644
> --- a/rust/kernel/id_pool.rs
> +++ b/rust/kernel/id_pool.rs
> @@ -106,13 +106,8 @@ pub fn new() -> Self {
> }
>
> /// Constructs a new [`IdPool`] with space for a specific number of bits.
> - ///
> - /// A capacity below [`MAX_INLINE_LEN`] is adjusted to [`MAX_INLINE_LEN`].
> - ///
> - /// [`MAX_INLINE_LEN`]: BitmapVec::MAX_INLINE_LEN
> #[inline]
> pub fn with_capacity(num_ids: usize, flags: Flags) -> Result<Self, AllocError> {
> - let num_ids = usize::max(num_ids, BitmapVec::MAX_INLINE_LEN);
> let map = BitmapVec::new(num_ids, flags)?;
> Ok(Self { map })
> }
[Severity: Medium]
With the capacity floor removed, can calling IdPool::find_unused_id() on a
pool created with capacity 0 (or any capacity <= offset) trigger a panic when
CONFIG_RUST_BITMAP_HARDENED=y is enabled?
In rust/kernel/id_pool.rs, IdPool::find_unused_id() passes offset directly to
Bitmap::next_zero_bit() without checking whether offset >= self.capacity():
pub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>> {
// INVARIANT: `next_zero_bit()` returns None or an integer less than `map.len()`
Some(UnusedId {
id: self.map.next_zero_bit(offset)?,
pool: self,
})
}
In rust/kernel/bitmap.rs, Bitmap::next_zero_bit() asserts that start is
strictly less than self.len():
pub fn next_zero_bit(&self, start: usize) -> Option<usize> {
bitmap_assert!(
start < self.len(),
"`start` must be < {} was {}",
self.len(),
start
);
When a pool is constructed via IdPool::with_capacity(0, flags) and a caller
invokes pool.find_unused_id(0) before growing the pool, self.len() is 0 and
start < self.len() fails, panicking under CONFIG_RUST_BITMAP_HARDENED=y
instead of returning None. The same happens if a caller creates a small pool
(for example with capacity 1) and calls find_unused_id(1).
[ ... ]
>
>
>
>
>
>
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019-chid-v10-0-67de9180b4ed@nvidia.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v10 1/3] rust: use Alignment size constants
2026-10-19 4:29 ` [PATCH v10 1/3] rust: use Alignment size constants Eliot Courtney
@ 2026-10-19 4:41 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-19 4:41 UTC (permalink / raw)
To: Eliot Courtney, Alice Ryhl, Burak Emir, Yury Norov, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
Tamir Duberstein, Alexandre Courbot, Onur Özkan,
David Airlie, Simona Vetter
Cc: Greg Kroah-Hartman, John Hubbard, Alistair Popple, Timur Tabi,
Zhi Wang, nova-gpu, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] rust: missing SizeConstants implementation and sub-1K constants for Alignment
--
commit 2a0eb77a4c0fef593fa5a986d45a2a3fe50ca233
Author: Eliot Courtney <ecourtney@nvidia.com>
rust: use Alignment size constants
This commit replaces Alignment::new::<...>() calls with SizeConstants
associated constants on Alignment across rust/kernel/ and
drivers/gpu/nova-core/.
> diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs
> index 8a934c55169fd..f53886f9ed91e 100644
> --- a/drivers/gpu/nova-core/mm.rs
> +++ b/drivers/gpu/nova-core/mm.rs
> @@ -317,7 +317,7 @@ pub(crate) fn run(
>
> let base = usable_fb_regions.iter().find_map(|region| {
> // Tests rely on this being 8 byte aligned for checking misalignment handling.
> - let base = region.start.align_up(Alignment::new::<8>())?;
> + let base = region.start.align_up(Alignment::SZ_8)?;
> (base.checked_add(SELFTEST_SPAN)? <= region.end).then_some(base)
> });
> let Some(base) = base else {
> diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs
> index 9c214b9f4dd9d..a2d2d170b5014 100644
> --- a/drivers/gpu/nova-core/vbios.rs
> +++ b/drivers/gpu/nova-core/vbios.rs
[ ... ]
> @@ -291,7 +294,7 @@ fn next(&mut self) -> Option<Self::Item> {
>
> // Advance to next image (aligned to 512 bytes).
> self.current_offset += image_size;
> - self.current_offset = self.current_offset.align_up(Alignment::new::<512>())?;
> + self.current_offset = self.current_offset.align_up(Alignment::SZ_512)?;
>
> Some(Ok(full_image))
> }
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index de8ef8e2aec41..5712478a54616 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -19,7 +19,8 @@
> ptr::{
> Alignment,
> KnownSize, //
> - }, //
> + },
> + sizes::SizeConstants, //
> };
>
> #[cfg(CONFIG_HAS_IOMEM)]
> @@ -90,7 +91,7 @@ pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Sel
> impl<const SIZE: usize> KnownSize for Region<SIZE> {
> const MIN_SIZE: usize = SIZE;
> // Alignment of 4 is the most common; different base types can be added once required.
> - const MIN_ALIGN: Alignment = Alignment::new::<4>();
> + const MIN_ALIGN: Alignment = Alignment::SZ_4;
>
> #[inline(always)]
> fn size(p: *const Self) -> usize {
[Severity: Low]
Is this patch missing a prerequisite commit that implements SizeConstants for
Alignment and adds the sub-1K size constants?
Currently in rust/kernel/sizes.rs, define_sizes! is only invoked for integer
types:
define_sizes!(u32, u64, usize);
and define_sizes! only defines constants from SZ_1K through SZ_2G. There is no
SizeConstants implementation for Alignment in rust/kernel/sizes.rs or
rust/kernel/ptr.rs, and sub-1K constants such as SZ_4 (used in
Region::MIN_ALIGN in rust/kernel/io.rs), SZ_8 (used in selftest::run in
drivers/gpu/nova-core/mm.rs under CONFIG_NOVA_CORE_SELFTESTS), and SZ_512 (used
in PciRomImageIterator::next in drivers/gpu/nova-core/vbios.rs) are not defined
in SizeConstants.
Without that prerequisite change, will building the kernel Rust crate,
rust/kernel/gpu/buddy.rs doctests, and drivers/gpu/nova-core/ fail?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019-chid-v10-0-67de9180b4ed@nvidia.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-19 4:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19 4:29 [PATCH v10 0/3] rust: Add support for reserving of ranges of IDs Eliot Courtney
2026-10-19 4:29 ` [PATCH v10 1/3] rust: use Alignment size constants Eliot Courtney
2026-10-19 4:41 ` sashiko-bot
2026-10-19 4:29 ` [PATCH v10 2/3] rust: id_pool: do not round capacity up to BitmapVec::MAX_INLINE_LEN Eliot Courtney
2026-10-19 4:37 ` sashiko-bot
2026-10-19 4:29 ` [PATCH v10 3/3] gpu: nova-core: add ChannelIdPool Eliot Courtney
2026-10-19 4:37 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.