mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Eliot Courtney <ecourtney@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
	 Alexandre Courbot <acourbot@nvidia.com>
Cc: Alice Ryhl <aliceryhl@google.com>,
	John Hubbard <jhubbard@nvidia.com>,
	 Alistair Popple <apopple@nvidia.com>,
	Timur Tabi <ttabi@nvidia.com>,
	 nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org,
	 linux-kernel@vger.kernel.org,
	Eliot Courtney <ecourtney@nvidia.com>,
	 Joel Fernandes <joelagnelf@nvidia.com>
Subject: [PATCH 02/16] gpu: nova-core: mm: Add buddy allocator and TLB to GpuMm
Date: Wed, 09 Sep 2026 12:59:40 +0900	[thread overview]
Message-ID: <20260909-mmrebase-v1-2-8dd5d4225d2e@nvidia.com> (raw)
In-Reply-To: <20260909-mmrebase-v1-0-8dd5d4225d2e@nvidia.com>

From: Joel Fernandes <joelagnelf@nvidia.com>

Extend GpuMm with the remaining two memory-management components:

- Buddy allocator for VRAM allocation.
- TLB manager for translation buffer operations.

PRAMIN was added in an earlier commit; this completes the centralized
ownership model with accessor methods for each component.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
[ecourtney: rebase GpuMm for borrowed BAR0, pin Tlb, write regs directly]
[ecourtney: size the buddy from the first usable FB region, drop dev_info]
[ecourtney: update for the VramAddress raw API and typed register base]
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
 drivers/gpu/nova-core/Kconfig   |   1 +
 drivers/gpu/nova-core/gpu.rs    |  27 +++++++--
 drivers/gpu/nova-core/mm.rs     |  24 ++++++++
 drivers/gpu/nova-core/mm/tlb.rs | 120 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/nova-core/regs.rs   |  68 +++++++++++++++++++++++
 5 files changed, 234 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index cb7f0b00f796..1934f17baa8b 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -5,6 +5,7 @@ config NOVA_CORE
 	depends on RUST
 	depends on !CPU_BIG_ENDIAN
 	select AUXILIARY_BUS
+	select GPU_BUDDY
 	select RUST_FW_LOADER_ABSTRACTIONS
 	default n
 	help
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index a52a3d4d86af..b797472279d3 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -6,11 +6,16 @@
     device,
     dma::Device,
     fmt,
+    gpu::buddy::GpuBuddyParams,
     io::Io,
     num::Bounded,
     pci,
     prelude::*,
-    sizes::SizeConstants, //
+    ptr::Alignment,
+    sizes::{
+        SizeConstants,
+        SZ_4K, //
+    },
 };
 
 use crate::{
@@ -422,11 +427,21 @@ pub(crate) fn new<'a>(
             },
 
             // Create GPU memory manager owning memory management resources.
-            mm: GpuMm::new(
-                bar,
-                gsp_resources.spec.chipset,
-                VramAddress::from_raw(gsp_static_info.total_fb_end),
-            )?,
+            mm: {
+                let usable_vram = gsp_static_info.usable_fb_regions.first().ok_or(ENODEV)?;
+                let buddy_params = GpuBuddyParams {
+                    base_offset: usable_vram.start,
+                    size: usable_vram.end - usable_vram.start,
+                    chunk_size: Alignment::new::<SZ_4K>(),
+                };
+
+                GpuMm::new(
+                    bar,
+                    gsp_resources.spec.chipset,
+                    buddy_params,
+                    VramAddress::from_raw(gsp_static_info.total_fb_end),
+                )?
+            },
         })
     }
 
diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs
index 4234ba4d596a..202bb8f8ebed 100644
--- a/drivers/gpu/nova-core/mm.rs
+++ b/drivers/gpu/nova-core/mm.rs
@@ -40,6 +40,10 @@ macro_rules! impl_pfn_bounded {
 use kernel::{
     bitfield,
     fmt,
+    gpu::buddy::{
+        GpuBuddy,
+        GpuBuddyParams, //
+    },
     num::Bounded,
     prelude::*,
     ptr::{
@@ -54,16 +58,23 @@ macro_rules! impl_pfn_bounded {
     gpu::Chipset, //
 };
 
+pub(crate) use tlb::Tlb;
+
 mod hal;
 mod pramin;
 mod regs;
+pub(super) mod 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.
 pub(crate) struct GpuMm<'gpu> {
+    buddy: GpuBuddy,
     pramin: pramin::Pramin<'gpu>,
+    tlb: Pin<KBox<Tlb<'gpu>>>,
 }
 
 impl<'gpu> GpuMm<'gpu> {
@@ -71,6 +82,7 @@ impl<'gpu> GpuMm<'gpu> {
     pub(crate) fn new(
         bar: Bar0<'gpu>,
         chipset: Chipset,
+        buddy_params: GpuBuddyParams,
         total_fb_end: VramAddress,
     ) -> Result<Self> {
         // PRAMIN covers all physical VRAM (including GSP-reserved areas
@@ -78,14 +90,26 @@ pub(crate) fn new(
         let vram_region = VramAddress::ZERO..total_fb_end;
 
         Ok(Self {
+            buddy: GpuBuddy::new(buddy_params)?,
             pramin: pramin::Pramin::new(bar, chipset, vram_region)?,
+            tlb: KBox::pin_init(Tlb::new(bar), GFP_KERNEL)?,
         })
     }
 
+    /// Access the [`GpuBuddy`] allocator.
+    pub(crate) fn buddy(&self) -> &GpuBuddy {
+        &self.buddy
+    }
+
     /// Access the [`pramin::Pramin`].
     fn pramin_mut(&mut self) -> &mut pramin::Pramin<'gpu> {
         &mut self.pramin
     }
+
+    /// Access the [`Tlb`] manager.
+    pub(crate) fn tlb(&self) -> &Tlb<'gpu> {
+        self.tlb.as_ref().get_ref()
+    }
 }
 
 /// Page size in bytes (4 KiB).
diff --git a/drivers/gpu/nova-core/mm/tlb.rs b/drivers/gpu/nova-core/mm/tlb.rs
new file mode 100644
index 000000000000..cc862e8159a1
--- /dev/null
+++ b/drivers/gpu/nova-core/mm/tlb.rs
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! TLB (Translation Lookaside Buffer) flush support for GPU MMU.
+//!
+//! After modifying page table entries, the GPU's TLB must be flushed to
+//! ensure the new mappings take effect. This module provides TLB flush
+//! functionality for virtual memory managers.
+//!
+//! # Examples
+//!
+//! ```ignore
+//! use crate::mm::tlb::Tlb;
+//!
+//! fn page_table_update(tlb: &Tlb, pdb_addr: VramAddress) -> Result<()> {
+//!     // ... modify page tables ...
+//!
+//!     // Flush TLB to make changes visible (polls for completion).
+//!     tlb.flush(pdb_addr)?;
+//!
+//!     Ok(())
+//! }
+//! ```
+
+use kernel::{
+    io::poll::read_poll_timeout,
+    io::Io,
+    new_mutex,
+    prelude::*,
+    sync::Mutex,
+    time::Delta, //
+};
+
+use crate::{
+    bounded_enum,
+    driver::Bar0,
+    mm::VramAddress,
+    regs, //
+};
+
+bounded_enum! {
+    /// TLB invalidation acknowledgment scope.
+    ///
+    /// Controls how far the hardware waits for the invalidation to propagate
+    /// before clearing the `trigger` bit of `NV_TLB_FLUSH_CTRL`.
+    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
+    pub(crate) enum TlbAckMode with TryFrom<Bounded<u32, 2>> {
+        /// Fire-and-forget: no acknowledgment required.
+        None = 0,
+        /// Wait for acknowledgment from all consumers, including remote GPUs
+        /// reachable over NVLink.
+        ///
+        /// Globally is strictly required only during unmap or permission
+        /// tightening, because the backing memory may be reassigned after the
+        /// flush returns and a stale TLB entry could let the GPU access freed
+        /// memory. For new mapping or relaxing permissions, a stale entry would
+        /// merely cause a redundant fault and retry, so [`TlbAckMode::None`]
+        /// would suffice.
+        Globally = 1,
+        /// Wait for acknowledgment from consumers within the local NVLink
+        /// fabric node only; skip cross-node ack.
+        Intranode = 2,
+    }
+}
+
+/// TLB manager for GPU translation buffer operations.
+#[pin_data]
+pub(crate) struct Tlb<'gpu> {
+    bar: Bar0<'gpu>,
+    /// TLB flush serialization lock: This lock is designed to be acquired during
+    /// the DMA fence signalling critical path. It should NEVER be held across any
+    /// reclaimable CPU memory allocations because the memory reclaim path can
+    /// call `dma_fence_wait()` (when implemented), which would deadlock if lock held.
+    #[pin]
+    lock: Mutex<()>,
+}
+
+impl<'gpu> Tlb<'gpu> {
+    /// Create a new TLB manager.
+    pub(super) fn new(bar: Bar0<'gpu>) -> impl PinInit<Self> {
+        pin_init!(Self {
+            bar,
+            lock <- new_mutex!((), "tlb_flush"),
+        })
+    }
+
+    /// Flush the GPU TLB for a specific page directory base.
+    ///
+    /// This invalidates all TLB entries associated with the given PDB address.
+    /// Must be called after modifying page table entries to ensure the GPU sees
+    /// the updated mappings.
+    pub(super) fn flush(&self, pdb_addr: VramAddress) -> Result {
+        let _guard = self.lock.lock();
+
+        // Write PDB address.
+        self.bar.write_reg(regs::NV_TLB_FLUSH_PDB_LO::from_pdb_addr(
+            pdb_addr.into_raw(),
+        ));
+        self.bar.write_reg(regs::NV_TLB_FLUSH_PDB_HI::from_pdb_addr(
+            pdb_addr.into_raw(),
+        ));
+
+        // Trigger flush.
+        self.bar.write_reg(
+            regs::NV_TLB_FLUSH_CTRL::zeroed()
+                .with_all_va(true)
+                .with_ack(TlbAckMode::None)
+                .with_trigger(true),
+        );
+
+        // Poll for completion.
+        read_poll_timeout(
+            || Ok(self.bar.read(regs::NV_TLB_FLUSH_CTRL)),
+            |ctrl: &regs::NV_TLB_FLUSH_CTRL| !ctrl.trigger(),
+            Delta::ZERO,
+            Delta::from_secs(2),
+        )?;
+
+        Ok(())
+    }
+}
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index bf1f3a97c632..9978fb2803b0 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -10,6 +10,7 @@
     sizes::SizeConstants,
     time, //
 };
+use pin_init::Zeroable;
 
 use crate::{
     driver::NovaRegisters,
@@ -26,6 +27,7 @@
         PFalconRegisters,
         PeregrineCoreSelect, //
     },
+    mm::tlb::TlbAckMode, //
 };
 
 // PBUS
@@ -471,3 +473,69 @@ pub(crate) mod gb202 {
         }
     }
 }
+
+// MMU TLB
+
+register! {
+    base: NovaRegisters;
+
+    /// TLB flush register: PDB address lower bits.
+    pub(crate) NV_TLB_FLUSH_PDB_LO(u32) @ 0x00b830a0 {
+        /// PDB address bits [39:8].
+        31:0    pdb_lo => u32;
+    }
+
+    /// TLB flush register: PDB address higher bits.
+    pub(crate) NV_TLB_FLUSH_PDB_HI(u32) @ 0x00b830a4 {
+        /// PDB address bits [47:40].
+        7:0     pdb_hi => u8;
+    }
+
+    /// TLB flush control register.
+    pub(crate) NV_TLB_FLUSH_CTRL(u32) @ 0x00b830b0 {
+        /// Invalidate every VA in the PDB selected by `NV_TLB_FLUSH_PDB_LO/HI`.
+        0:0     all_va => bool;
+        /// Invalidate TLBs for all PDBs (ignores `NV_TLB_FLUSH_PDB_LO/HI`).
+        1:1     all_pdb => bool;
+        /// Restrict the flush to the HUB MMU's TLBs; skip broadcasting to the
+        /// per-GPC L2 TLBs.
+        ///
+        /// The GPU MMU has a two-level TLB hierarchy:
+        /// 1. The *HUB MMU* sits at the top and serves memory requests from
+        ///    "host-side" engines: the host/channel interface, copy engines,
+        ///    display, and BAR1/BAR2 accesses.
+        /// 2. Each GPC (Graphics Processing Cluster — the block that houses
+        ///    shader cores / SMs) has its own L2 TLB that serves requests from
+        ///    the compute and graphics engines inside the cluster.
+        ///
+        /// When set, only the HUB TLBs are invalidated. This is a performance
+        /// optimization for flushes that only affect HUB-side mappings (e.g.
+        /// BAR1/BAR2 windows), where fanning the invalidation out to every
+        /// GPC's L2 TLB would be wasted work. Must be false when flushing
+        /// mappings that may be cached by compute/graphics engines.
+        2:2     hubtlb_only => bool;
+        /// Invalidation acknowledgment scope. See [`TlbAckMode`] for details.
+        8:7     ack ?=> TlbAckMode;
+        /// Write 1 to kick off the flush. Hardware clears this bit when the
+        /// flush completes; reads as 1 while the flush is in progress.
+        31:31   trigger => bool;
+    }
+}
+
+impl NV_TLB_FLUSH_PDB_LO {
+    /// Create a register value from a PDB address.
+    ///
+    /// Extracts bits [39:8] of the address and shifts it right by 8 bits.
+    pub(crate) fn from_pdb_addr(addr: u64) -> Self {
+        Self::zeroed().with_pdb_lo(((addr >> 8) & 0xFFFF_FFFF) as u32)
+    }
+}
+
+impl NV_TLB_FLUSH_PDB_HI {
+    /// Create a register value from a PDB address.
+    ///
+    /// Extracts bits [47:40] of the address and shifts it right by 40 bits.
+    pub(crate) fn from_pdb_addr(addr: u64) -> Self {
+        Self::zeroed().with_pdb_hi(((addr >> 40) & 0xFF) as u8)
+    }
+}

-- 
2.55.0


  parent reply	other threads:[~2026-09-09  4:00 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09  3:59 [PATCH 00/16] gpu: nova-core: GPU page table, vmm, and bar1 mapping Eliot Courtney
2026-09-09  3:59 ` [PATCH 01/16] gpu: nova-core: mm: Add common types for virtual memory management Eliot Courtney
2026-09-09  3:59 ` Eliot Courtney [this message]
2026-09-09  3:59 ` [PATCH 03/16] gpu: nova-core: mm: Add common types for all page table formats Eliot Courtney
2026-09-09  3:59 ` [PATCH 04/16] gpu: nova-core: mm: pagetable: Add PteOps trait Eliot Courtney
2026-09-09  3:59 ` [PATCH 05/16] gpu: nova-core: mm: pagetable: Add PdeOps trait Eliot Courtney
2026-09-09  3:59 ` [PATCH 06/16] gpu: nova-core: mm: pagetable: Add DualPdeOps trait Eliot Courtney
2026-09-09  3:59 ` [PATCH 07/16] gpu: nova-core: mm: Add MMU v2 page table types Eliot Courtney
2026-09-09 18:43   ` Danilo Krummrich
2026-09-09  3:59 ` [PATCH 08/16] gpu: nova-core: mm: Add MMU v3 " Eliot Courtney
2026-09-09  3:59 ` [PATCH 09/16] gpu: nova-core: mm: pagetable: Add MmuConfig trait Eliot Courtney
2026-09-09  3:59 ` [PATCH 10/16] gpu: nova-core: mm: Add page table walker for MMU v2/v3 Eliot Courtney
2026-09-09  3:59 ` [PATCH 11/16] gpu: nova-core: mm: Add Virtual Memory Manager Eliot Courtney
2026-09-09  3:59 ` [PATCH 12/16] gpu: nova-core: mm: Add virtual address range tracking to VMM Eliot Courtney
2026-09-09 19:32   ` Danilo Krummrich
2026-09-09  3:59 ` [PATCH 13/16] gpu: nova-core: mm: Add multi-page mapping API " Eliot Courtney
2026-09-09 19:58   ` Danilo Krummrich
2026-09-10  0:47   ` Alistair Popple
2026-09-09  3:59 ` [PATCH 14/16] gpu: nova-core: Add BAR1 aperture type and size constant Eliot Courtney
2026-09-09  3:59 ` [PATCH 15/16] gpu: nova-core: mm: Add BAR1 user interface Eliot Courtney
2026-09-09 20:13   ` Danilo Krummrich
2026-09-09  3:59 ` [PATCH 16/16] gpu: nova-core: mm: Add BAR1 memory management self-tests Eliot Courtney
2026-09-09 21:11 ` [PATCH 00/16] gpu: nova-core: GPU page table, vmm, and bar1 mapping Danilo Krummrich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909-mmrebase-v1-2-8dd5d4225d2e@nvidia.com \
    --to=ecourtney@nvidia.com \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jhubbard@nvidia.com \
    --cc=joelagnelf@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ttabi@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®