Add common page table types shared between MMU v2 and v3. These types are hardware-agnostic and used by both MMU versions.
Signed-off-by: Joel Fernandes <[email protected]> --- drivers/gpu/nova-core/mm/mod.rs | 1 + drivers/gpu/nova-core/mm/pagetable/mod.rs | 168 ++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 drivers/gpu/nova-core/mm/pagetable/mod.rs diff --git a/drivers/gpu/nova-core/mm/mod.rs b/drivers/gpu/nova-core/mm/mod.rs index b57016d453ce..6015fc8753bc 100644 --- a/drivers/gpu/nova-core/mm/mod.rs +++ b/drivers/gpu/nova-core/mm/mod.rs @@ -4,6 +4,7 @@ #![expect(dead_code)] +pub(crate) mod pagetable; pub(crate) mod pramin; use kernel::sizes::SZ_4K; diff --git a/drivers/gpu/nova-core/mm/pagetable/mod.rs b/drivers/gpu/nova-core/mm/pagetable/mod.rs new file mode 100644 index 000000000000..bb3a37cc6ca0 --- /dev/null +++ b/drivers/gpu/nova-core/mm/pagetable/mod.rs @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Common page table types shared between MMU v2 and v3. +//! +//! This module provides foundational types used by both MMU versions: +//! - Page table level hierarchy +//! - Memory aperture types for PDEs and PTEs + +#![expect(dead_code)] + +use crate::gpu::Architecture; + +/// MMU version enumeration. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum MmuVersion { + /// MMU v2 for Turing/Ampere/Ada. + V2, + /// MMU v3 for Hopper and later. + V3, +} + +impl From<Architecture> for MmuVersion { + fn from(arch: Architecture) -> Self { + match arch { + Architecture::Turing | Architecture::Ampere | Architecture::Ada => Self::V2, + // In the future, uncomment: + // _ => Self::V3, + } + } +} + +/// Page Table Level hierarchy for MMU v2/v3. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum PageTableLevel { + /// Level 0 - Page Directory Base (root). + Pdb, + /// Level 1 - Intermediate page directory. + L1, + /// Level 2 - Intermediate page directory. + L2, + /// Level 3 - Dual PDE level (Big and Small Page Tables, 128-bit entries). + L3, + /// Level 4 - Page Table Entries, pointing directly to physical pages. + L4, +} + +impl PageTableLevel { + /// Get the entry size in bytes for this level. + pub(crate) const fn entry_size(&self) -> usize { + match self { + Self::L3 => 16, // 128-bit dual PDE + _ => 8, // 64-bit PDE/PTE + } + } + + /// Number of entries per page table (512 for 4KB pages). + pub(crate) const ENTRIES_PER_TABLE: usize = 512; + + /// Get the next level in the hierarchy. + pub(crate) const fn next(&self) -> Option<PageTableLevel> { + match self { + Self::Pdb => Some(Self::L1), + Self::L1 => Some(Self::L2), + Self::L2 => Some(Self::L3), + Self::L3 => Some(Self::L4), + Self::L4 => None, + } + } + + /// Check if this is the PTE level. + pub(crate) const fn is_pte_level(&self) -> bool { + matches!(self, Self::L4) + } + + /// Check if this level uses dual PDE (128-bit entries). + pub(crate) const fn is_dual_pde_level(&self) -> bool { + matches!(self, Self::L3) + } + + /// Get all PDE levels (excluding PTE level) for walking. + pub(crate) const fn pde_levels() -> [PageTableLevel; 4] { + [Self::Pdb, Self::L1, Self::L2, Self::L3] + } + + /// Get the level as a numeric index (0-4). + pub(crate) const fn as_index(&self) -> u64 { + match self { + Self::Pdb => 0, + Self::L1 => 1, + Self::L2 => 2, + Self::L3 => 3, + Self::L4 => 4, + } + } +} + +/// Memory aperture for Page Table Entries (`PTE`s). +/// +/// Determines which memory region the `PTE` points to. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub(crate) enum AperturePte { + /// Local video memory (VRAM). + #[default] + VideoMemory = 0, + /// Peer GPU's video memory. + PeerMemory = 1, + /// System memory with cache coherence. + SystemCoherent = 2, + /// System memory without cache coherence. + SystemNonCoherent = 3, +} + +// TODO[FPRI]: Replace with `#[derive(FromPrimitive)]` when available. +impl From<u8> for AperturePte { + fn from(val: u8) -> Self { + match val { + 0 => Self::VideoMemory, + 1 => Self::PeerMemory, + 2 => Self::SystemCoherent, + 3 => Self::SystemNonCoherent, + _ => Self::VideoMemory, + } + } +} + +// TODO[FPRI]: Replace with `#[derive(ToPrimitive)]` when available. +impl From<AperturePte> for u8 { + fn from(val: AperturePte) -> Self { + val as u8 + } +} + +/// Memory aperture for Page Directory Entries (`PDE`s). +/// +/// Note: For `PDE`s, `Invalid` (0) means the entry is not valid. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub(crate) enum AperturePde { + /// Invalid/unused entry. + #[default] + Invalid = 0, + /// Page table is in video memory. + VideoMemory = 1, + /// Page table is in system memory with coherence. + SystemCoherent = 2, + /// Page table is in system memory without coherence. + SystemNonCoherent = 3, +} + +// TODO[FPRI]: Replace with `#[derive(FromPrimitive)]` when available. +impl From<u8> for AperturePde { + fn from(val: u8) -> Self { + match val { + 1 => Self::VideoMemory, + 2 => Self::SystemCoherent, + 3 => Self::SystemNonCoherent, + _ => Self::Invalid, + } + } +} + +// TODO[FPRI]: Replace with `#[derive(ToPrimitive)]` when available. +impl From<AperturePde> for u8 { + fn from(val: AperturePde) -> Self { + val as u8 + } +} -- 2.34.1
