public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] rust, nova-core: add DeviceSize trait for SZ_* constants
@ 2026-03-12  3:15 John Hubbard
  2026-03-12  3:15 ` [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants John Hubbard
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: John Hubbard @ 2026-03-12  3:15 UTC (permalink / raw)
  To: Danilo Krummrich, Alexandre Courbot
  Cc: Joel Fernandes, Timur Tabi, Alistair Popple, Eliot Courtney,
	Shashank Sharma, Zhi Wang, David Airlie, Simona Vetter,
	Bjorn Helgaas, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, rust-for-linux, LKML, John Hubbard

Changes in v2:
  * Replaced flat SZ_*_U64 constants with a DeviceSize trait that
    provides SZ_* as associated constants on u32 and u64.

  * A define_sizes! macro generates everything from one list of names.

  * Added Alignment::from_u64() so alignment values can be constructed
    from DeviceSize constants without falling back to usize variants.

  * Rebased onto drm-rust-next. No longer depends on the Blackwell
    patchset.

v1 is here:
    https://lore.kernel.org/20260310023145.120037-1-jhubbard@nvidia.com

John Hubbard (3):
  rust: sizes: add DeviceSize trait for device address space constants
  rust: ptr: add Alignment::from_u64() for DeviceSize constants
  gpu: nova-core: use DeviceSize trait for u64 size constants

 drivers/gpu/nova-core/fb.rs     |  31 ++++----
 drivers/gpu/nova-core/gsp/fw.rs |  18 ++---
 drivers/gpu/nova-core/regs.rs   |   6 +-
 rust/kernel/ptr.rs              |  35 +++++++++
 rust/kernel/sizes.rs            | 132 +++++++++++++++++++++-----------
 5 files changed, 147 insertions(+), 75 deletions(-)


base-commit: a544873ce0575b2fd8285a1364d3e09929d9a3ba
-- 
2.53.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants
  2026-03-12  3:15 [PATCH v2 0/3] rust, nova-core: add DeviceSize trait for SZ_* constants John Hubbard
@ 2026-03-12  3:15 ` John Hubbard
  2026-03-24 14:32   ` Alexandre Courbot
  2026-03-12  3:15 ` [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants John Hubbard
  2026-03-12  3:15 ` [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants John Hubbard
  2 siblings, 1 reply; 9+ messages in thread
From: John Hubbard @ 2026-03-12  3:15 UTC (permalink / raw)
  To: Danilo Krummrich, Alexandre Courbot
  Cc: Joel Fernandes, Timur Tabi, Alistair Popple, Eliot Courtney,
	Shashank Sharma, Zhi Wang, David Airlie, Simona Vetter,
	Bjorn Helgaas, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, rust-for-linux, LKML, John Hubbard

The SZ_* constants are usize, matching the CPU pointer width. But
device address spaces have their own widths (32-bit MMIO windows,
64-bit GPU framebuffers, etc.), so drivers end up with repeated
usize-to-u64 or usize-to-u32 conversion calls like
usize_as_u64(SZ_1M). This adds boilerplate with no safety benefit.

Add a DeviceSize trait with associated SZ_* constants, implemented for
u32 and u64. With the trait in scope, callers write u64::SZ_1M or
u32::SZ_4K to get the constant in their device's native width. All
SZ_* values fit in a u32, so both implementations are lossless. The
u32 impl has a const assert to catch any future constant that would
overflow; the u64 cast from usize is inherently lossless.

Replace the hand-written constant list with a define_sizes! macro that
generates the usize constants, the trait, and both trait impls from a
single list of names. Adding a new size or a new target type requires
changing only one place.

The trait also enables future generic APIs that accept T: DeviceSize,
so shared infrastructure can work with whatever address width the
driver declares.

Suggested-by: Danilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/all/DGB9G697GSWO.3VBFGU5MKFPMR@kernel.org/
Link: https://lore.kernel.org/all/DGHI8WRKBQS9.38910L6FIIZTE@kernel.org/
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 rust/kernel/sizes.rs | 132 ++++++++++++++++++++++++++++---------------
 1 file changed, 88 insertions(+), 44 deletions(-)

diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
index 661e680d9330..6b11ec6d97b3 100644
--- a/rust/kernel/sizes.rs
+++ b/rust/kernel/sizes.rs
@@ -3,48 +3,92 @@
 //! Commonly used sizes.
 //!
 //! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
+//!
+//! The top-level `SZ_*` constants are [`usize`]-typed, for use in kernel page
+//! arithmetic and similar CPU-side work.
+//!
+//! The [`DeviceSize`] trait provides the same constants as associated constants
+//! on [`u32`] and [`u64`], for use in device address spaces where the address
+//! width depends on the hardware. Device drivers frequently need these constants
+//! as [`u64`] (or [`u32`]) rather than [`usize`], because device address spaces
+//! are sized independently of the CPU pointer width.
+//!
+//! ```
+//! use kernel::sizes::{DeviceSize, SZ_1M};
+//!
+//! // usize constant (CPU-side)
+//! let pages: usize = SZ_1M / kernel::page::PAGE_SIZE;
+//!
+//! // Device-side constant via the trait
+//! let heap_size: u64 = 14 * u64::SZ_1M;
+//! let small: u32 = u32::SZ_4K;
+//! ```
+
+macro_rules! define_sizes {
+    ($($name:ident),* $(,)?) => {
+        // `usize` constants, from the C `SZ_*` defines in `include/linux/sizes.h`.
+        $(
+            #[doc = concat!("`", stringify!($name), "` as a [`usize`].")]
+            pub const $name: usize = bindings::$name as usize;
+        )*
+
+        /// Size constants for device address spaces.
+        ///
+        /// Implemented for [`u32`] and [`u64`] so drivers can choose the width
+        /// that matches their hardware. All `SZ_*` values fit in a [`u32`], so
+        /// both implementations are lossless.
+        ///
+        /// ```
+        /// use kernel::sizes::DeviceSize;
+        ///
+        /// let gpu_heap: u64 = 14 * u64::SZ_1M;
+        /// let mmio_window: u32 = u32::SZ_16M;
+        /// ```
+        pub trait DeviceSize {
+            $(
+                #[doc = concat!("`", stringify!($name), "` for this type.")]
+                const $name: Self;
+            )*
+        }
+
+        impl DeviceSize for u32 {
+            $(
+                const $name: Self = {
+                    assert!(self::$name <= u32::MAX as usize);
+                    self::$name as u32
+                };
+            )*
+        }
+
+        impl DeviceSize for u64 {
+            $(
+                const $name: Self = self::$name as u64;
+            )*
+        }
+    };
+}
 
-/// 0x00000400
-pub const SZ_1K: usize = bindings::SZ_1K as usize;
-/// 0x00000800
-pub const SZ_2K: usize = bindings::SZ_2K as usize;
-/// 0x00001000
-pub const SZ_4K: usize = bindings::SZ_4K as usize;
-/// 0x00002000
-pub const SZ_8K: usize = bindings::SZ_8K as usize;
-/// 0x00004000
-pub const SZ_16K: usize = bindings::SZ_16K as usize;
-/// 0x00008000
-pub const SZ_32K: usize = bindings::SZ_32K as usize;
-/// 0x00010000
-pub const SZ_64K: usize = bindings::SZ_64K as usize;
-/// 0x00020000
-pub const SZ_128K: usize = bindings::SZ_128K as usize;
-/// 0x00040000
-pub const SZ_256K: usize = bindings::SZ_256K as usize;
-/// 0x00080000
-pub const SZ_512K: usize = bindings::SZ_512K as usize;
-/// 0x00100000
-pub const SZ_1M: usize = bindings::SZ_1M as usize;
-/// 0x00200000
-pub const SZ_2M: usize = bindings::SZ_2M as usize;
-/// 0x00400000
-pub const SZ_4M: usize = bindings::SZ_4M as usize;
-/// 0x00800000
-pub const SZ_8M: usize = bindings::SZ_8M as usize;
-/// 0x01000000
-pub const SZ_16M: usize = bindings::SZ_16M as usize;
-/// 0x02000000
-pub const SZ_32M: usize = bindings::SZ_32M as usize;
-/// 0x04000000
-pub const SZ_64M: usize = bindings::SZ_64M as usize;
-/// 0x08000000
-pub const SZ_128M: usize = bindings::SZ_128M as usize;
-/// 0x10000000
-pub const SZ_256M: usize = bindings::SZ_256M as usize;
-/// 0x20000000
-pub const SZ_512M: usize = bindings::SZ_512M as usize;
-/// 0x40000000
-pub const SZ_1G: usize = bindings::SZ_1G as usize;
-/// 0x80000000
-pub const SZ_2G: usize = bindings::SZ_2G as usize;
+define_sizes! {
+    SZ_1K,   // 0x0000_0400
+    SZ_2K,   // 0x0000_0800
+    SZ_4K,   // 0x0000_1000
+    SZ_8K,   // 0x0000_2000
+    SZ_16K,  // 0x0000_4000
+    SZ_32K,  // 0x0000_8000
+    SZ_64K,  // 0x0001_0000
+    SZ_128K, // 0x0002_0000
+    SZ_256K, // 0x0004_0000
+    SZ_512K, // 0x0008_0000
+    SZ_1M,   // 0x0010_0000
+    SZ_2M,   // 0x0020_0000
+    SZ_4M,   // 0x0040_0000
+    SZ_8M,   // 0x0080_0000
+    SZ_16M,  // 0x0100_0000
+    SZ_32M,  // 0x0200_0000
+    SZ_64M,  // 0x0400_0000
+    SZ_128M, // 0x0800_0000
+    SZ_256M, // 0x1000_0000
+    SZ_512M, // 0x2000_0000
+    SZ_1G,   // 0x4000_0000
+    SZ_2G,   // 0x8000_0000
+}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
  2026-03-12  3:15 [PATCH v2 0/3] rust, nova-core: add DeviceSize trait for SZ_* constants John Hubbard
  2026-03-12  3:15 ` [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants John Hubbard
@ 2026-03-12  3:15 ` John Hubbard
  2026-03-12  6:16   ` Miguel Ojeda
  2026-03-24 14:19   ` Gary Guo
  2026-03-12  3:15 ` [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants John Hubbard
  2 siblings, 2 replies; 9+ messages in thread
From: John Hubbard @ 2026-03-12  3:15 UTC (permalink / raw)
  To: Danilo Krummrich, Alexandre Courbot
  Cc: Joel Fernandes, Timur Tabi, Alistair Popple, Eliot Courtney,
	Shashank Sharma, Zhi Wang, David Airlie, Simona Vetter,
	Bjorn Helgaas, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, rust-for-linux, LKML, John Hubbard

Alignment::new() takes a const usize, which means callers that work
with DeviceSize constants still need to import the usize SZ_*
variants. Add from_u64() so callers can write
Alignment::from_u64(u64::SZ_128K) and stay entirely in the
DeviceSize world.

Both asserts evaluate at compile time in const context, so there is
no runtime cost.

Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 rust/kernel/ptr.rs | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index 5b6a382637fe..b06f6b404a46 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -76,6 +76,41 @@ pub const fn new_checked(align: usize) -> Option<Self> {
         }
     }
 
+    /// Creates an [`Alignment`] from a [`u64`] value.
+    ///
+    /// This is useful when the alignment comes from a [`DeviceSize`] constant
+    /// rather than a [`usize`] literal.
+    ///
+    /// A build error is triggered if `align` is not a power of two, or if it
+    /// exceeds [`usize::MAX`].
+    ///
+    /// [`DeviceSize`]: crate::sizes::DeviceSize
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use kernel::ptr::Alignment;
+    /// use kernel::sizes::DeviceSize;
+    ///
+    /// let v = Alignment::from_u64(u64::SZ_128K);
+    /// assert_eq!(v.as_usize(), 0x0002_0000);
+    /// ```
+    #[inline(always)]
+    pub const fn from_u64(align: u64) -> Self {
+        assert!(
+            align.is_power_of_two(),
+            "Provided alignment is not a power of two."
+        );
+        assert!(
+            align <= usize::MAX as u64,
+            "Provided alignment exceeds usize::MAX."
+        );
+
+        // INVARIANT: `align` is a power of two.
+        // SAFETY: `align` is a power of two, fits in usize, and thus non-zero.
+        Self(unsafe { NonZero::new_unchecked(align as usize) })
+    }
+
     /// Returns the alignment of `T`.
     ///
     /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants
  2026-03-12  3:15 [PATCH v2 0/3] rust, nova-core: add DeviceSize trait for SZ_* constants John Hubbard
  2026-03-12  3:15 ` [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants John Hubbard
  2026-03-12  3:15 ` [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants John Hubbard
@ 2026-03-12  3:15 ` John Hubbard
  2026-03-24 14:06   ` Alexandre Courbot
  2 siblings, 1 reply; 9+ messages in thread
From: John Hubbard @ 2026-03-12  3:15 UTC (permalink / raw)
  To: Danilo Krummrich, Alexandre Courbot
  Cc: Joel Fernandes, Timur Tabi, Alistair Popple, Eliot Courtney,
	Shashank Sharma, Zhi Wang, David Airlie, Simona Vetter,
	Bjorn Helgaas, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, rust-for-linux, LKML, John Hubbard

Replace manual usize-to-u64 conversions of SZ_* constants with the
DeviceSize trait's associated constants on u64. With the DeviceSize
trait in scope, u64::SZ_1M replaces usize_as_u64(SZ_1M) and similar.

Also switch Alignment::new::<SZ_*>() calls to Alignment::from_u64(),
which accepts u64 DeviceSize constants directly.

This removes several now-unused imports: usize_as_u64 and the SZ_*
type-level constants.

Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 drivers/gpu/nova-core/fb.rs     | 31 ++++++++++++++-----------------
 drivers/gpu/nova-core/gsp/fw.rs | 18 +++++++-----------
 drivers/gpu/nova-core/regs.rs   |  6 +++---
 3 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index 6536d0035cb1..aa80fffc4a30 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -13,7 +13,7 @@
         Alignable,
         Alignment, //
     },
-    sizes::*,
+    sizes::DeviceSize,
     sync::aref::ARef, //
 };
 
@@ -23,10 +23,7 @@
     firmware::gsp::GspFirmware,
     gpu::Chipset,
     gsp,
-    num::{
-        usize_as_u64,
-        FromSafeCast, //
-    },
+    num::FromSafeCast,
     regs,
 };
 
@@ -126,8 +123,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if f.alternate() {
             let size = self.len();
 
-            if size < usize_as_u64(SZ_1M) {
-                let size_kib = size / usize_as_u64(SZ_1K);
+            if size < u64::SZ_1M {
+                let size_kib = size / u64::SZ_1K;
                 f.write_fmt(fmt!(
                     "{:#x}..{:#x} ({} KiB)",
                     self.0.start,
@@ -135,7 +132,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     size_kib
                 ))
             } else {
-                let size_mib = size / usize_as_u64(SZ_1M);
+                let size_mib = size / u64::SZ_1M;
                 f.write_fmt(fmt!(
                     "{:#x}..{:#x} ({} MiB)",
                     self.0.start,
@@ -185,14 +182,14 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
 
         let vga_workspace = {
             let vga_base = {
-                const NV_PRAMIN_SIZE: u64 = usize_as_u64(SZ_1M);
+                const NV_PRAMIN_SIZE: u64 = u64::SZ_1M;
                 let base = fb.end - NV_PRAMIN_SIZE;
 
                 if hal.supports_display(bar) {
                     match regs::NV_PDISP_VGA_WORKSPACE_BASE::read(bar).vga_workspace_addr() {
                         Some(addr) => {
                             if addr < base {
-                                const VBIOS_WORKSPACE_SIZE: u64 = usize_as_u64(SZ_128K);
+                                const VBIOS_WORKSPACE_SIZE: u64 = u64::SZ_128K;
 
                                 // Point workspace address to end of framebuffer.
                                 fb.end - VBIOS_WORKSPACE_SIZE
@@ -211,15 +208,15 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
         };
 
         let frts = {
-            const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>();
-            const FRTS_SIZE: u64 = usize_as_u64(SZ_1M);
+            const FRTS_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::SZ_128K);
+            const FRTS_SIZE: u64 = u64::SZ_1M;
             let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - FRTS_SIZE;
 
             FbRange(frts_base..frts_base + FRTS_SIZE)
         };
 
         let boot = {
-            const BOOTLOADER_DOWN_ALIGN: Alignment = Alignment::new::<SZ_4K>();
+            const BOOTLOADER_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::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);
 
@@ -227,7 +224,7 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
         };
 
         let elf = {
-            const ELF_DOWN_ALIGN: Alignment = Alignment::new::<SZ_64K>();
+            const ELF_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::SZ_64K);
             let elf_size = u64::from_safe_cast(gsp_fw.size);
             let elf_addr = (boot.start - elf_size).align_down(ELF_DOWN_ALIGN);
 
@@ -235,7 +232,7 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
         };
 
         let wpr2_heap = {
-            const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::new::<SZ_1M>();
+            const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::SZ_1M);
             let wpr2_heap_size =
                 gsp::LibosParams::from_chipset(chipset).wpr_heap_size(chipset, fb.end);
             let wpr2_heap_addr = (elf.start - wpr2_heap_size).align_down(WPR2_HEAP_DOWN_ALIGN);
@@ -244,7 +241,7 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
         };
 
         let wpr2 = {
-            const WPR2_DOWN_ALIGN: Alignment = Alignment::new::<SZ_1M>();
+            const WPR2_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::SZ_1M);
             let wpr2_addr = (wpr2_heap.start - u64::from_safe_cast(size_of::<gsp::GspFwWprMeta>()))
                 .align_down(WPR2_DOWN_ALIGN);
 
@@ -252,7 +249,7 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
         };
 
         let heap = {
-            const HEAP_SIZE: u64 = usize_as_u64(SZ_1M);
+            const HEAP_SIZE: u64 = u64::SZ_1M;
 
             FbRange(wpr2.start - HEAP_SIZE..wpr2.start)
         };
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index 25fca1f6db2c..454a4a92105a 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -15,10 +15,7 @@
         Alignable,
         Alignment, //
     },
-    sizes::{
-        SZ_128K,
-        SZ_1M, //
-    },
+    sizes::DeviceSize,
     transmute::{
         AsBytes,
         FromBytes, //
@@ -69,7 +66,7 @@ fn client_alloc_size() -> u64 {
     /// Returns the amount of memory to reserve for management purposes for a framebuffer of size
     /// `fb_size`.
     fn management_overhead(fb_size: u64) -> u64 {
-        let fb_size_gb = fb_size.div_ceil(u64::from_safe_cast(kernel::sizes::SZ_1G));
+        let fb_size_gb = fb_size.div_ceil(u64::SZ_1G);
 
         u64::from(bindings::GSP_FW_HEAP_PARAM_SIZE_PER_GB_FB)
             .saturating_mul(fb_size_gb)
@@ -91,9 +88,8 @@ impl LibosParams {
     const LIBOS2: LibosParams = LibosParams {
         carveout_size: num::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS2),
         allowed_heap_size: num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MIN_MB)
-            * num::usize_as_u64(SZ_1M)
-            ..num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB)
-                * num::usize_as_u64(SZ_1M),
+            * u64::SZ_1M
+            ..num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB) * u64::SZ_1M,
     };
 
     /// Version 3 of the GSP LIBOS (GA102+)
@@ -101,9 +97,9 @@ impl LibosParams {
         carveout_size: num::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS3_BAREMETAL),
         allowed_heap_size: num::u32_as_u64(
             bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB,
-        ) * num::usize_as_u64(SZ_1M)
+        ) * u64::SZ_1M
             ..num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB)
-                * num::usize_as_u64(SZ_1M),
+                * u64::SZ_1M,
     };
 
     /// Returns the libos parameters corresponding to `chipset`.
@@ -181,7 +177,7 @@ pub(crate) fn new(gsp_firmware: &GspFirmware, fb_layout: &FbLayout) -> Self {
             gspFwWprEnd: fb_layout
                 .vga_workspace
                 .start
-                .align_down(Alignment::new::<SZ_128K>()),
+                .align_down(Alignment::from_u64(u64::SZ_128K)),
             gspFwHeapVfPartitionCount: fb_layout.vf_partition_count,
             fbSize: fb_layout.fb.end - fb_layout.fb.start,
             vgaWorkspaceOffset: fb_layout.vga_workspace.start,
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 53f412f0ca32..8514b4bd7279 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -9,6 +9,7 @@
 
 use kernel::{
     prelude::*,
+    sizes::DeviceSize,
     time, //
 };
 
@@ -32,7 +33,6 @@
         Architecture,
         Chipset, //
     },
-    num::FromSafeCast,
 };
 
 // PMC
@@ -129,7 +129,7 @@ impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
     /// Returns the usable framebuffer size, in bytes.
     pub(crate) fn usable_fb_size(self) -> u64 {
         let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale()))
-            * u64::from_safe_cast(kernel::sizes::SZ_1M);
+            * u64::SZ_1M;
 
         if self.ecc_mode_enabled() {
             // Remove the amount of memory reserved for ECC (one per 16 units).
@@ -218,7 +218,7 @@ pub(crate) fn completed(self) -> bool {
 impl NV_USABLE_FB_SIZE_IN_MB {
     /// Returns the usable framebuffer size, in bytes.
     pub(crate) fn usable_fb_size(self) -> u64 {
-        u64::from(self.value()) * u64::from_safe_cast(kernel::sizes::SZ_1M)
+        u64::from(self.value()) * u64::SZ_1M
     }
 }
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
  2026-03-12  3:15 ` [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants John Hubbard
@ 2026-03-12  6:16   ` Miguel Ojeda
  2026-03-12  6:23     ` John Hubbard
  2026-03-24 14:19   ` Gary Guo
  1 sibling, 1 reply; 9+ messages in thread
From: Miguel Ojeda @ 2026-03-12  6:16 UTC (permalink / raw)
  To: John Hubbard
  Cc: Danilo Krummrich, Alexandre Courbot, Joel Fernandes, Timur Tabi,
	Alistair Popple, Eliot Courtney, Shashank Sharma, Zhi Wang,
	David Airlie, Simona Vetter, Bjorn Helgaas, Miguel Ojeda,
	Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	rust-for-linux, LKML

On Thu, Mar 12, 2026 at 4:15 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> +    /// A build error is triggered if `align` is not a power of two, or if it
> +    /// exceeds [`usize::MAX`].

I think this wording comes from the `new` constructor, but there we
use a const assert, not a runtime one.

So as you mention in the commit message,  it is true that if you call
it in a const context you will get it at compile-time error, but the
wording here in the docs seems to imply otherwise.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
  2026-03-12  6:16   ` Miguel Ojeda
@ 2026-03-12  6:23     ` John Hubbard
  0 siblings, 0 replies; 9+ messages in thread
From: John Hubbard @ 2026-03-12  6:23 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Danilo Krummrich, Alexandre Courbot, Joel Fernandes, Timur Tabi,
	Alistair Popple, Eliot Courtney, Shashank Sharma, Zhi Wang,
	David Airlie, Simona Vetter, Bjorn Helgaas, Miguel Ojeda,
	Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	rust-for-linux, LKML

On 3/11/26 11:16 PM, Miguel Ojeda wrote:
> On Thu, Mar 12, 2026 at 4:15 AM John Hubbard <jhubbard@nvidia.com> wrote:
>>
>> +    /// A build error is triggered if `align` is not a power of two, or if it
>> +    /// exceeds [`usize::MAX`].
> 
> I think this wording comes from the `new` constructor, but there we

Yes it does--guilty as charged, haha. :)

> use a const assert, not a runtime one.
> 
> So as you mention in the commit message,  it is true that if you call
> it in a const context you will get it at compile-time error, but the
> wording here in the docs seems to imply otherwise.
> 

Good catch, thanks.


thanks,
-- 
John Hubbard


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants
  2026-03-12  3:15 ` [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants John Hubbard
@ 2026-03-24 14:06   ` Alexandre Courbot
  0 siblings, 0 replies; 9+ messages in thread
From: Alexandre Courbot @ 2026-03-24 14:06 UTC (permalink / raw)
  To: John Hubbard
  Cc: Danilo Krummrich, Joel Fernandes, Timur Tabi, Alistair Popple,
	Eliot Courtney, Shashank Sharma, Zhi Wang, David Airlie,
	Simona Vetter, Bjorn Helgaas, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, rust-for-linux, LKML

On Thu Mar 12, 2026 at 12:15 PM JST, John Hubbard wrote:
<snip>
> @@ -211,15 +208,15 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
>          };
>  
>          let frts = {
> -            const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>();
> -            const FRTS_SIZE: u64 = usize_as_u64(SZ_1M);
> +            const FRTS_DOWN_ALIGN: Alignment = Alignment::from_u64(u64::SZ_128K);

Replacing the call to `new` by `from_u64` seems to be unnecessary -
`Alignment` works with `usize`, which `SZ_128K` already is. By using
`from_u64` we convert `SZ_128K` into a `u64` in the `define_sizes`
macro, only to convert it back into a `usize`.

All the uses of `from_u64` follow this pattern, so I'd say we can just
drop patch 2.

> +            const FRTS_SIZE: u64 = u64::SZ_1M;

This, on the other hand, is really useful and much better than using
`usize_as_u64`. Actually I'm wondering whether we should not have
`DeviceSize` implemented for `usize` as well to provide better scope and
consistency (in which case it should just be renamed `Size`?) and sunset
the original definitions.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
  2026-03-12  3:15 ` [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants John Hubbard
  2026-03-12  6:16   ` Miguel Ojeda
@ 2026-03-24 14:19   ` Gary Guo
  1 sibling, 0 replies; 9+ messages in thread
From: Gary Guo @ 2026-03-24 14:19 UTC (permalink / raw)
  To: John Hubbard, Danilo Krummrich, Alexandre Courbot
  Cc: Joel Fernandes, Timur Tabi, Alistair Popple, Eliot Courtney,
	Shashank Sharma, Zhi Wang, David Airlie, Simona Vetter,
	Bjorn Helgaas, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, rust-for-linux, LKML

On Thu Mar 12, 2026 at 3:15 AM GMT, John Hubbard wrote:
> Alignment::new() takes a const usize, which means callers that work
> with DeviceSize constants still need to import the usize SZ_*
> variants. Add from_u64() so callers can write
> Alignment::from_u64(u64::SZ_128K) and stay entirely in the
> DeviceSize world.
>
> Both asserts evaluate at compile time in const context, so there is
> no runtime cost.
>
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>
> ---
>  rust/kernel/ptr.rs | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index 5b6a382637fe..b06f6b404a46 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -76,6 +76,41 @@ pub const fn new_checked(align: usize) -> Option<Self> {
>          }
>      }
>  
> +    /// Creates an [`Alignment`] from a [`u64`] value.
> +    ///
> +    /// This is useful when the alignment comes from a [`DeviceSize`] constant
> +    /// rather than a [`usize`] literal.
> +    ///
> +    /// A build error is triggered if `align` is not a power of two, or if it
> +    /// exceeds [`usize::MAX`].
> +    ///
> +    /// [`DeviceSize`]: crate::sizes::DeviceSize
> +    ///
> +    /// # Examples
> +    ///
> +    /// ```
> +    /// use kernel::ptr::Alignment;
> +    /// use kernel::sizes::DeviceSize;
> +    ///
> +    /// let v = Alignment::from_u64(u64::SZ_128K);
> +    /// assert_eq!(v.as_usize(), 0x0002_0000);
> +    /// ```
> +    #[inline(always)]
> +    pub const fn from_u64(align: u64) -> Self {
> +        assert!(
> +            align.is_power_of_two(),
> +            "Provided alignment is not a power of two."
> +        );

This should be build_assert! to match the doc.

Best,
Gary

> +        assert!(
> +            align <= usize::MAX as u64,
> +            "Provided alignment exceeds usize::MAX."
> +        );
> +
> +        // INVARIANT: `align` is a power of two.
> +        // SAFETY: `align` is a power of two, fits in usize, and thus non-zero.
> +        Self(unsafe { NonZero::new_unchecked(align as usize) })
> +    }
> +
>      /// Returns the alignment of `T`.
>      ///
>      /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants
  2026-03-12  3:15 ` [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants John Hubbard
@ 2026-03-24 14:32   ` Alexandre Courbot
  0 siblings, 0 replies; 9+ messages in thread
From: Alexandre Courbot @ 2026-03-24 14:32 UTC (permalink / raw)
  To: John Hubbard
  Cc: Danilo Krummrich, Joel Fernandes, Timur Tabi, Alistair Popple,
	Eliot Courtney, Shashank Sharma, Zhi Wang, David Airlie,
	Simona Vetter, Bjorn Helgaas, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, rust-for-linux, LKML

General note: `make rustfmt` reformats code from the series.

On Thu Mar 12, 2026 at 12:15 PM JST, John Hubbard wrote:
> The SZ_* constants are usize, matching the CPU pointer width. But
> device address spaces have their own widths (32-bit MMIO windows,
> 64-bit GPU framebuffers, etc.), so drivers end up with repeated
> usize-to-u64 or usize-to-u32 conversion calls like
> usize_as_u64(SZ_1M). This adds boilerplate with no safety benefit.

`usize_as_u64` is Nova-only at the moment, so it might not be
well understood in this context.

>
> Add a DeviceSize trait with associated SZ_* constants, implemented for
> u32 and u64. With the trait in scope, callers write u64::SZ_1M or
> u32::SZ_4K to get the constant in their device's native width. All
> SZ_* values fit in a u32, so both implementations are lossless. The
> u32 impl has a const assert to catch any future constant that would
> overflow; the u64 cast from usize is inherently lossless.
>
> Replace the hand-written constant list with a define_sizes! macro that
> generates the usize constants, the trait, and both trait impls from a
> single list of names. Adding a new size or a new target type requires
> changing only one place.
>
> The trait also enables future generic APIs that accept T: DeviceSize,
> so shared infrastructure can work with whatever address width the
> driver declares.
>
> Suggested-by: Danilo Krummrich <dakr@kernel.org>
> Link: https://lore.kernel.org/all/DGB9G697GSWO.3VBFGU5MKFPMR@kernel.org/
> Link: https://lore.kernel.org/all/DGHI8WRKBQS9.38910L6FIIZTE@kernel.org/
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>
> ---
>  rust/kernel/sizes.rs | 132 ++++++++++++++++++++++++++++---------------
>  1 file changed, 88 insertions(+), 44 deletions(-)
>
> diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
> index 661e680d9330..6b11ec6d97b3 100644
> --- a/rust/kernel/sizes.rs
> +++ b/rust/kernel/sizes.rs
> @@ -3,48 +3,92 @@
>  //! Commonly used sizes.
>  //!
>  //! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
> +//!
> +//! The top-level `SZ_*` constants are [`usize`]-typed, for use in kernel page
> +//! arithmetic and similar CPU-side work.
> +//!
> +//! The [`DeviceSize`] trait provides the same constants as associated constants
> +//! on [`u32`] and [`u64`], for use in device address spaces where the address
> +//! width depends on the hardware. Device drivers frequently need these constants
> +//! as [`u64`] (or [`u32`]) rather than [`usize`], because device address spaces
> +//! are sized independently of the CPU pointer width.
> +//!

There should be a `# Examples` here.

> +//! ```
> +//! use kernel::sizes::{DeviceSize, SZ_1M};
> +//!
> +//! // usize constant (CPU-side)
> +//! let pages: usize = SZ_1M / kernel::page::PAGE_SIZE;

Maybe `num_pages_in_1m` to be more precise.

> +//!
> +//! // Device-side constant via the trait
> +//! let heap_size: u64 = 14 * u64::SZ_1M;
> +//! let small: u32 = u32::SZ_4K;
> +//! ```
> +
> +macro_rules! define_sizes {
> +    ($($name:ident),* $(,)?) => {
> +        // `usize` constants, from the C `SZ_*` defines in `include/linux/sizes.h`.
> +        $(
> +            #[doc = concat!("`", stringify!($name), "` as a [`usize`].")]

All the information in this doccomment (the value and the type) is
already in the declaration below, which appears both in the
rust-analyzer and the HTML doc.

The original doccomments OTOH were useful and they showed the
hexadecimal value, allowing the reader to understand at a peek which bit
was affected. Right now we don't have this information as the value is
displayed in decimal in the documentation. So I think we should just
keep the original doccomments without any extra ornament.

> +            pub const $name: usize = bindings::$name as usize;
> +        )*
> +
> +        /// Size constants for device address spaces.
> +        ///
> +        /// Implemented for [`u32`] and [`u64`] so drivers can choose the width
> +        /// that matches their hardware. All `SZ_*` values fit in a [`u32`], so
> +        /// both implementations are lossless.
> +        ///
> +        /// ```
> +        /// use kernel::sizes::DeviceSize;
> +        ///
> +        /// let gpu_heap: u64 = 14 * u64::SZ_1M;
> +        /// let mmio_window: u32 = u32::SZ_16M;
> +        /// ```
> +        pub trait DeviceSize {
> +            $(
> +                #[doc = concat!("`", stringify!($name), "` for this type.")]
> +                const $name: Self;
> +            )*
> +        }
> +
> +        impl DeviceSize for u32 {
> +            $(
> +                const $name: Self = {
> +                    assert!(self::$name <= u32::MAX as usize);
> +                    self::$name as u32
> +                };
> +            )*
> +        }
> +
> +        impl DeviceSize for u64 {
> +            $(
> +                const $name: Self = self::$name as u64;

I know 64-bit is that largest architecture so far, but in order to
protect for an eventual future where larger sizes exist (and for
consistency), let's have the defensive `assert` here as well.

> +            )*
> +        }
> +    };
> +}
>  
> -/// 0x00000400
> -pub const SZ_1K: usize = bindings::SZ_1K as usize;
> -/// 0x00000800
> -pub const SZ_2K: usize = bindings::SZ_2K as usize;
> -/// 0x00001000
> -pub const SZ_4K: usize = bindings::SZ_4K as usize;
> -/// 0x00002000
> -pub const SZ_8K: usize = bindings::SZ_8K as usize;
> -/// 0x00004000
> -pub const SZ_16K: usize = bindings::SZ_16K as usize;
> -/// 0x00008000
> -pub const SZ_32K: usize = bindings::SZ_32K as usize;
> -/// 0x00010000
> -pub const SZ_64K: usize = bindings::SZ_64K as usize;
> -/// 0x00020000
> -pub const SZ_128K: usize = bindings::SZ_128K as usize;
> -/// 0x00040000
> -pub const SZ_256K: usize = bindings::SZ_256K as usize;
> -/// 0x00080000
> -pub const SZ_512K: usize = bindings::SZ_512K as usize;
> -/// 0x00100000
> -pub const SZ_1M: usize = bindings::SZ_1M as usize;
> -/// 0x00200000
> -pub const SZ_2M: usize = bindings::SZ_2M as usize;
> -/// 0x00400000
> -pub const SZ_4M: usize = bindings::SZ_4M as usize;
> -/// 0x00800000
> -pub const SZ_8M: usize = bindings::SZ_8M as usize;
> -/// 0x01000000
> -pub const SZ_16M: usize = bindings::SZ_16M as usize;
> -/// 0x02000000
> -pub const SZ_32M: usize = bindings::SZ_32M as usize;
> -/// 0x04000000
> -pub const SZ_64M: usize = bindings::SZ_64M as usize;
> -/// 0x08000000
> -pub const SZ_128M: usize = bindings::SZ_128M as usize;
> -/// 0x10000000
> -pub const SZ_256M: usize = bindings::SZ_256M as usize;
> -/// 0x20000000
> -pub const SZ_512M: usize = bindings::SZ_512M as usize;
> -/// 0x40000000
> -pub const SZ_1G: usize = bindings::SZ_1G as usize;
> -/// 0x80000000
> -pub const SZ_2G: usize = bindings::SZ_2G as usize;
> +define_sizes! {
> +    SZ_1K,   // 0x0000_0400
> +    SZ_2K,   // 0x0000_0800
> +    SZ_4K,   // 0x0000_1000
> +    SZ_8K,   // 0x0000_2000
> +    SZ_16K,  // 0x0000_4000
> +    SZ_32K,  // 0x0000_8000
> +    SZ_64K,  // 0x0001_0000
> +    SZ_128K, // 0x0002_0000
> +    SZ_256K, // 0x0004_0000
> +    SZ_512K, // 0x0008_0000
> +    SZ_1M,   // 0x0010_0000
> +    SZ_2M,   // 0x0020_0000
> +    SZ_4M,   // 0x0040_0000
> +    SZ_8M,   // 0x0080_0000
> +    SZ_16M,  // 0x0100_0000
> +    SZ_32M,  // 0x0200_0000
> +    SZ_64M,  // 0x0400_0000
> +    SZ_128M, // 0x0800_0000
> +    SZ_256M, // 0x1000_0000
> +    SZ_512M, // 0x2000_0000
> +    SZ_1G,   // 0x4000_0000
> +    SZ_2G,   // 0x8000_0000
> +}

This macro looks like it has its arguments backwards. `SZ_*` is a fixed
list of values from the C headers that is stable and never changes.
OTOH, the types on which we want to implement `DeviceSize` may vary (as
I suggested in patch 3 to also support `usize`). So I think the macro
invocation should be like:

  define_sizes!(usize, u32, u64);

This would make it easier to integrate the doccomment fix I suggested
above. The only drawback is that generating the module-level usize
consts would need an internal macro rule with the SZ_* list, but that
doesn't add much complexity and makes more sense that way IMHO - you
would just be moving the list from the macro call site to the macro
internals.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-03-24 14:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12  3:15 [PATCH v2 0/3] rust, nova-core: add DeviceSize trait for SZ_* constants John Hubbard
2026-03-12  3:15 ` [PATCH v2 1/3] rust: sizes: add DeviceSize trait for device address space constants John Hubbard
2026-03-24 14:32   ` Alexandre Courbot
2026-03-12  3:15 ` [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants John Hubbard
2026-03-12  6:16   ` Miguel Ojeda
2026-03-12  6:23     ` John Hubbard
2026-03-24 14:19   ` Gary Guo
2026-03-12  3:15 ` [PATCH v2 3/3] gpu: nova-core: use DeviceSize trait for u64 size constants John Hubbard
2026-03-24 14:06   ` Alexandre Courbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox