[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251219203805.1246586-7-joelagnelf@nvidia.com>
Date: Fri, 19 Dec 2025 15:38:05 -0500
From: Joel Fernandes <joelagnelf@...dia.com>
To: Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>,
David Airlie <airlied@...il.com>,
Simona Vetter <simona@...ll.ch>,
Jonathan Corbet <corbet@....net>,
Alex Deucher <alexander.deucher@....com>,
Christian König <christian.koenig@....com>,
Jani Nikula <jani.nikula@...ux.intel.com>,
Joonas Lahtinen <joonas.lahtinen@...ux.intel.com>,
Rodrigo Vivi <rodrigo.vivi@...el.com>,
Tvrtko Ursulin <tursulin@...ulin.net>,
Huang Rui <ray.huang@....com>,
Matthew Auld <matthew.auld@...el.com>,
Matthew Brost <matthew.brost@...el.com>,
Lucas De Marchi <lucas.demarchi@...el.com>,
Thomas Hellström <thomas.hellstrom@...ux.intel.com>,
Helge Deller <deller@....de>
Cc: Danilo Krummrich <dakr@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>,
Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>,
Andreas Hindborg <a.hindborg@...nel.org>,
Trevor Gross <tmgross@...ch.edu>,
John Hubbard <jhubbard@...dia.com>,
Alistair Popple <apopple@...dia.com>,
Timur Tabi <ttabi@...dia.com>,
Edwin Peer <epeer@...dia.com>,
Alexandre Courbot <acourbot@...dia.com>,
Andrea Righi <arighi@...dia.com>,
Philipp Stanner <phasta@...nel.org>,
Elle Rhumsaa <elle@...thered-steel.dev>,
Daniel Almeida <daniel.almeida@...labora.com>,
joel@...lfernandes.org,
nouveau@...ts.freedesktop.org,
dri-devel@...ts.freedesktop.org,
rust-for-linux@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-doc@...r.kernel.org,
amd-gfx@...ts.freedesktop.org,
intel-gfx@...ts.freedesktop.org,
intel-xe@...ts.freedesktop.org,
linux-fbdev@...r.kernel.org,
Joel Fernandes <joelagnelf@...dia.com>
Subject: [PATCH RFC v5 6/6] nova-core: Add PRAMIN aperture self-tests
Add self-tests for the PRAMIN aperture mechanism to verify correct
operation during GPU probe. The tests validate:
- Byte-level read/write at odd-aligned locations
- Word write followed by byte-level readback (endianness verification)
- Window repositioning across 1MB boundaries
The tests are gated behind CONFIG_NOVA_PRAMIN_SELFTESTS which is
disabled by default. When enabled, tests run after GSP boot during
probe.
Also remove the unused lint suppression at the module level since the
PRAMIN code is now being actively used.
Signed-off-by: Joel Fernandes <joelagnelf@...dia.com>
---
drivers/gpu/nova-core/Kconfig | 11 ++++
drivers/gpu/nova-core/gsp/boot.rs | 4 ++
drivers/gpu/nova-core/mm/pramin.rs | 102 ++++++++++++++++++++++++++++-
3 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index 20d3e6d0d796..a37335e3381c 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -14,3 +14,14 @@ config NOVA_CORE
This driver is work in progress and may not be functional.
If M is selected, the module will be called nova_core.
+
+config NOVA_PRAMIN_SELFTESTS
+ bool "PRAMIN self-tests"
+ depends on NOVA_CORE
+ default n
+ help
+ Enable self-tests for the PRAMIN aperture mechanism. When enabled,
+ basic tests are run during GPU probe after GSP boot to
+ verify PRAMIN functionality.
+
+ This is a testing option and should normally be disabled.
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index 54937606b5b0..b9750c86b6ed 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -239,6 +239,10 @@ pub(crate) fn boot(
// Wait until GSP is fully initialized.
commands::wait_gsp_init_done(&mut self.cmdq)?;
+ // Run PRAMIN aperture self-tests (disabled by default).
+ #[cfg(CONFIG_NOVA_PRAMIN_SELFTESTS)]
+ crate::mm::pramin::run_self_test(pdev.as_ref(), bar)?;
+
// Obtain and display basic GPU information.
let info = commands::get_gsp_info(&mut self.cmdq, bar)?;
dev_info!(
diff --git a/drivers/gpu/nova-core/mm/pramin.rs b/drivers/gpu/nova-core/mm/pramin.rs
index 5878a3f80b9c..483832b8f87e 100644
--- a/drivers/gpu/nova-core/mm/pramin.rs
+++ b/drivers/gpu/nova-core/mm/pramin.rs
@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-#![expect(unused)]
-
//! Direct VRAM access through the PRAMIN aperture.
//!
//! PRAMIN provides a 1MB sliding window into VRAM through BAR0, allowing the CPU to access
@@ -56,6 +54,8 @@
//! }
//! ```
+#![allow(unused)]
+
use crate::{
driver::Bar0,
regs, //
@@ -198,3 +198,101 @@ unsafe impl Send for Window<'_> {}
// SAFETY: `Window` requires `&mut self` for all accessors.
unsafe impl Sync for Window<'_> {}
+
+/// Run PRAMIN self-tests during probe.
+#[cfg(CONFIG_NOVA_PRAMIN_SELFTESTS)]
+pub(crate) fn run_self_test(dev: &kernel::device::Device, bar: &Bar0) -> Result {
+ dev_info!(dev, "PRAMIN: Starting self-test...\n");
+
+ let mut win = Window::new(bar);
+
+ // Use offset 0x1000 as test area.
+ let base: usize = 0x1000;
+
+ // Test 1: Read/write at odd-aligned locations.
+ dev_info!(dev, "PRAMIN: Test 1 - Odd-aligned u8 read/write\n");
+ for i in 0u8..4 {
+ let offset = base + 1 + i as usize; // Offsets 0x1001, 0x1002, 0x1003, 0x1004
+ let val = 0xA0 + i;
+ win.try_write8(offset, val)?;
+ let read_val = win.try_read8(offset)?;
+ if read_val != val {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: wrote {:#x}, read {:#x}\n",
+ offset,
+ val,
+ read_val
+ );
+ return Err(EIO);
+ }
+ }
+ dev_info!(dev, "PRAMIN: Test 1 PASSED\n");
+
+ // Test 2: Write u32 and read back as u8s.
+ dev_info!(dev, "PRAMIN: Test 2 - Write u32, read as u8s\n");
+ let test2_offset = base + 0x10;
+ let test2_val: u32 = 0xDEADBEEF;
+ win.try_write32(test2_offset, test2_val)?;
+
+ // Read back as individual bytes (little-endian: EF BE AD DE).
+ let expected_bytes: [u8; 4] = [0xEF, 0xBE, 0xAD, 0xDE];
+ for (i, &expected) in expected_bytes.iter().enumerate() {
+ let read_val = win.try_read8(test2_offset + i)?;
+ if read_val != expected {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test2_offset + i,
+ expected,
+ read_val
+ );
+ return Err(EIO);
+ }
+ }
+ dev_info!(dev, "PRAMIN: Test 2 PASSED\n");
+
+ // Test 3: Window repositioning across 1MB boundaries.
+ // Write to offset > 1MB to trigger window slide, then verify.
+ dev_info!(dev, "PRAMIN: Test 4 - Window repositioning\n");
+ let test4_offset_a = base; // First 1MB region
+ let test4_offset_b = 0x200000 + base; // 2MB + base (different 1MB region)
+ let val_a: u32 = 0x11111111;
+ let val_b: u32 = 0x22222222;
+
+ // Write to first region.
+ win.try_write32(test4_offset_a, val_a)?;
+
+ // Write to second region (triggers window reposition).
+ win.try_write32(test4_offset_b, val_b)?;
+
+ // Read back from second region.
+ let read_b = win.try_read32(test4_offset_b)?;
+ if read_b != val_b {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test4_offset_b,
+ val_b,
+ read_b
+ );
+ return Err(EIO);
+ }
+
+ // Read back from first region (triggers window reposition again).
+ let read_a = win.try_read32(test4_offset_a)?;
+ if read_a != val_a {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test4_offset_a,
+ val_a,
+ read_a
+ );
+ return Err(EIO);
+ }
+ dev_info!(dev, "PRAMIN: Test 3 PASSED\n");
+
+ dev_info!(dev, "PRAMIN: All self-tests PASSED\n");
+ Ok(())
+}
--
2.34.1
Powered by blists - more mailing lists