[PATCH 3/3] gpu: nova-core: gsp: map the WPR meta for streaming DMA

Maurice Hieronymus <[email protected]>
Newsgroups dev.linux.lists.nova-gpu,dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
`GspFwWprMeta` is filled in once during boot, read out of system memory
by the booter, and dropped when `Gsp::boot()` returns. That is a
streaming transfer, so a coherent allocation buys nothing.

Map a `KBox<GspFwWprMeta>` instead. The mapping is submitted right
after initialization, which makes the contents unreachable for the
duration of the chipset-specific boot sequence and lets `dma_handle()`
be read through a shared reference.

`complete()` is called as soon as `hal.boot()` succeeds, the earliest
point the device is provably done with the metadata: on Tu102 the
Booter-load falcon has halted, on GH100 GSP-FMC has released the
lockdown. If `hal.boot()` fails instead, no such proof exists --
`Gsp::unload()` deliberately carries on past failed steps, so the
falcon may still be reading the buffer -- and `wpr_meta` drops in
flight, trading a one-off leak for a device-side use-after-free.

Signed-off-by: Maurice Hieronymus <[email protected]>
---
 drivers/gpu/nova-core/firmware/booter.rs | 11 +++++++----
 drivers/gpu/nova-core/gsp/boot.rs        | 20 ++++++++++++++++++--
 drivers/gpu/nova-core/gsp/hal.rs         |  4 ++--
 drivers/gpu/nova-core/gsp/hal/gh100.rs   |  4 ++--
 drivers/gpu/nova-core/gsp/hal/tu102.rs   |  4 ++--
 5 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/nova-core/firmware/booter.rs b/drivers/gpu/nova-core/firmware/booter.rs
index d9313ac361af..780c7702a777 100644
--- a/drivers/gpu/nova-core/firmware/booter.rs
+++ b/drivers/gpu/nova-core/firmware/booter.rs
@@ -9,9 +9,12 @@
 
 use kernel::{
     device,
-    dma::Coherent,
+    dma::StreamingInFlight,
     prelude::*,
-    transmute::FromBytes, //
+    transmute::{
+        AsBytes,
+        FromBytes, //
+    },
 };
 
 use crate::{
@@ -402,12 +405,12 @@ pub(crate) fn new(
     ///
     /// Resets SEC2, loads this firmware image, then boots with the WPR metadata
     /// address passed via the SEC2 mailboxes.
-    pub(crate) fn run<T>(
+    pub(crate) fn run<T: FromBytes + AsBytes>(
         &self,
         dev: &device::Device<device::Bound>,
         bar: Bar0<'_>,
         sec2_falcon: &Falcon<Sec2>,
-        wpr_meta: &Coherent<T>,
+        wpr_meta: &StreamingInFlight<'_, KBox<T>>,
     ) -> Result {
         sec2_falcon.reset(bar)?;
         sec2_falcon.load(dev, bar, self)?;
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index 8afb62d689cb..300ebf4e843d 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -4,7 +4,10 @@
 use kernel::{
     bits,
     device,
-    dma::Coherent,
+    dma::{
+        DataDirection,
+        Streaming, //
+    },
     io::poll::read_poll_timeout,
     pci,
     prelude::*,
@@ -117,7 +120,12 @@ pub(crate) fn boot(
         let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
         dev_dbg!(dev, "{:#x?}\n", fb_layout);
 
-        let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
+        let wpr_meta = Streaming::new(
+            dev,
+            KBox::init(GspFwWprMeta::new(&gsp_fw, &fb_layout), GFP_KERNEL)?,
+            DataDirection::ToDevice,
+        )?
+        .submit();
 
         // Perform the chipset-specific boot sequence, and retrieve the unload bundle.
         let unload_guard = hal.boot(
@@ -131,6 +139,14 @@ pub(crate) fn boot(
             sec2_falcon,
         )?;
 
+        // The chipset-specific boot sequence only succeeds once the device is done reading the
+        // WPR metadata: on Tu102 the Booter-load falcon has halted, on GH100 GSP-FMC has released
+        // the lockdown. If it fails instead, `wpr_meta` drops in flight and leaks, as the falcon
+        // may still be reading the buffer.
+        //
+        // SAFETY: Per the above, the device has finished accessing the buffer.
+        let _ = unsafe { wpr_meta.complete() };
+
         gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version);
 
         // Poll for RISC-V to become active before continuing.
diff --git a/drivers/gpu/nova-core/gsp/hal.rs b/drivers/gpu/nova-core/gsp/hal.rs
index 04f004856c60..09a523e3a180 100644
--- a/drivers/gpu/nova-core/gsp/hal.rs
+++ b/drivers/gpu/nova-core/gsp/hal.rs
@@ -8,7 +8,7 @@
 
 use kernel::{
     device,
-    dma::Coherent, //
+    dma::StreamingInFlight, //
 };
 
 use crate::{
@@ -61,7 +61,7 @@ fn boot<'a>(
         bar: Bar0<'a>,
         chipset: Chipset,
         fb_layout: &FbLayout,
-        wpr_meta: &Coherent<GspFwWprMeta>,
+        wpr_meta: &StreamingInFlight<'_, KBox<GspFwWprMeta>>,
         gsp_falcon: &'a Falcon<GspEngine>,
         sec2_falcon: &'a Falcon<Sec2>,
     ) -> Result<BootUnloadGuard<'a>>;
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index 98f5ce197d13..67a79c54a739 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -5,7 +5,7 @@
 
 use kernel::{
     device,
-    dma::Coherent,
+    dma::StreamingInFlight,
     io::poll::read_poll_timeout,
     time::Delta, //
 };
@@ -156,7 +156,7 @@ fn boot<'a>(
         bar: Bar0<'a>,
         chipset: Chipset,
         fb_layout: &FbLayout,
-        wpr_meta: &Coherent<GspFwWprMeta>,
+        wpr_meta: &StreamingInFlight<'_, KBox<GspFwWprMeta>>,
         gsp_falcon: &'a Falcon<GspEngine>,
         sec2_falcon: &'a Falcon<Sec2>,
     ) -> Result<BootUnloadGuard<'a>> {
diff --git a/drivers/gpu/nova-core/gsp/hal/tu102.rs b/drivers/gpu/nova-core/gsp/hal/tu102.rs
index 2f6301af7113..7d906de6d8bf 100644
--- a/drivers/gpu/nova-core/gsp/hal/tu102.rs
+++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs
@@ -5,7 +5,7 @@
 
 use kernel::{
     device,
-    dma::Coherent,
+    dma::StreamingInFlight,
     io::Io, //
 };
 
@@ -262,7 +262,7 @@ fn boot<'a>(
         bar: Bar0<'a>,
         chipset: Chipset,
         fb_layout: &FbLayout,
-        wpr_meta: &Coherent<GspFwWprMeta>,
+        wpr_meta: &StreamingInFlight<'_, KBox<GspFwWprMeta>>,
         gsp_falcon: &'a Falcon<GspEngine>,
         sec2_falcon: &'a Falcon<Sec2>,
     ) -> Result<BootUnloadGuard<'a>> {

-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.