Re: [PATCH v3 09/33] gpu: nova-core: add GMC API message types

From: John Hubbard

Date: Mon Sep 21 2026 - 22:26:12 EST


On 9/18/26 2:45 PM, Timur Tabi wrote:
> On Thu, 2026-09-17 at 18:06 -0700, John Hubbard wrote:
>>
>> +#[repr(C)]
>> +pub(crate) struct QueueElementHeader {
>> +    magic: u32,
>> +    /// Length of the whole element: the queue element header, the message header and the
>> +    /// payload. Open RM calls it `mctpPayloadSize`.
>> +    element_len: u32,
>> +    mctp: MctpHeader,
>> +    nvdm: NvdmHeader,
>> +    /// Length of the message header and the payload, the queue element header excluded. Open
>> RM
>> +    /// calls it `nvdmPayloadSize`.
>> +    message_len: u32,
>> +    reserved: u32,
>> +}
>> +
>> +static_assert!(
>> +    core::mem::offset_of!(QueueElementHeader, magic)
>> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT, mctpMagic)
>> +);
>> +static_assert!(
>> +    core::mem::offset_of!(QueueElementHeader, element_len)
>> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT, mctpPayloadSize)
>> +);
>> +static_assert!(
>> +    core::mem::offset_of!(QueueElementHeader, mctp)
>> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT, mctpHeader)
>> +);
>> +static_assert!(
>> +    core::mem::offset_of!(QueueElementHeader, nvdm)
>> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT, nvdmHeader)
>> +);
>
> Can you also static_assert! on the size of the struct?

Not directly, because it's got a union involved, but I've added in some
assorted static_asserts that attempt to cover as much as can be asserted
in this situation.

Open RM's layout:

typedef struct {
NvU32 mctpMagic;
NvU32 mctpPayloadSize;
NvU32 mctpHeader;
NvU32 nvdmHeader;
union {
struct {
GSP_MSG_QUEUE_ENCRYPTION_TAG encryptionTag; /* 16 bytes */
NvU32 nvdmPayloadSize;
NvU32 reserved;
NvU8 payload[];
} withEncryption;
struct {
NvU32 nvdmPayloadSize;
NvU32 reserved;
NvU8 payload[];
} noEncryption;
};
} GSP_MSG_QUEUE_ELEMENT;

QueueElementHeader uses the noEncryption layout.

Open RM has the same mismatch and defines the unencrypted size separately,
as GSP_MSG_QUEUE_ELEMENT_SIZE_NO_ENCRYPTION, which is the offset of the
union plus two words.

I've added these static asserts, for v4:

* The size of QueueElementHeader equals the offset of the union plus
the size of the noEncryption struct.

* The offset of message_len equals the offset of the union plus the
offset of nvdmPayloadSize within noEncryption.

* The offset of reserved equals the offset of the union plus the
offset of reserved within noEncryption.

>
>> +    /// Returns the length of the payload that follows a message header of
>> +    /// Returns the length of the payload that follows a message header of
>> `message_header_len`
>> +    /// bytes.
>> +    fn payload_len(&self, message_header_len: usize) -> usize {
>> +        num::u32_as_usize(self.message_len).saturating_sub(message_header_len)
>
> Is it possible for message_header_len to exceed self.message_len? If so, then I think that
> warrants a comment. If not, well, then that should have a comment, too.

Yes, it is possible.

So, in v4, I've made this return an Option<usize> in this patch, instead
of waiting until later patches to do that.

The v4 doc comment on payload_len() now says that None means the message
length in the queue element header is shorter than the message header.


thanks,
--
John Hubbard