gpu: nova-core: mm: Add the memory management HAL

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 <ecourtney@nvidia.com>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260827-pramin-split-v3-4-24b24d7afc52@nvidia.com
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
Eliot Courtney 2026-08-27 17:51:45 +09:00 committed by Alexandre Courbot
parent d3bd73dcf5
commit b05ff82081
5 changed files with 164 additions and 0 deletions

View File

@ -19,6 +19,7 @@
},
};
mod hal;
mod regs;
/// Physical VRAM address in GPU video memory.

View File

@ -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)
}

View File

@ -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;

View File

@ -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;

View File

@ -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;