Add the `VramAddress` bitfield-backed type representing a physical address in VRAM. The bitfield layout splits the address into a 12-bit intra-page offset and a 52-bit physical frame number, matching the GPU MMU addressing scheme. also add a few conversion traits required in later patches.
Signed-off-by: Joel Fernandes <[email protected]> --- drivers/gpu/nova-core/mm.rs | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs index 3b131aedf2f9..f8a70f93bc03 100644 --- a/drivers/gpu/nova-core/mm.rs +++ b/drivers/gpu/nova-core/mm.rs @@ -31,11 +31,62 @@ macro_rules! impl_pfn_bounded { }; } +use core::ops::Range; + use kernel::{ + bitfield, num::Bounded, prelude::*, // }; +bitfield! { + /// Physical VRAM address in GPU video memory. + pub(crate) struct VramAddress(u64) { + /// Offset within 4KB page. + 11:0 offset; + /// Physical frame number. + 63:12 frame_number => Pfn; + } +} + +impl VramAddress { + /// Create a new VRAM address from a raw value. + pub(crate) const fn new(addr: u64) -> Self { + Self::from_raw(addr) + } + + /// Get the raw address value as `u64`. + pub(crate) const fn raw(&self) -> u64 { + self.into_raw() + } +} + +// Allow VRAM addresses to be printed with the `{:#x}` format specifier. +impl core::fmt::LowerHex for VramAddress { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::LowerHex::fmt(&self.raw(), f) + } +} + +impl From<Pfn> for VramAddress { + fn from(pfn: Pfn) -> Self { + Self::zeroed().with_frame_number(pfn) + } +} + +/// Extension trait to convert a `Range<u64>` of byte addresses into a +/// `Range<VramAddress>`. +pub(crate) trait IntoVramRange { + /// Convert this range of byte addresses into a `Range<VramAddress>`. + fn into_vram_range(self) -> Range<VramAddress>; +} + +impl IntoVramRange for Range<u64> { + fn into_vram_range(self) -> Range<VramAddress> { + VramAddress::new(self.start)..VramAddress::new(self.end) + } +} + /// Physical Frame Number. /// /// Represents a physical page in VRAM. @@ -55,6 +106,12 @@ pub(crate) const fn raw(self) -> u64 { } } +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) -- 2.34.1
