[PATCH 07/12] gpu: nova-core: mm: Add the memory management HAL

Eliot Courtney <[email protected]>
Newsgroups dev.linux.lists.nova-gpu,dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
Positioning the PRAMIN window requires writing an architecture-specific
register: `NV_PBUS_BAR0_WINDOW` on Turing, Ampere and Ada, and
`NV_XAL_EP_BAR0_WINDOW` with a different field width on Hopper and on
Blackwell.

A `MmHal` trait with one implementation per hardware family hides the
register choice from the rest of the mm code, matching the layout of
the driver's other HALs.

Signed-off-by: Eliot Courtney <[email protected]>
---
 drivers/gpu/nova-core/mm.rs           |  1 +
 drivers/gpu/nova-core/mm/hal.rs       | 56 +++++++++++++++++++++++++++++++++++
 drivers/gpu/nova-core/mm/hal/gb100.rs | 35 ++++++++++++++++++++++
 drivers/gpu/nova-core/mm/hal/gh100.rs | 35 ++++++++++++++++++++++
 drivers/gpu/nova-core/mm/hal/tu102.rs | 37 +++++++++++++++++++++++
 5 files changed, 164 insertions(+)

diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs
index 7d24ad790310..07dce4ce2473 100644
--- a/drivers/gpu/nova-core/mm.rs
+++ b/drivers/gpu/nova-core/mm.rs
@@ -19,6 +19,7 @@
     },
 };
 
+mod hal;
 mod regs;
 
 /// Physical VRAM address in GPU video memory.
diff --git a/drivers/gpu/nova-core/mm/hal.rs b/drivers/gpu/nova-core/mm/hal.rs
new file mode 100644
index 000000000000..e7fd1e38bd38
--- /dev/null
+++ b/drivers/gpu/nova-core/mm/hal.rs
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Memory management HAL.
+
+use kernel::{
+    num::Bounded,
+    prelude::*, //
+};
+
+use crate::{
+    driver::Bar0,
+    gpu::{
+        Architecture,
+        Chipset, //
+    },
+    mm::VramAddress, //
+};
+
+mod gb100;
+mod gh100;
+mod tu102;
+
+/// Trait implemented by per-architecture MM HALs.
+///
+/// `Sync` is required so that the `&'static dyn MmHal` references can be stored in `Send`
+/// structures.
+pub(super) trait MmHal: Sync {
+    /// Positions the PRAMIN window at `base`.
+    ///
+    /// This fails if `base` is not aligned to the 64 KiB window alignment or is too large for
+    /// the receiving register.
+    fn write_pramin_window_base(&self, bar: Bar0<'_>, base: VramAddress) -> Result;
+}
+
+/// Returns the HAL corresponding to `chipset`.
+pub(super) fn mm_hal(chipset: Chipset) -> &'static dyn MmHal {
+    match chipset.arch() {
+        Architecture::Turing | Architecture::Ampere | Architecture::Ada => tu102::TU102_HAL,
+        Architecture::Hopper => gh100::GH100_HAL,
+        Architecture::BlackwellGB10x | Architecture::BlackwellGB20x => gb100::GB100_HAL,
+    }
+}
+
+/// Converts `base` into the value of the window-base register field.
+///
+/// Fails with [`EINVAL`] if `base` is not aligned to the window alignment required by the register
+/// field's shift, or if the shifted value does not fit within `RES` bits.
+fn window_base<const RES: u32>(base: VramAddress) -> Result<Bounded<u64, RES>> {
+    const WINDOW_BASE_SHIFT: u32 = 16;
+
+    Bounded::<u64, 64>::from(base.into_raw())
+        .shr_exact::<WINDOW_BASE_SHIFT, { 64 - WINDOW_BASE_SHIFT }>()
+        .and_then(Bounded::try_shrink)
+        .ok_or(EINVAL)
+}
diff --git a/drivers/gpu/nova-core/mm/hal/gb100.rs b/drivers/gpu/nova-core/mm/hal/gb100.rs
new file mode 100644
index 000000000000..3781e143dea7
--- /dev/null
+++ b/drivers/gpu/nova-core/mm/hal/gb100.rs
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Blackwell GB10x/GB20x memory management HAL.
+
+use kernel::{
+    io::Io,
+    prelude::*, //
+};
+
+use crate::{
+    driver::Bar0,
+    mm::{
+        hal::{
+            window_base,
+            MmHal, //
+        },
+        regs,
+        VramAddress, //
+    },
+};
+
+struct Gb100;
+
+impl MmHal for Gb100 {
+    fn write_pramin_window_base(&self, bar: Bar0<'_>, base: VramAddress) -> Result {
+        bar.write_reg(
+            regs::gb100::NV_XAL_EP_BAR0_WINDOW::zeroed().with_base(window_base(base)?.cast()),
+        );
+        Ok(())
+    }
+}
+
+const GB100: Gb100 = Gb100;
+pub(super) const GB100_HAL: &dyn MmHal = &GB100;
diff --git a/drivers/gpu/nova-core/mm/hal/gh100.rs b/drivers/gpu/nova-core/mm/hal/gh100.rs
new file mode 100644
index 000000000000..8af384db2921
--- /dev/null
+++ b/drivers/gpu/nova-core/mm/hal/gh100.rs
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Hopper memory management HAL.
+
+use kernel::{
+    io::Io,
+    prelude::*, //
+};
+
+use crate::{
+    driver::Bar0,
+    mm::{
+        hal::{
+            window_base,
+            MmHal, //
+        },
+        regs,
+        VramAddress, //
+    },
+};
+
+struct Gh100;
+
+impl MmHal for Gh100 {
+    fn write_pramin_window_base(&self, bar: Bar0<'_>, base: VramAddress) -> Result {
+        bar.write_reg(
+            regs::gh100::NV_XAL_EP_BAR0_WINDOW::zeroed().with_base(window_base(base)?.cast()),
+        );
+        Ok(())
+    }
+}
+
+const GH100: Gh100 = Gh100;
+pub(super) const GH100_HAL: &dyn MmHal = &GH100;
diff --git a/drivers/gpu/nova-core/mm/hal/tu102.rs b/drivers/gpu/nova-core/mm/hal/tu102.rs
new file mode 100644
index 000000000000..e4fe7561223c
--- /dev/null
+++ b/drivers/gpu/nova-core/mm/hal/tu102.rs
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Turing, Ampere and Ada memory management HAL.
+
+use kernel::{
+    io::Io,
+    prelude::*, //
+};
+
+use crate::{
+    driver::Bar0,
+    mm::{
+        hal::{
+            window_base,
+            MmHal, //
+        },
+        regs,
+        VramAddress, //
+    },
+};
+
+struct Tu102;
+
+impl MmHal for Tu102 {
+    fn write_pramin_window_base(&self, bar: Bar0<'_>, base: VramAddress) -> Result {
+        bar.write_reg(
+            regs::NV_PBUS_BAR0_WINDOW::zeroed()
+                .with_target(regs::Bar0WindowTarget::VidMem)
+                .with_base(window_base(base)?.cast()),
+        );
+        Ok(())
+    }
+}
+
+const TU102: Tu102 = Tu102;
+pub(super) const TU102_HAL: &dyn MmHal = &TU102;

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.