nvidia-gpu: add support for communication to the endpoint
The commit uses MCTP VDM protocol to read temperature sensor value from
the gpu.
The MCTP VDM protocol is an extension of the OCP Accelerator Management
Interface specification. [1]
Tested: Build an image for gb200nvl-obmc machine with the following
patches cherry picked. This patches are needed to enable the mctp stack.
https://gerrit.openbmc.org/c/openbmc/openbmc/+/79422
Restart the nvidiagpusensor service.
```
root@gb200nvl-obmc:~# systemctl start xyz.openbmc_project.nvidiagpusensor.service
```
The app is detecting entity-manager configuration on gb200nvl-obmc
machine. The app is also able to detect all the endpoints from the mctp
service dbus tree. The app is reading temperature sensor value from gpu
correctly and the temperature sensor is also present on redfish.
```
$ curl -k -u 'root:0penBmc' https://10.137.203.137/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/temperature_NVIDIA_GB200_GPU
{
"@odata.id": "/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/temperature_NVIDIA_GB200_GPU",
"@odata.type": "#Sensor.v1_2_0.Sensor",
"Id": "temperature_NVIDIA_GB200_GPU",
"Name": "NVIDIA GB200 GPU",
"Reading": 36.4375,
"ReadingRangeMax": 127.0,
"ReadingRangeMin": -128.0,
"ReadingType": "Temperature",
"ReadingUnits": "Cel",
"Status": {
"Health": "OK",
"State": "Enabled"
}
}%
root@gb200nvl-obmc:~# busctl tree xyz.openbmc_project.GpuSensor
└─ /xyz
└─ /xyz/openbmc_project
└─ /xyz/openbmc_project/sensors
└─ /xyz/openbmc_project/sensors/temperature
└─ /xyz/openbmc_project/sensors/temperature/NVIDIA_GB200_GPU
root@gb200nvl-obmc:~# busctl introspect xyz.openbmc_project.GpuSensor /xyz/openbmc_project/sensors/temperature/NVIDIA_GB200_GPU
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
xyz.openbmc_project.Association.Definitions interface - - -
.Associations property a(sss) 1 "chassis" "all_sensors" "/xyz/openbmc… emits-change
xyz.openbmc_project.Sensor.Value interface - - -
.MaxValue property d 127 emits-change
.MinValue property d -128 emits-change
.Unit property s "xyz.openbmc_project.Sensor.Value.Unit.… emits-change
.Value property d 36.3125 emits-change writable
xyz.openbmc_project.Sensor.ValueMutability interface - - -
.Mutable property b true emits-change
xyz.openbmc_project.State.Decorator.Availability interface - - -
.Available property b true emits-change writable
xyz.openbmc_project.State.Decorator.OperationalStatus interface - - -
.Functional property b true emits-change
```
[1] https://www.opencompute.org/documents/ocp-gpu-accelerator-management-interfaces-v1-pdf
Change-Id: Ied938b9e5c19751ee283b4b948e16c905c78fb48
Signed-off-by: Harshit Aghera <haghera@nvidia.com>
diff --git a/src/nvidia-gpu/OcpMctpVdm.hpp b/src/nvidia-gpu/OcpMctpVdm.hpp
new file mode 100644
index 0000000..735d0a5
--- /dev/null
+++ b/src/nvidia-gpu/OcpMctpVdm.hpp
@@ -0,0 +1,107 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
+ * AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <span>
+
+namespace ocp
+{
+namespace accelerator_management
+{
+
+constexpr uint8_t messageType = 0x7E;
+
+constexpr uint8_t ocpType = 8;
+constexpr uint8_t ocpVersion = 9;
+constexpr uint8_t ocpTypeBitOffset = 4;
+constexpr uint8_t ocpTypeBitMask = 0b11110000;
+constexpr uint8_t ocpVersionBitMask = 0b00001111;
+constexpr uint8_t instanceIdBitMask = 0b00011111;
+constexpr uint8_t instanceIdReservedBitMask = 0b00100000;
+constexpr uint8_t datagramBitMask = 0b01000000;
+constexpr uint8_t requestBitMask = 0b10000000;
+
+constexpr uint8_t instanceMin = 0;
+constexpr uint8_t instanceMax = 31;
+
+enum class CompletionCode : uint8_t
+{
+ SUCCESS = 0x00,
+ ERROR = 0x01,
+ ERR_INVALID_DATA = 0x02,
+ ERR_INVALID_DATA_LENGTH = 0x03,
+ ERR_NOT_READY = 0x04,
+ ERR_UNSUPPORTED_COMMAND_CODE = 0x05,
+ ERR_UNSUPPORTED_MSG_TYPE = 0x06,
+ ERR_BUS_ACCESS = 0x7f,
+ ERR_NULL = 0x80,
+};
+
+enum class ReasonCode : uint16_t
+{
+ REASON_NONE = 0x00,
+};
+
+enum class MessageType : uint8_t
+{
+ RESPONSE = 0, //!< OCP MCTP VDM response message
+ REQUEST = 2, //!< OCP MCTP VDM request message
+};
+
+struct BindingPciVid
+{
+ uint16_t pci_vendor_id; //!< PCI defined vendor ID
+ uint8_t instance_id; //!< Instance ID
+ uint8_t ocp_version; //!< OCP version
+ uint8_t ocp_accelerator_management_msg_type; //!< Message Type
+} __attribute__((packed));
+
+struct Message
+{
+ BindingPciVid hdr; //!< OCP MCTP VDM message header
+} __attribute__((packed));
+
+struct BindingPciVidInfo
+{
+ uint8_t ocp_accelerator_management_msg_type;
+ uint8_t instance_id;
+ uint8_t msg_type;
+};
+
+struct CommonRequest
+{
+ Message msgHdr;
+ uint8_t command;
+ uint8_t data_size;
+} __attribute__((packed));
+
+struct CommonResponse
+{
+ Message msgHdr;
+ uint8_t command;
+ uint8_t completion_code;
+ uint16_t reserved;
+ uint16_t data_size;
+} __attribute__((packed));
+
+struct CommonNonSuccessResponse
+{
+ Message msgHdr;
+ uint8_t command;
+ uint8_t completion_code;
+ uint16_t reason_code;
+} __attribute__((packed));
+
+int packHeader(uint16_t pciVendorId, const BindingPciVidInfo& hdr,
+ BindingPciVid& msg);
+
+int decodeReasonCodeAndCC(std::span<const uint8_t> buf, CompletionCode& cc,
+ uint16_t& reasonCode);
+
+} // namespace accelerator_management
+} // namespace ocp