本文档主要介绍如何在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卡加载流程如下:
{
"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信息
{
"ManagementTopology": {
"Anchor": {
"Buses": ["I2cMux_Chan"]
},
"I2cMux_Chan": {
"Chips": ["Chip_TempChip"]
}
}
}component对象
- 配置GPU卡的FruId
- 配置GPU卡的部件类型
- 配置GPU卡的在位信息
- 配置GPU卡的序列号来源
- 配置GPU卡的名称
{
"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对象
{
"Entity_GPUCard": {
"Id": 11,
"Name": "GPUCard",
"PowerState": 1,
"Presence": 1,
"Instance": 101
}
}GPU对象
定义GPU卡的基本信息和属性
- 名称
- ID
- 位置信息
- 厂商信息
- 设备的插槽号
- 型号信息
- GPU卡固件版本
- GPU卡部件编码
- GPU卡的四元组信息
- GPU卡的BDF信息
{
"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对象
{
"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对象
{
"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值,使计算出的传感器读值在一个字节的有效区间
{
"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告警事件对象
"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
}散热控制对象
- 目标温度
- 最大允许温度
{
"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卡的调速策略。