[PATCH RFC 4/4] gpu: nova-core: gsp: convert GspMem to zerocopy via the transmute bridge

SeungJong Ha via B4 Relay <[email protected]>
Newsgroups dev.linux.lists.nova-gpu,org.freedesktop.lists.dri-devel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
From: SeungJong Ha <[email protected]>

`GspMem` (shared with the GSP over a DMA `Coherent`) carried a
hand-audited `unsafe impl transmute::{AsBytes, FromBytes}` that did not
actually meet the no-padding requirement: `Msgq` embeds a page-aligned
`MsgqData` after two small headers.

Make that padding explicit (`_pad`), derive the `zerocopy` traits on the
`MsgqData`/`Msgq`/`GspMem` chain, and bridge to `transmute` via
`impl_transmute_via_zerocopy!`. The `unsafe` is now machine-checked.

Unions (e.g. `GspFwWprMeta`) are left on their hand-audited impls, since
`zerocopy::IntoBytes` cannot derive for unions.

Assisted-by: Claude-Code:claude-opus-4-8
Signed-off-by: SeungJong Ha <[email protected]>
---
 drivers/gpu/nova-core/gsp/cmdq.rs | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 070de0731e95..d9929d24d316 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -152,7 +152,7 @@ fn read(
 /// This area of memory is to be shared between the driver and the GSP to exchange commands or
 /// messages.
 #[repr(C, align(0x1000))]
-#[derive(Debug)]
+#[derive(Debug, FromBytes, IntoBytes, Immutable)]
 struct MsgqData {
     data: [[u8; GSP_PAGE_SIZE]; num::u32_as_usize(MSGQ_NUM_PAGES)],
 }
@@ -169,6 +169,7 @@ struct MsgqData {
 /// read pointer of `rx` actually refers to the `Msgq` owned by the other side.
 /// This design ensures that only the driver or GSP ever writes to a given instance of this struct.
 #[repr(C)]
+#[derive(FromBytes, IntoBytes, Immutable)]
 // There is no struct defined for this in the open-gpu-kernel-source headers.
 // Instead it is defined by code in `GspMsgQueuesInit()`.
 // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
@@ -177,12 +178,16 @@ pub(super) struct Msgq {
     pub(super) tx: MsgqTxHeader,
     /// Header for receiving messages, including the read pointer.
     pub(super) rx: MsgqRxHeader,
+    _pad: [u8; GSP_PAGE_SIZE - size_of::<MsgqTxHeader>() - size_of::<MsgqRxHeader>()],
     /// The message queue proper.
     msgq: MsgqData,
 }
 
+static_assert!(size_of::<MsgqTxHeader>() + size_of::<MsgqRxHeader>() <= GSP_PAGE_SIZE);
+
 /// Structure shared between the driver and the GSP and containing the command and message queues.
 #[repr(C)]
+#[derive(FromBytes, IntoBytes, Immutable)]
 // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module.
 pub(super) struct GspMem {
     /// Self-mapping page table entries.
@@ -205,13 +210,7 @@ impl GspMem {
     const PTE_ARRAY_SIZE: usize = GSP_PAGE_SIZE / size_of::<u64>();
 }
 
-// SAFETY: These structs don't meet the no-padding requirements of AsBytes but
-// that is not a problem because they are not used outside the kernel.
-unsafe impl AsBytes for GspMem {}
-
-// SAFETY: These structs don't meet the no-padding requirements of FromBytes but
-// that is not a problem because they are not used outside the kernel.
-unsafe impl FromBytes for GspMem {}
+kernel::impl_transmute_via_zerocopy!(GspMem);
 
 /// Wrapper around [`GspMem`] to share it with the GPU using a [`Coherent`].
 ///

-- 
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.