From: Joel Fernandes <[email protected]> Add common virtual memory memory management types: `PAGE_SIZE` constant, `VirtualAddress` bitfield type, `Vfn` (Virtual Frame Number) type, `Pfn` (Physical Frame Number) type.
Signed-off-by: Joel Fernandes <[email protected]> [ecourtney: restore Pfn and its VramAddress conversions on the raw API] [ecourtney: make dead_code expect unconditional until the self-tests patch] Signed-off-by: Eliot Courtney <[email protected]> --- drivers/gpu/nova-core/mm.rs | 142 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs index 9e4338c7c393..4234ba4d596a 100644 --- a/drivers/gpu/nova-core/mm.rs +++ b/drivers/gpu/nova-core/mm.rs @@ -3,7 +3,34 @@ //! Memory management subsystems. -#![cfg_attr(not(CONFIG_NOVA_CORE_SELFTESTS), expect(dead_code))] +#![expect(dead_code)] + +/// Implements `From` conversions between a frame-number type and `Bounded<u64, N>`. +/// +/// Each MMU version module should invoke this for the specific bit widths used by that version's +/// PTE/PDE bitfield definitions. +macro_rules! impl_frame_number_bounded { + ($type:ty, $bits:literal) => { + impl From<Bounded<u64, $bits>> for $type { + fn from(val: Bounded<u64, $bits>) -> Self { + Self::new(val.get()) + } + } + + impl From<$type> for Bounded<u64, $bits> { + fn from(v: $type) -> Self { + Bounded::from_expr(v.raw() & ::kernel::bits::genmask_u64(0..=($bits - 1))) + } + } + }; +} + +/// Implements `From` conversions between [`Pfn`] and `Bounded<u64, N>` for bitfield interop. +macro_rules! impl_pfn_bounded { + ($bits:literal) => { + impl_frame_number_bounded!(Pfn, $bits); + }; +} use core::{ fmt::LowerHex, @@ -11,12 +38,15 @@ }; use kernel::{ + bitfield, fmt, + num::Bounded, prelude::*, ptr::{ Alignable, Alignment, // }, + sizes::SZ_4K, // }; use crate::{ @@ -58,6 +88,9 @@ fn pramin_mut(&mut self) -> &mut pramin::Pramin<'gpu> { } } +/// Page size in bytes (4 KiB). +pub(crate) const PAGE_SIZE: usize = SZ_4K; + /// Physical VRAM address in GPU video memory. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] @@ -124,6 +157,113 @@ fn sub(self, rhs: Self) -> Self::Output { } } +impl From<Pfn> for VramAddress { + fn from(pfn: Pfn) -> Self { + Self::from_raw(pfn.raw() << 12) + } +} + +bitfield! { + /// Virtual address in GPU address space. + pub(crate) struct VirtualAddress(u64) { + /// Offset within 4KB page. + 11:0 offset; + /// Virtual frame number. + 63:12 frame_number => Vfn; + } +} + +impl VirtualAddress { + /// Create a new virtual address from a raw value. + pub(crate) const fn new(addr: u64) -> Self { + Self::from_raw(addr) + } +} + +impl From<Vfn> for VirtualAddress { + fn from(vfn: Vfn) -> Self { + Self::zeroed().with_frame_number(vfn) + } +} + +/// Physical Frame Number. +/// +/// Represents a physical page in VRAM. +#[repr(transparent)] +#[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 { + Self::new(addr.into_raw() >> 12) + } +} + +impl From<u64> for Pfn { + fn from(val: u64) -> Self { + Self(val) + } +} + +impl From<Pfn> for u64 { + fn from(pfn: Pfn) -> Self { + pfn.0 + } +} + +impl_pfn_bounded!(52); + +/// Virtual Frame Number. +/// +/// Represents a virtual page in GPU address space. +#[repr(transparent)] +#[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 + } +} + +impl_frame_number_bounded!(Vfn, 52); + #[cfg(CONFIG_NOVA_CORE_SELFTESTS)] pub(crate) mod selftest { use core::ops::Range; -- 2.55.0
