GPU1.0卡适配指导
更新时间: 2025/12/09
在Gitcode上查看源码

本文档主要介绍如何在openUBMC上适配一张规范1.0的GPU卡,规范1.0是普通Pcie卡配置,包含csr配置与代码协议适配。

GPU卡介绍

GPU(Graphics Processing Unit,图形处理单元)加速卡是一种专门用于图形渲染和并行计算的硬件设备。最初设计用于加速计算机图形处理,但随着技术发展,GPU已成为通用并行计算的重要工具,广泛应用于科学计算、人工智能、数据分析等领域。

与CPU(Central Processing Unit,中央处理单元)相比,GPU拥有更多的核心数和更高的内存带宽,特别适合处理大规模并行计算任务。

GPU加速卡已从单纯的图形处理设备发展成为通用并行计算的核心组件,尤其在人工智能、科学计算和数据中心领域发挥着不可替代的作用。随着技术的不断进步,GPU加速卡将继续推动计算能力的提升,为各行业的创新应用提供强大的算力支持。

GPU卡适配流程

与其他部件一样,每一张GPU卡都有一个CSR文件,CSR文件用来告诉openUBMC如何识别GPU卡、管理GPU卡信息、监控GPU卡状态、GPU卡信息管理等。

新适配一张GPU卡CSR需要做什么

  • GPU卡的名称、型号、厂商、槽位号、序列号、四元组、处理器类型、部件编码、root BDF等固定信息。
  • 需要监控GPU卡的哪些状态,如GPU卡温度、GPU卡状态、GPU卡功耗等。
  • GPU卡传感器都需要哪些,如何获取这些传感器读值。
  • 需要上报哪些告警或事件及告警条件,如温度、GPU卡预故障、GPU卡替换记录、GPU卡PCIE带宽、GPU卡PCIE速率等。
  • GPU卡的状态和告警信息获取来源。
  • GPU卡是否需要单独的调速策略。
  • GPU卡是否需要适配新的协议。

GPU卡识别

  • 配置正确的SR文件名称,根据“BOM+ID+AUXID”组成对应GPU卡的文件名,在GPU卡连接的上级组件(如载板、IEU)SR中,配置GPU卡的连接器,然后根据硬件反馈的在位信号加载GPU卡SR文件。
  • SR加载的IdentifyMode模式建议配置为2,由BIOS上报GPU卡BDF信息后BMC根据上报的BDF查询四元组信息并加载GPU卡。

GPU卡加载流程如下:

json
{
    "Connector_PCIE_1": {
            "Bom": "14140130",
            "Slot": 1,
            "Position": 1,
            "Presence": 0,  // 在位信息由BIOS上报后,BMC根据上报的BDF查询四元组信息,并查找对应的SR后更新在位状态
            "Id": "",
            "AuxId": "",
            "Buses": [
                "I2cMux_IEUChan1"
            ],
            "SystemId": "${SystemId}",
            "ManagerId": "${ManagerId}",
            "ChassisId": "${ChassisId}",
            "IdentifyMode": 2,    // 下级组件识别方式,2对应下级组件识别方式为BoardId不可读(上报)类型组件
            "Container": "Component_RiserCard",
            "Type": "PCIe"
        }
}

管理拓扑对象

  • 配置GPU卡的所有总线信息
  • 配置所有通道信息
  • 配置所有chip信息
json
{
    "ManagementTopology": {
        "Anchor": {
        "Buses": ["I2cMux_Chan"]
        },
        "I2cMux_Chan": {
        "Chips": ["Chip_TempChip"]
        }
    }
}

component对象

  • 配置GPU卡的FruId
  • 配置GPU卡的部件类型
  • 配置GPU卡的在位信息
  • 配置GPU卡的序列号来源
  • 配置GPU卡的名称
json
{
    "Component_PCIeCard": {
        "Instance": "<=/PCIeDevice_1.SlotID",
        "Type": 8,  // 部件类型,对应代码中的COMPONENT_TYPE*
        "Name": "<=/PCIeDevice_1.DeviceName",  // 名称
        "FruId": 255,  // 无Fru则默认255,有Fru则引用Fru对象的FruId
        "Presence": 1,  // 在位信息
        "Health": 0,  // 健康状态
        "PowerState": 1,  // 电源状态
        "BoardId": 65535,  // 板卡ID
        "UniqueId": "N/A", // 唯一ID
        "Manufacturer": "Nvidia",  // 厂商
        "GroupId": 1,
        "ReplaceFlag": 0,    // 是否被替换标记
        "PreviousSN": "",  // 上一个序列号
        "SerialNumber": "<=/PCIeCard_1.SerialNumber"  // 序列号
    }
}

Entity对象

json
{
    "Entity_GPUCard": {
    "Id": 11,
    "Name": "GPUCard",
    "PowerState": 1,
    "Presence": 1,
    "Instance": 101
    }
}

GPU对象

定义GPU卡的基本信息和属性

  • 名称
  • ID
  • 位置信息
  • 厂商信息
  • 设备的插槽号
  • 型号信息
  • GPU卡固件版本
  • GPU卡部件编码
  • GPU卡的四元组信息
  • GPU卡的BDF信息
json
{
    "GPU_1": {
        "SystemId": 1,
        "Id": 1,  // GPU ID
        "Name": "RTX A6000",  // GPU卡名称
        "Presence": 1,  // GPU卡在位状态,0:不在位,1:在位,255:无效值
        "Manufacturer": "Nvidia",  // GPU卡厂商
        "Model": "RTX A6000",  // GPU卡型号
        "SN": "",  // GPU卡序列号,一般需要通过GPU带外管理协议获取
        "SocketDesignation": "1",
        "Position": "<=/PCIeDevice_1.Position",  // GPU卡的位置信息
        "ProcessorType": "2",  // 处理器类型,对于GPU,在CSR配置为"2"
        "Health": "#/Component_PCIeCard.Health",  // 健康状态
        "Slot": "<=/PCIeDevice_1.SlotID",  // 设备的插槽号
        "VendorID": 4318,  // 设备的VendorID
        "DeviceID": 8752,  // 设备的DeviceID
        "SubVendorID": 4318,  // 设备的子供应商ID
        "SubDeviceID": 5209,  // 设备的子设备ID
        "DevBus": "<=/PCIeDevice_1.DevBus",  // 设备的 Bus
        "DevDevice": "<=/PCIeDevice_1.DevDevice",  // 设备的 Device
        "DevFunction": "<=/PCIeDevice_1.DevFunction",  // 设备的 Function
        "RefChip": "#/Chip_TempChip",  // 引用的芯片对象
        "SerialNumber": "#/PCIeCard_1.SerialNumber",  // GPU卡序列号
        "CardFirmwareVersion": "#/PCIeCard_1.FirmwareVersion",  // GPU卡固件版本
        "CardPartNumber": "0632Y014"  // GPU卡部件编码
    }
}

PCIeDevice对象

json
{
    "PCIeDevice_1": {
        "Segment": 1,  // 段号,应用于多PCI Bridge场景,每个Segment对应一个PCI Bus空间
        "DeviceName": "PCIe Card $ (RTX A6000)",  // 设备资源名称
        "DiagnosticFault": 0,  // 严重故障诊断告警状态
        "PredictiveFault": 0,  // 预故障告警状态
        "FunctionClass": 3,  // 功能分类,0:未知、1:RAID、2:网卡、3:GPU卡、4:存储卡(SSD卡/M.2卡)、5:SDI卡、6:加速卡、7:扩展卡(PCIe Riser)、8:FPGA卡、9:NPU卡
        "Position": "",  // 设备位置(容器名称)
        "Container": "${Container}",  // PCIe设备容器引用
        "GroupPosition": "PCIeDevice_${GroupPosition}",  // PCIe设备对象的主键,同一个CSR里不能重复
        "BandwidthReduction": 0,  // 带宽减少告警上报事件属性,BIOS上报
        "CorrectableError": 0,  // 可恢复错误,BIOS上报
        "UncorrectableError": 0,  // 不可恢复错误,BIOS上报
        "FatalError": 0,  // 致命错误,BIOS上报
        "LinkSpeedReduced": 0,  // PCIe设备降速率检测告警上报事件属性,BIOS上报
        "DeviceType": 8,  // 设备类型,对应代码中的DEVICE_TYPE*
        "PCIeDeviceType": "SingleFunction",  // 设备类型
        "SlotType": "FullLength",  // 插槽类型
        "FunctionProtocol": "PCIe",  // 协议类型
        "FunctionType": "Physical",  // 功能类型
        "SlotID": 1,  // 槽位号
        "Bus": 0,  // root port Bus
        "Device": 0,  // root port Device
        "Function": 0,  // root port Function
        "DevBus": 1,  // 设备总线
        "DevDevice": 0,  // 设备的 Device
        "DevFunction": 0,   // 设备的 Function
        "SocketID": 0  // CPU ID
        }
}

PCIeCard对象

json
{
    "PCIeCard_1": {
        "SlotID": "<=/PCIeDevice_1.SlotID",  // 设备的插槽号
        "NodeID": "<=/PCIeDevice_1.SlotID |> string.format('PCIeCard%s',$1)",  // 板卡节点ID
        "Name": "RTX A6000",  // 板卡名称
        "DeviceName": "<=/PCIeDevice_1.DeviceName",  // 设备资源名称
        "BoardName": "RTX A6000",  // 板卡名称
        "Model": "RTX A6000",  // 设备型号
        "Description": "RTX A6000",  // 设备描述
        "FunctionClass": 3,  // 功能分类,0:未知、1:RAID、2:网卡、3:GPU卡、4:存储卡(SSD卡/M.2卡)、5:SDI卡、6:加速卡、7:扩展卡(PCIe Riser)、8:FPGA卡、9:NPU卡
        "VendorID": 4318,  // 设备的 VendorID
        "DeviceID": 8752,  // 设备的 DeviceID
        "SubVendorID": 4318,  // 设备的子供应商ID
        "SubDeviceID": 5209,  // 设备的子设备ID
        "Position": "<=/PCIeDevice_1.Position",  // 下级器件对应的Position
        "LaneOwner": "<=/PCIeDevice_1.SocketID",  // 资源归属,起始值为1,表示当前卡挂在哪个CPU下
        "FirmwareVersion": "<=/GPU_1.FirmwareVersion",  // 固件版本
        "Manufacturer": "Nvidia",  // 厂商
        "PartNumber": "0632Y014",  // 部件编码
        "Protocol": "",  // 协议类型
        "MaxFrameLen": 64,  // 最大帧长度
        "LinkSpeed": "N/A",  // 当前链路速率
        "LinkSpeedCapability": "N/A",  // 最大链路速率
        "PcbVersion": "N/A",  // PCB版本
        "DevBus": "<=/PCIeDevice_1.DevBus",  // 设备总线
        "DevDevice": "<=/PCIeDevice_1.DevDevice",  // 设备的 Device
        "SerialNumber": "<=/GPU_1.SN",  // 序列号
        "DevFunction": "<=/PCIeDevice_1.DevFunction"   // 设备的 Function
        }
}

配置告警和事件

传感器定制与开发请参考《传感器定制与开发》进行配置,以下仅举例GPU卡相关传感器。

  • 设置温度监控阈值,用于告警或调速

阈值传感器对象 (ThresholdSensor)

  • 6个阈值
  • 告警取消滞后值
  • 读值数据源
  • 合理的M,RBExp值,使计算出的传感器读值在一个字节的有效区间
json
{
    "ThresholdSensor_GPUTemp": {
        "OwnerId": 32,  // 传感器的归属Id
        "OwnerLun": 0,  // 传感器的归属Lun
        "EntityId": "<=/Entity_GPU.Id",  // 传感器对应实体标识,关联传感器对应的 Entity.Id
        "EntityInstance": "<=/Entity_GPU.Instance",  // 传感器对应实体实例,关联传感器对应的 Entity.Instance
        "Initialization": 127,  // 传感器初始化选项,门限传感器取值127
        "Capabilities": 104,  // 传感器生效条件
        "SensorType": 1,  // 传感器类型,参考ipmi规范42章
        "ReadingType": 1,  // 传感器读值类型,门限传感器取值1
        "SensorName": "<=/PCIeDevice_1.SlotID |> string.format('GPU%s Temp',$1)",  // 传感器名
        "Unit": 128,  // 单位,128表示有符号,0表示无符号
        "BaseUnit": 1,  // 传感器基准单位,参考ipmi规范,温度传感器为1
        "ModifierUnit": 0,  // 传感器单位描述符
        "Analog": 1,
        "NominalReading": 25,
        "NormalMaximum": 0,
        "NormalMinimum": 0,
        "MaximumReading": 127,  // 传感器最大读值
        "MinimumReading": 128,  // 传感器最小读值
        "Reading": "<=/Scanner_GPUTemp.Value",  // 传感器读值
        "ReadingStatus": "<=/Scanner_GPUTemp.Value;<=/Scanner_GPUTemp.Status |> expr($1 >= 255 ? 2 : ($2 == 0 ? 0 : 2))",  // 传感器读值状态
        "AssertMask": 128,  // 告警能力掩码,参考ipmi规范Assertion Event Mask
        "DeassertMask": 28800,  // 参考ipmi规范Deassertion Event Mask
        "ReadingMask": 2056,
        "Linearization": 0,
        "M": 100,  // 线性计算方程参数
        "RBExp": 224,  // [7:4]RExp(K2,有符号,二补数),共4-bit,[3:0]BExp(K1,有符号,二补数),共4-bit
        "UpperNoncritical": 93,  // 非临界上限阈值
        "PositiveHysteresis": 2,  // 告警阈值滞后值
        "NegativeHysteresis": 2  // 告警阈值滞后值
    }
}

Event告警事件对象

json
    "Event_PCIeCardUCE": {  // 不可恢复故障事件
        "Reading": "<=/PCIeDevice_1.DiagnosticFault;<=/PCIeDevice_1.UCEByBIOS |> expr(($1 + $2) == 0 ? 0 : 1)",
        "OperatorId": 5,
        "Enabled": true,
        "AdditionalInfo": "2",
        "DescArg2": "#/Component_PCIeCard.Name",
        "DescArg4": "NA",
        "Component": "#/Component_PCIeCard",
        "EventKeyId": "PCIeCard.PCIeCardUncorrectableErr",
        "Condition": 1,
        "LedFaultCode": "q$"
    },
    "Event_PCIeCardCE": {  // 可恢复故障事件
        "Reading": "<=/PCIeDevice_1.PredictiveFault",
        "OperatorId": 5,
        "Enabled": true,
        "AdditionalInfo": "2",
        "DescArg2": "#/Component_PCIeCard.Name",
        "Component": "#/Component_PCIeCard",
        "EventKeyId": "PCIeCard.PCIeCardCEHardFailure",
        "Condition": 1,
        "LedFaultCode": "q$"
    },
    "Event_PcieCardReplaceMntr": {  // 替换事件
        "Reading": "<=/Component_PCIeCard.ReplaceFlag",
        "OperatorId": 5,
        "Enabled": true,
        "AdditionalInfo": "1",
        "DescArg1": "#/Component_PCIeCard.Name",
        "DescArg2": "#/Component_PCIeCard.PreviousSN",
        "DescArg3": "#/Component_PCIeCard.SerialNumber",
        "Component": "#/Component_PCIeCard",
        "EventKeyId": "PcieCard.PcieCardReplace",
        "Condition": 1
    },
    "Event_OverTemp": {  // 温度告警事件
        "Reading": "<=/Scanner_GPUTemp.Value |> expr(($1 >= 255) ? 30 : ($1 & 255))",
        "@Default": {
            "Condition": 93
        },
        "OperatorId": 4,
        "Enabled": true,
        "Component": "#/Component_PCIeCard",
        "AdditionalInfo": "2",
        "DescArg2": "#/Component_PCIeCard.Name",
        "DescArg4": "#/Event_OverTemp.Reading |> string.format('%s', $1)",
        "DescArg5": "#/ThresholdSensor_GPUTemp.UpperNoncritical",
        "EventKeyId": "PCIeCard.PCIeCardOverTemp",
        "Condition": "<=/ThresholdSensor_GPUTemp.UpperNoncritical",
        "Hysteresis": "<=/ThresholdSensor_GPUTemp.PositiveHysteresis"
    },
    "Event_TempFail": {  // 温度获取失败事件
        "Reading": "<=/Scanner_GPUTemp.Status",
        "OperatorId": 5,
        "Enabled": true,
        "Component": "#/Component_PCIeCard",
        "AdditionalInfo": "2",
        "DescArg2": "#/Component_PCIeCard.Name",
        "EventKeyId": "PcieCard.PCIeCardTempFail",
        "Condition": 1
    },
    "Event_PCIeBandWidth": {  // 带宽告警事件
        "Reading": "<=/PCIeDevice_1.BandwidthReduction",
        "OperatorId": 5,
        "Enabled": true,
        "AdditionalInfo": "2",
        "DescArg2": "#/PCIeDevice_1.SlotID",
        "DescArg3": "(RTX A6000)",
        "Component": "#/Component_PCIeCard",
        "EventKeyId": "PCIeCard.PCIeCardBandWidthDecreased",
        "Condition": 1
    },
    "Event_PCIeLinkSpeed": {  // 链路速度告警事件
        "Reading": "<=/PCIeDevice_1.LinkSpeedReduced",
        "OperatorId": 5,
        "Enabled": true,
        "AdditionalInfo": "2",
        "DescArg2": "#/PCIeDevice_1.SlotID",
        "DescArg3": "(RTX A6000)",
        "Component": "#/Component_PCIeCard",
        "EventKeyId": "PCIeCard.PCIeCardLinkSpeedReduced",
        "Condition": 1
    }

散热控制对象

  • 目标温度
  • 最大允许温度
json
{
    "CoolingConfig_Basic": {  // CoolingConfig类通常不配置在板卡的配置文件中
        "SmartCoolingState": "Enabled",  // 智能调速是否启用,取值范围"Enabled","Disabled"
        "SmartCoolingMode": "EnergySaving",  // 智能调速模式,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "LevelPercentRange": [20, 100],  // 智能调速等级范围,样例中为调速范围为20-100
        "InitLevelInStartup": 100,  // 启动时默认调速等级,取值范围LevelPercentRange
        "DiskRowTemperatureAvailable": false,  // 硬盘温度是否可获取
        "SysHDDsMaxTemperature": 80.0,  // HDD硬盘最大温度阈值
        "SysSSDsMaxTemperature": 80.0,  // SSD硬盘最大温度阈值
        "SensorLocationSupported": false  // 是否支持温度海洋界面
    }
    "CoolingPolicy_EnergySaving": {
        "PolicyIdx": 6,  // 线性调速策略Id,PolicyIdx必须全局唯一
        "ExpCondVal": "EnergySaving",  // 预期生效条件,CoolingPolicy生效前提是实际条件与期望条件一致,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "ActualCondVal": "<=/CoolingConfig_1.SmartCoolingMode",  // 实际生效条件,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "TemperatureRangeLow": [-127, 20, 30, 40, 50],  // 线性调速策略温度区间低门限
        "TemperatureRangeHigh": [20, 30, 40, 50, 127],  // 线性调速策略温度区间高门限
        "SpeedRangeLow": [20, 32, 70, 100],  // 线性调速策略转速区间低门限
        "SpeedRangeHigh": [20, 32, 70, 100],  // 线性调速策略转速区间高门限
        "FanType": ["02314BLG 8038+"]  // 风扇类型列表,环境风扇类型为列表之一时,风扇条件生效
    }
    "CoolingRequirement_1_7": {
        "RequirementId": 7,  // 目标调速策略Id,Id必须全局唯一,当前Id支持有效16位,前8位baseid,后8位槽位号
        "TemperatureType": 11,  // 目标调速温度点类型,1:Cpu 2:Outlet 3:Disk 4:Memory 5:PCH 6:VRD 7:VDDQ 8:NPUHbm 9:NPUAiCore 10:NPUBoard 11:Inlet 12:SoCBoardOutlet 13:SoCBoardInlet
        "MonitoringStatus": "<=/Scanner_Lm75_Inlet.Status",  // 温度点传感器状态,0:正常 1:异常
        "MonitoringValue": "<=/Scanner_Lm75_Inlet.Value;<=/Scanner_Lm75_Inlet.Value |> expr((($1 + 5) > ($2 - 10)) ? ($1 + 5) : ($2 - 10))",  // 参与调速的温度值
        "FailedValue": 80,  // 温度状态异常后的异常调速转速,不配代表不触发异常调速;如果配置了值,温度点读取失败的时候,异常调速会固定下发这个转速值
        "TargetTemperatureCelsius": 50,  // 当前调速目标值
        "MaxAllowedTemperatureCelsius": 60,
        "TargetTemperatureRangeCelsius": [  // 自定义温度允许范围,用于自定义目标值时的合法性判断
            40,
            60
        ],
        "SmartCoolingTargetTemperature": [  // EnergySaving/HighPerformance/LowNoise 三种模式下的目标温度值,可不配置
            50,
            47,
            53
        ],
        "CustomSupported": true,  // 是否支持自定义目标温度值,true:支持,false:不支持
        "CustomTargetTemperatureCelsius": 50,  // 用户自定义温度值,255为无效值
        "SensorName": "#/ThresholdSensor_InletTemp.SensorName"  // 传感器名称
    },
    "CoolingArea_1_25": {
        "AreaId": 25,
        "RequirementIdx": 25,
        "PolicyIdxGroup": [],
        "FanIdxGroup": [
            1,
            2,
            3,
            4
        ]
    }
}

新增需要实现带外管理协议的GPU卡

NVIDIA的GPU:
NVIDIA的GPU采用自定义的带外管理协议SMBus Post Box Interface(SMBPBI),当前openUBMC已支持。新适配NVIDIA的GPU卡时,理论上只需增加配置文件(路径在general_hardware/src/lualib/hardware_config/),配置文件名需要和GPU对象的"Model"字段匹配,具体可参考general_hardware仓的Tesla_T4.lua和RTX_A6000.lua。

非NVIDIA的GPU卡:
非NVIDIA的GPU卡如果要实现新的带外管理协议,需要修改general_hardware组件代码,可以参考NVIDIA GPU的代码流程,新增GPU卡驱动请按照如下规范:
《GPU卡驱动规范v0.1》


常见问题

1、GPU卡无法识别
说明:GPU卡一般按IdentifyMode为2的方式加载,该方式整体流程为:
->整机适配时,在BMC配置PCIE卡的PcieAddrInfo对象。
->BIOS通过WritePcieCardBdfToBmc、WriteOcpCardBdfToBmc将设备的BDF号传给BMC。
->BMC根据BDF号向IMU查询对应PCIe槽位的四元组信息,设置对应属性到对应连接器的ID和AuxID和在位信息,从而加载对应的CSR。


2、iBMA上报的数据无法正确匹配
说明:检查对应的PcieAddrInfo对象配置是否和硬件信息匹配,可在os下用lscpi命令查看每个对应槽位卡的bdf等信息。


3、接入GPU卡后风扇转速/噪音/散热不满足
说明:GPU卡通常是高发热部件,一般都需要专门的调速策略,如果没有增加专门的调速策略,容易导致散热不满足或风扇转速过高等问题,需要整机适配时考虑GPU卡的散热,对输出针对具体GPU卡的调速策略。