Introduce GpuMm as the centralized GPU memory manager that owns: - Buddy allocator for VRAM allocation. - PRAMIN window for direct VRAM access. - TLB manager for translation buffer operations.
This provides clean ownership model where GpuMm provides accessor methods for its components that can be used for memory management operations. Cc: Nikola Djukic <[email protected]> Signed-off-by: Joel Fernandes <[email protected]> --- drivers/gpu/nova-core/gpu.rs | 32 +++++++++++- drivers/gpu/nova-core/gsp/commands.rs | 2 - drivers/gpu/nova-core/mm.rs | 70 ++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index c324d96bd0c6..32266480bb0f 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -4,8 +4,10 @@ device, devres::Devres, fmt, + gpu::buddy::GpuBuddyParams, pci, prelude::*, + sizes::SZ_4K, sync::Arc, // }; @@ -22,6 +24,7 @@ commands::GetGspStaticInfoReply, Gsp, // }, + mm::GpuMm, regs, }; @@ -252,6 +255,9 @@ pub(crate) struct Gpu { gsp_falcon: Falcon<GspFalcon>, /// SEC2 falcon instance, used for GSP boot up and cleanup. sec2_falcon: Falcon<Sec2Falcon>, + /// GPU memory manager owning memory management resources. + #[pin] + mm: GpuMm, /// GSP runtime data. Temporarily an empty placeholder. #[pin] gsp: Gsp, @@ -288,7 +294,31 @@ pub(crate) fn new<'a>( gsp <- Gsp::new(pdev), - gsp_static_info: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)? }, + gsp_static_info: { + let info = gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)?; + + dev_info!( + pdev.as_ref(), + "Using FB region: {:#x}..{:#x}\n", + info.usable_fb_region.start, + info.usable_fb_region.end + ); + + info + }, + + // Create GPU memory manager owning memory management resources. + mm <- { + let usable_vram = &gsp_static_info.usable_fb_region; + // PRAMIN covers all physical VRAM (including GSP-reserved areas + // above the usable region, e.g. the BAR1 page directory). + let pramin_vram_region = 0..gsp_static_info.total_fb_end; + GpuMm::new(devres_bar.clone(), GpuBuddyParams { + base_offset: usable_vram.start, + physical_memory_size: usable_vram.end - usable_vram.start, + chunk_size: SZ_4K, + }, pramin_vram_region)? + }, bar: devres_bar, }) diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs index 389d215098c6..18dd86a38d46 100644 --- a/drivers/gpu/nova-core/gsp/commands.rs +++ b/drivers/gpu/nova-core/gsp/commands.rs @@ -191,10 +191,8 @@ fn init(&self) -> impl Init<Self::Command, Self::InitError> { pub(crate) struct GetGspStaticInfoReply { gpu_name: [u8; 64], /// Usable FB (VRAM) region for driver memory allocation. - #[expect(dead_code)] pub(crate) usable_fb_region: Range<u64>, /// End of VRAM. - #[expect(dead_code)] pub(crate) total_fb_end: u64, } diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs index b02dc265a2c8..dd15175c841d 100644 --- a/drivers/gpu/nova-core/mm.rs +++ b/drivers/gpu/nova-core/mm.rs @@ -7,9 +7,75 @@ pub(crate) mod pramin; pub(crate) mod tlb; -use kernel::sizes::SZ_4K; +use kernel::{ + devres::Devres, + gpu::buddy::{ + GpuBuddy, + GpuBuddyParams, // + }, + prelude::*, + sizes::SZ_4K, + sync::Arc, // +}; -use crate::num::u64_as_usize; +use crate::{ + driver::Bar0, + num::u64_as_usize, // +}; + +pub(crate) use tlb::Tlb; + +/// GPU Memory Manager - owns all core MM components. +/// +/// Provides centralized ownership of memory management resources: +/// - [`GpuBuddy`] allocator for VRAM page table allocation. +/// - [`pramin::Pramin`] for direct VRAM access. +/// - [`Tlb`] manager for translation buffer flush operations. +#[pin_data] +pub(crate) struct GpuMm { + buddy: GpuBuddy, + #[pin] + pramin: pramin::Pramin, + #[pin] + tlb: Tlb, +} + +impl GpuMm { + /// Create a pin-initializer for `GpuMm`. + /// + /// `pramin_vram_region` is the full physical VRAM range (including GSP-reserved + /// areas). PRAMIN window accesses are validated against this range. + pub(crate) fn new( + bar: Arc<Devres<Bar0>>, + buddy_params: GpuBuddyParams, + pramin_vram_region: core::ops::Range<u64>, + ) -> Result<impl PinInit<Self>> { + let buddy = GpuBuddy::new(buddy_params)?; + let tlb_init = Tlb::new(bar.clone()); + let pramin_init = pramin::Pramin::new(bar, pramin_vram_region)?; + + Ok(pin_init!(Self { + buddy, + pramin <- pramin_init, + tlb <- tlb_init, + })) + } + + /// Access the [`GpuBuddy`] allocator. + pub(crate) fn buddy(&self) -> &GpuBuddy { + &self.buddy + } + + /// Access the [`pramin::Pramin`]. + pub(crate) fn pramin(&self) -> &pramin::Pramin { + &self.pramin + } + + /// Access the [`Tlb`] manager. + pub(crate) fn tlb(&self) -> &Tlb { + &self.tlb + } +} /// Page size in bytes (4 KiB). pub(crate) const PAGE_SIZE: usize = SZ_4K; -- 2.34.1
