Add foundational types for GPU memory management. These types are used throughout the nova memory management subsystem for page table operations, address translation, and memory allocation.
Signed-off-by: Joel Fernandes <[email protected]> --- drivers/gpu/nova-core/mm/mod.rs | 147 ++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/gpu/nova-core/mm/mod.rs b/drivers/gpu/nova-core/mm/mod.rs index 7a5dd4220c67..b57016d453ce 100644 --- a/drivers/gpu/nova-core/mm/mod.rs +++ b/drivers/gpu/nova-core/mm/mod.rs @@ -2,4 +2,151 @@ //! Memory management subsystems for nova-core. +#![expect(dead_code)] + pub(crate) mod pramin; + +use kernel::sizes::SZ_4K; + +/// Page size in bytes (4 KiB). +pub(crate) const PAGE_SIZE: usize = SZ_4K; + +bitfield! { + pub(crate) struct VramAddress(u64), "Physical VRAM address in GPU video memory" { + 11:0 offset as u64, "Offset within 4KB page"; + 63:12 frame_number as u64 => Pfn, "Physical frame number"; + } +} + +impl VramAddress { + /// Create a new VRAM address from a raw value. + pub(crate) const fn new(addr: u64) -> Self { + Self(addr) + } + + /// Get the raw address value as `usize` (useful for MMIO offsets). + pub(crate) const fn raw(&self) -> usize { + self.0 as usize + } + + /// Get the raw address value as `u64`. + pub(crate) const fn raw_u64(&self) -> u64 { + self.0 + } +} + +impl From<Pfn> for VramAddress { + fn from(pfn: Pfn) -> Self { + Self::default().set_frame_number(pfn) + } +} + +bitfield! { + pub(crate) struct VirtualAddress(u64), "Virtual address in GPU address space" { + 11:0 offset as u64, "Offset within 4KB page"; + 20:12 l4_index as u64, "Level 4 index (PTE)"; + 29:21 l3_index as u64, "Level 3 index (Dual PDE)"; + 38:30 l2_index as u64, "Level 2 index"; + 47:39 l1_index as u64, "Level 1 index"; + 56:48 l0_index as u64, "Level 0 index (PDB)"; + 63:12 frame_number as u64 => Vfn, "Virtual frame number"; + } +} + +impl VirtualAddress { + /// Create a new virtual address from a raw value. + #[expect(dead_code)] + pub(crate) const fn new(addr: u64) -> Self { + Self(addr) + } + + /// Get the page table index for a given level. + pub(crate) fn level_index(&self, level: u64) -> u64 { + match level { + 0 => self.l0_index(), + 1 => self.l1_index(), + 2 => self.l2_index(), + 3 => self.l3_index(), + 4 => self.l4_index(), + _ => 0, + } + } +} + +impl From<Vfn> for VirtualAddress { + fn from(vfn: Vfn) -> Self { + Self::default().set_frame_number(vfn) + } +} + +/// Physical Frame Number. +/// +/// Represents a physical page in VRAM. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub(crate) struct Pfn(u64); + +impl Pfn { + /// Create a new PFN from a frame number. + pub(crate) const fn new(frame_number: u64) -> Self { + Self(frame_number) + } + + /// Get the raw frame number. + pub(crate) const fn raw(self) -> u64 { + self.0 + } +} + +impl From<VramAddress> for Pfn { + fn from(addr: VramAddress) -> Self { + addr.frame_number() + } +} + +impl From<u64> for Pfn { + fn from(val: u64) -> Self { + Self(val) + } +} + +impl From<Pfn> for u64 { + fn from(pfn: Pfn) -> Self { + pfn.0 + } +} + +/// Virtual Frame Number. +/// +/// Represents a virtual page in GPU address space. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub(crate) struct Vfn(u64); + +impl Vfn { + /// Create a new VFN from a frame number. + pub(crate) const fn new(frame_number: u64) -> Self { + Self(frame_number) + } + + /// Get the raw frame number. + pub(crate) const fn raw(self) -> u64 { + self.0 + } +} + +impl From<VirtualAddress> for Vfn { + fn from(addr: VirtualAddress) -> Self { + addr.frame_number() + } +} + +impl From<u64> for Vfn { + fn from(val: u64) -> Self { + Self(val) + } +} + +impl From<Vfn> for u64 { + fn from(vfn: Vfn) -> Self { + vfn.0 + } +} -- 2.34.1
