[PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication

John Hubbard posted 31 patches 2 weeks, 5 days ago
There is a newer version of this series
[PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by John Hubbard 2 weeks, 5 days ago
Add the MCTP (Management Component Transport Protocol) and NVDM (NVIDIA
Device Management) wire-format types used for communication between the
kernel driver and GPU firmware processors.

This includes typed MCTP transport headers, NVDM message headers, and
NVDM message type identifiers. Both the FSP boot path and the upcoming
GSP RPC message queue share this protocol layer.

Cc: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 drivers/gpu/nova-core/mctp.rs      | 126 +++++++++++++++++++++++++++++
 drivers/gpu/nova-core/nova_core.rs |   1 +
 2 files changed, 127 insertions(+)
 create mode 100644 drivers/gpu/nova-core/mctp.rs

diff --git a/drivers/gpu/nova-core/mctp.rs b/drivers/gpu/nova-core/mctp.rs
new file mode 100644
index 000000000000..9e052d916e79
--- /dev/null
+++ b/drivers/gpu/nova-core/mctp.rs
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! MCTP/NVDM protocol types for NVIDIA GPU firmware communication.
+//!
+//! MCTP (Management Component Transport Protocol) carries NVDM (NVIDIA
+//! Device Management) messages between the kernel driver and GPU firmware
+//! processors such as FSP and GSP.
+
+#![expect(dead_code)]
+
+/// NVDM message type identifiers carried over MCTP.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub(crate) enum NvdmType {
+    /// Chain of Trust boot message.
+    Cot = 0x14,
+    /// FSP command response.
+    FspResponse = 0x15,
+}
+
+impl TryFrom<u8> for NvdmType {
+    type Error = u8;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            x if x == Self::Cot as u8 => Ok(Self::Cot),
+            x if x == Self::FspResponse as u8 => Ok(Self::FspResponse),
+            _ => Err(value),
+        }
+    }
+}
+
+impl From<NvdmType> for u8 {
+    fn from(value: NvdmType) -> Self {
+        value as u8
+    }
+}
+
+bitfield! {
+    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
+        31:31 som as bool, "Start-of-message bit.";
+        30:30 eom as bool, "End-of-message bit.";
+        29:28 seq as u8, "Packet sequence number.";
+        23:16 seid as u8, "Source endpoint ID.";
+    }
+}
+
+impl MctpHeader {
+    /// Build a single-packet MCTP header (SOM=1, EOM=1, SEQ=0, SEID=0).
+    pub(crate) fn single_packet() -> Self {
+        Self::default().set_som(true).set_eom(true)
+    }
+
+    /// Return the raw packed u32.
+    pub(crate) const fn raw(self) -> u32 {
+        self.0
+    }
+
+    /// Check if this is a complete single-packet message (SOM=1 and EOM=1).
+    pub(crate) fn is_single_packet(self) -> bool {
+        self.som() && self.eom()
+    }
+}
+
+impl From<u32> for MctpHeader {
+    fn from(raw: u32) -> Self {
+        Self(raw)
+    }
+}
+
+/// MCTP message type for PCI vendor-defined messages.
+const MSG_TYPE_VENDOR_PCI: u8 = 0x7e;
+
+/// NVIDIA PCI vendor ID.
+const VENDOR_ID_NV: u16 = 0x10de;
+
+bitfield! {
+    pub(crate) struct NvdmHeader(u32), "NVIDIA Vendor-Defined Message header over MCTP." {
+        31:24 raw_nvdm_type as u8, "Raw NVDM message type.";
+        23:8 vendor_id as u16, "PCI vendor ID.";
+        6:0 msg_type as u8, "MCTP vendor-defined message type.";
+    }
+}
+
+impl NvdmHeader {
+    /// Build an NVDM header for the given message type.
+    pub(crate) fn new(nvdm_type: NvdmType) -> Self {
+        Self::default()
+            .set_msg_type(MSG_TYPE_VENDOR_PCI)
+            .set_vendor_id(VENDOR_ID_NV)
+            .set_nvdm_type(nvdm_type)
+    }
+
+    /// Return the raw packed u32.
+    pub(crate) const fn raw(self) -> u32 {
+        self.0
+    }
+
+    /// Extract the NVDM type field as a typed value.
+    pub(crate) fn nvdm_type(self) -> core::result::Result<NvdmType, u8> {
+        NvdmType::try_from(self.raw_nvdm_type())
+    }
+
+    /// Extract the NVDM type field as a raw value.
+    pub(crate) fn nvdm_type_raw(self) -> u32 {
+        u32::from(self.raw_nvdm_type())
+    }
+
+    /// Set the NVDM type field from a typed value.
+    pub(crate) fn set_nvdm_type(self, nvdm_type: NvdmType) -> Self {
+        self.set_raw_nvdm_type(u8::from(nvdm_type))
+    }
+
+    /// Validate this header against the expected NVIDIA NVDM format and type.
+    pub(crate) fn validate(self, expected_type: NvdmType) -> bool {
+        self.msg_type() == MSG_TYPE_VENDOR_PCI
+            && self.vendor_id() == VENDOR_ID_NV
+            && matches!(self.nvdm_type(), Ok(nvdm_type) if nvdm_type == expected_type)
+    }
+}
+
+impl From<u32> for NvdmHeader {
+    fn from(raw: u32) -> Self {
+        Self(raw)
+    }
+}
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index b5caf1044697..3bd9b1dd0264 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -13,6 +13,7 @@
 mod gfw;
 mod gpu;
 mod gsp;
+mod mctp;
 mod num;
 mod regs;
 mod sbuffer;
-- 
2.53.0
Re: [PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by John Hubbard 2 weeks, 5 days ago
On 3/17/26 3:53 PM, John Hubbard wrote:
...
> +bitfield! {
> +    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
> +        31:31 som as bool, "Start-of-message bit.";
> +        30:30 eom as bool, "End-of-message bit.";
> +        29:28 seq as u8, "Packet sequence number.";
> +        23:16 seid as u8, "Source endpoint ID.";

hmmm, I seem to remember my very slightly younger self insisting
that fields be listed from lowest to highest bits. And now I've
violated that in both headers in this patch. arghh

I'll fix it if there is a v8 required.

thanks,
-- 
John Hubbard
Re: [PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by Danilo Krummrich 2 weeks, 5 days ago
On Wed Mar 18, 2026 at 1:01 AM CET, John Hubbard wrote:
> On 3/17/26 3:53 PM, John Hubbard wrote:
> ...
>> +bitfield! {
>> +    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
>> +        31:31 som as bool, "Start-of-message bit.";
>> +        30:30 eom as bool, "End-of-message bit.";
>> +        29:28 seq as u8, "Packet sequence number.";
>> +        23:16 seid as u8, "Source endpoint ID.";
>
> hmmm, I seem to remember my very slightly younger self insisting
> that fields be listed from lowest to highest bits. And now I've
> violated that in both headers in this patch. arghh

My now slightly older self still thinks that what you have above is actually the
way to go. So, I think your current self intuitively did the right thing. :P

It should be either

	31:16
	15:0

or it should be

	0:15
	16:31

with a strong preference for the former, but this

	15:0
	31:16

still looks pretty odd to me.
Re: [PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by Gary Guo 2 weeks, 5 days ago
On Wed Mar 18, 2026 at 12:21 AM GMT, Danilo Krummrich wrote:
> On Wed Mar 18, 2026 at 1:01 AM CET, John Hubbard wrote:
>> On 3/17/26 3:53 PM, John Hubbard wrote:
>> ...
>>> +bitfield! {
>>> +    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
>>> +        31:31 som as bool, "Start-of-message bit.";
>>> +        30:30 eom as bool, "End-of-message bit.";
>>> +        29:28 seq as u8, "Packet sequence number.";
>>> +        23:16 seid as u8, "Source endpoint ID.";
>>
>> hmmm, I seem to remember my very slightly younger self insisting
>> that fields be listed from lowest to highest bits. And now I've
>> violated that in both headers in this patch. arghh
>
> My now slightly older self still thinks that what you have above is actually the
> way to go. So, I think your current self intuitively did the right thing. :P
>
> It should be either
>
> 	31:16
> 	15:0

This is my preferred form as it closer to what hardware world uses and the order
is consistent with most data sheets.

Best,
Gary

>
> or it should be
>
> 	0:15
> 	16:31
>
> with a strong preference for the former, but this
>
> 	15:0
> 	31:16
>
> still looks pretty odd to me.
Re: [PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by John Hubbard 2 weeks, 5 days ago
On 3/18/26 5:36 AM, Gary Guo wrote:
> On Wed Mar 18, 2026 at 12:21 AM GMT, Danilo Krummrich wrote:
>> On Wed Mar 18, 2026 at 1:01 AM CET, John Hubbard wrote:
>>> On 3/17/26 3:53 PM, John Hubbard wrote:
>>> ...
>>>> +bitfield! {
>>>> +    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
>>>> +        31:31 som as bool, "Start-of-message bit.";
>>>> +        30:30 eom as bool, "End-of-message bit.";
>>>> +        29:28 seq as u8, "Packet sequence number.";
>>>> +        23:16 seid as u8, "Source endpoint ID.";
>>>
>>> hmmm, I seem to remember my very slightly younger self insisting
>>> that fields be listed from lowest to highest bits. And now I've
>>> violated that in both headers in this patch. arghh
>>
>> My now slightly older self still thinks that what you have above is actually the
>> way to go. So, I think your current self intuitively did the right thing. :P
>>
>> It should be either
>>
>> 	31:16
>> 	15:0
> 
> This is my preferred form as it closer to what hardware world uses and the order
> is consistent with most data sheets.
> 
> Best,
> Gary
> 

I'll let this patch alone in v8, then, as the most important
thing for me is the bit order. I don't worry so much about the
vertical order in which bitfields are listed.

Whew, I do hope this (along with my recent rustfmtcheck sins)
are the only remaining items. Getting close...

>>
>> or it should be
>>
>> 	0:15
>> 	16:31
>>
>> with a strong preference for the former, but this
>>
>> 	15:0
>> 	31:16
>>
>> still looks pretty odd to me.
> 

I will concede that the above is an acquired taste. :)

thanks,
-- 
John Hubbard
Re: [PATCH v7 18/31] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication
Posted by Alexandre Courbot 2 weeks, 5 days ago
On Wed Mar 18, 2026 at 9:21 AM JST, Danilo Krummrich wrote:
> On Wed Mar 18, 2026 at 1:01 AM CET, John Hubbard wrote:
>> On 3/17/26 3:53 PM, John Hubbard wrote:
>> ...
>>> +bitfield! {
>>> +    pub(crate) struct MctpHeader(u32), "MCTP transport header for NVIDIA firmware messages." {
>>> +        31:31 som as bool, "Start-of-message bit.";
>>> +        30:30 eom as bool, "End-of-message bit.";
>>> +        29:28 seq as u8, "Packet sequence number.";
>>> +        23:16 seid as u8, "Source endpoint ID.";
>>
>> hmmm, I seem to remember my very slightly younger self insisting
>> that fields be listed from lowest to highest bits. And now I've
>> violated that in both headers in this patch. arghh
>
> My now slightly older self still thinks that what you have above is actually the
> way to go. So, I think your current self intuitively did the right thing. :P
>
> It should be either
>
> 	31:16
> 	15:0
>
> or it should be
>
> 	0:15
> 	16:31
>
> with a strong preference for the former, but this
>
> 	15:0
> 	31:16
>
> still looks pretty odd to me.

Mmm, that's the order `regs.rs` currently uses. I don't have any
particular problem with it tbh.

The second form (`0:15`) is going to be rejected by the macro - it
expects the high bit first.