1 // SPDX-License-Identifier: GPL-2.0 2 // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 //! Memory management subsystems. 5 6 #![cfg_attr(not(CONFIG_NOVA_CORE_SELFTESTS), expect(dead_code))] 7 8 use core::{ 9 fmt::LowerHex, 10 ops, // 11 }; 12 13 use kernel::{ 14 fmt, 15 prelude::*, 16 ptr::{ 17 Alignable, 18 Alignment, // 19 }, 20 }; 21 22 use crate::{ 23 driver::Bar0, 24 gpu::Chipset, // 25 }; 26 27 mod hal; 28 mod pramin; 29 mod regs; 30 31 /// GPU Memory Manager - owns all core MM components. 32 /// 33 /// Provides centralized ownership of memory management resources: 34 /// - [`pramin::Pramin`] for direct VRAM access. 35 pub(crate) struct GpuMm<'gpu> { 36 pramin: pramin::Pramin<'gpu>, 37 } 38 39 impl<'gpu> GpuMm<'gpu> { 40 /// Creates the GPU memory manager. 41 pub(crate) fn new( 42 bar: Bar0<'gpu>, 43 chipset: Chipset, 44 total_fb_end: VramAddress, 45 ) -> Result<Self> { 46 // PRAMIN covers all physical VRAM (including GSP-reserved areas 47 // above the usable region, e.g. the BAR1 page directory). 48 let vram_region = VramAddress::ZERO..total_fb_end; 49 50 Ok(Self { 51 pramin: pramin::Pramin::new(bar, chipset, vram_region)?, 52 }) 53 } 54 55 /// Access the [`pramin::Pramin`]. 56 fn pramin_mut(&mut self) -> &mut pramin::Pramin<'gpu> { 57 &mut self.pramin 58 } 59 } 60 61 /// Physical VRAM address in GPU video memory. 62 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 63 #[repr(transparent)] 64 pub(crate) struct VramAddress(u64); 65 66 impl VramAddress { 67 /// The zero address. 68 pub(crate) const ZERO: Self = Self::from_raw(0); 69 70 /// Creates an address from a raw value. 71 pub(crate) const fn from_raw(addr: u64) -> Self { 72 Self(addr) 73 } 74 75 /// Returns the address as a raw value. 76 pub(crate) const fn into_raw(self) -> u64 { 77 self.0 78 } 79 80 /// Adds `rhs` to this address, returning [`None`] on overflow. 81 pub(crate) const fn checked_add(self, rhs: u64) -> Option<Self> { 82 match self.into_raw().checked_add(rhs) { 83 Some(addr) => Some(Self::from_raw(addr)), 84 None => None, 85 } 86 } 87 } 88 89 impl Alignable for VramAddress { 90 fn align_down(self, alignment: Alignment) -> Self { 91 Self::from_raw(self.into_raw().align_down(alignment)) 92 } 93 94 fn align_up(self, alignment: Alignment) -> Option<Self> { 95 self.into_raw().align_up(alignment).map(Self::from_raw) 96 } 97 } 98 99 impl LowerHex for VramAddress { 100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 101 LowerHex::fmt(&self.into_raw(), f) 102 } 103 } 104 105 impl fmt::Debug for VramAddress { 106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 107 f.write_fmt(fmt!("{:#x}", self)) 108 } 109 } 110 111 impl ops::Add<u64> for VramAddress { 112 type Output = Self; 113 114 fn add(self, rhs: u64) -> Self::Output { 115 Self::from_raw(self.into_raw() + rhs) 116 } 117 } 118 119 impl ops::Sub for VramAddress { 120 type Output = u64; 121 122 fn sub(self, rhs: Self) -> Self::Output { 123 self.into_raw() - rhs.into_raw() 124 } 125 } 126 127 #[cfg(CONFIG_NOVA_CORE_SELFTESTS)] 128 pub(crate) mod selftest { 129 use core::ops::Range; 130 131 use kernel::{ 132 device, 133 sizes::SizeConstants, // 134 }; 135 136 use super::*; 137 138 /// Run MM subsystem self-tests during probe. 139 pub(crate) fn run( 140 dev: &device::Device<device::Bound>, 141 mm: &mut GpuMm<'_>, 142 usable_fb_regions: &[Range<u64>], 143 ) -> Result { 144 // VRAM span the self-tests are free to overwrite, from the chosen test base. 145 const SELFTEST_SPAN: u64 = u64::SZ_64M; 146 147 let base = usable_fb_regions.iter().find_map(|region| { 148 // Tests rely on this being 8 byte aligned for checking misalignment handling. 149 let base = region.start.align_up(Alignment::new::<8>())?; 150 (base.checked_add(SELFTEST_SPAN)? <= region.end).then_some(base) 151 }); 152 let Some(base) = base else { 153 dev_warn!( 154 dev, 155 "PRAMIN: skipping self-tests, no usable VRAM region of {:#x} bytes\n", 156 SELFTEST_SPAN 157 ); 158 return Ok(()); 159 }; 160 161 pramin::selftest::run(dev, mm.pramin_mut(), VramAddress::from_raw(base)) 162 } 163 } 164