硬件故障诊断
概述
HUATUO 华佗以零侵入、低开销的方式持续监听 Linux 内核上报的硬件错误事件,将结构化的故障记录持久化存储,并以 Prometheus 指标形式对外暴露汇总计数器,供告警与可视化系统使用。
应用场景
-
通用计算
大规模服务器集群中,内存 ECC 可纠正错误(CE)是常见的低级别故障信号。单次 CE 可由硬件自动修复,但若同一 DIMM 上 CE 频率持续升高,则预示着内存条即将失效。华佗通过 EDAC/MCE tracepoint 实时感知此类事件,使工程团队能够在内存彻底失效前完成预防性换件,避免意外宕机。
-
AI 计算
AI 训练任务对硬件可靠性要求极高,单块故障的 PCIe 设备即可导致整个训练任务失败。华佗支持 PCIe AER 事件监测,能够实时上报 GPU、NVLink Bridge、RDMA 网卡(如 InfiniBand HCA)的链路层错误(Data Link Protocol Error、ECRC Error 等),为 AI 集群调度系统提供硬件健康状态数据,支撑故障节点的快速隔离与任务迁移。
-
存储服务
存储服务器通常配备大量 PCIe NVMe SSD 和 HBA 卡。PCIe AER 中的 Completion Timeout、Malformed TLP 等错误是存储设备性能抖动或掉线的先兆。华佗监控数据可与存储 IO 延迟指标联动,支撑根因分析。
-
安全合规
金融、政务等对合规有严格要求的行业,需要完整记录所有硬件故障历史。结构化事件存储(含时间戳、设备标识、错误类型、原始寄存器值)可直接作为硬件健康日志的合规存证。
监控原理
HUATUO 华佗通过 eBPF 技术观测内核的 MCE / EDAC / ACPI GHES / PCIe AER 子系统,当 eBPF tracepoint 被触发时,将原始事件写入 BPF Perf Event Buffer。用户态程序读取事件,解析结构体字段,生成结构化记录,并存储至本地或远端。总体架构如下:

RAS 原理
Linux 内核的 RAS 体系由多个相对独立的子系统协同构成,共同覆盖从 CPU 内部错误到 PCIe 链路错误的完整硬件故障谱系。
graph TB
subgraph HW["硬件层"]
CPU["CPU\nx86 / x86-64"]
MEM["内存\nDDR4/DDR5 DIMM ECC"]
Platform["平台硬件\nSoC / PCH"]
PCIeDev["PCIe 设备\nGPU / NVMe / HCA / FPGA"]
end
subgraph FW["固件层"]
BIOS["BIOS / UEFI\nCPER 缓冲区(APEI)"]
end
subgraph Kernel["Linux 内核 RAS 子系统"]
MCE["MCE 子系统\narch/x86/kernel/cpu/mce"]
EDAC["EDAC 子系统\ndrivers/edac"]
GHES["ACPI GHES 子系统\ndrivers/acpi/apei"]
AER["PCIe AER 子系统\ndrivers/pci/pcie/aer"]
end
subgraph TP["内核 Tracepoint"]
TP1["tracepoint/mce/mce_record"]
TP2["tracepoint/ras/mc_event"]
TP3["tracepoint/ras/non_standard_event"]
TP4["tracepoint/ras/aer_event"]
end
CPU -->|"MCE 异常(#MC)+ THR 中断"| MCE
MEM -->|ECC 错误| EDAC
Platform -->|APEI 错误记录| BIOS
BIOS -->|CPER 缓冲区| GHES
PCIeDev -->|AER 中断| AER
MCE --> TP1
EDAC --> TP2
GHES --> TP3
AER --> TP4
-
MCE
MCE(Machine Check Architecture)是处理器内置的硬件容错机制,由 Intel 和 AMD 在各自的架构规范中定义。处理器内部存在若干 Bank(Machine Check Bank),每个 Bank 对应一类硬件资源(如 L1 Cache、L2 Cache、内存控制器、TLB 等)。当检测到硬件错误时,对应 Bank 的 MSR 寄存器(MCi_STATUS、MCi_ADDR、MCi_MISC)被填充错误信息,并触发 MCE 异常。
-
MCE THR
MCE 支持阈值中断机制。当某类可纠正错误的计数超过预设阈值时,触发专用 APIC 中断(THR),而不升级为完整的 MCE 异常。此机制允许操作系统在错误频率异常升高时提前告警,而非等到错误完全不可纠正时才介入。
-
EDAC
EDAC(Error Detection And Correction)是 Linux 内核中专门处理内存和硬件 ECC 错误的子系统,其目标是"检测并报告运行在 Linux 下的计算机系统中发生的硬件错误"。EDAC 驱动直接与内存控制器通信,解析 ECC 错误的物理位置(内存控制器编号、Channel、Slot、行列地址)。
-
ACPI GHES
ACPI GHES(Generic Hardware Error Source,通用硬件错误源)是一种平台无关的硬件错误上报机制,由 BIOS/UEFI 通过 APEI(ACPI Platform Error Interface)规范定义。BIOS 固件将无法被特定驱动处理的硬件错误(如特定 SoC 内部错误、平台特定内存错误)写入 GHES 描述符中的 CPER(Common Platform Error Record)缓冲区。Linux 内核读取 CPER 记录,并上报无法被标准子系统解析的"非标准"错误部分。
-
PCIe AER
PCIe AER(Advanced Error Reporting)是 PCIe 规范定义的错误上报机制,允许 PCIe 设备向操作系统精确报告链路层和事务层的错误类型。
指标总览
-
RAS 指标
# HELP huatuo_bamai_ras_hw_total total RAS hardware error events by source type # TYPE huatuo_bamai_ras_hw_total counter huatuo_bamai_ras_hw_total{host="hostname",region="dev",type="acpi"} 0 huatuo_bamai_ras_hw_total{host="hostname",region="dev",type="aer"} 0 huatuo_bamai_ras_hw_total{host="hostname",region="dev",type="edac"} 0 huatuo_bamai_ras_hw_total{host="hostname",region="dev",type="mce"} 0 huatuo_bamai_ras_hw_total{host="hostname",region="dev",type="thr"} 0 -
网卡丢包
huatuo_bamai_netdev_hw_rx_dropped_total{host="hostname",region="dev",device="eth0",driver="ixgbe"} 0 -
RDMA PFC
# HELP huatuo_bamai_netdev_dcb_pfc_received_total count of the received pfc frames # TYPE huatuo_bamai_netdev_dcb_pfc_received_total counter huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="0",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="1",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="2",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="3",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="4",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="5",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="6",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_received_total{device="enp6s0f0np0",host="hostname",prio="7",region="dev"} 0 # HELP huatuo_bamai_netdev_dcb_pfc_send_total count of the sent pfc frames # TYPE huatuo_bamai_netdev_dcb_pfc_send_total counter huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="0",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="1",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="2",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="3",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="4",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="5",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="6",region="dev"} 0 huatuo_bamai_netdev_dcb_pfc_send_total{device="enp6s0f0np0",host="hostname",prio="7",region="dev"} 0 -
结构化存储
此外,每个硬件错误事件均以结构化形式持久化(存储于本地 huatuo-local 目录或远端 ES/OS 存储等),包含以下公共字段:
{ "hostname": "hostname", "region": "dev", "uploaded_time": "2026-03-05T18:28:39.153438921+08:00", "time": "2026-03-05 18:28:39.153 +0800", "tracer_name": "netdev_event", "tracer_time": "2026-03-05 18:28:39.153 +0800", "tracer_type": "auto", "tracer_data": { "ifname": "eth0", "index": 2, "linkstatus": "linkstatus_admindown", "mac": "5c:6f:11:11:11:11", "start": false } }linkstatus 字段的可能取值如下:
- linkstatus_adminup 管理员开启网卡,例如 ip link set dev eth0 up
- linkstatus_admindown 管理员关闭网卡,例如 ip link set dev eth0 down
- linkstatus_carrierup 物理链路恢复
- linkstatus_carrierdown 物理链路故障
{ "hostname": "localhost", "region": "xxx", "uploaded_time": "2026-05-11T16:58:47.328548319+08:00", "time": "2026-05-11 16:58:47.328 +0800", "tracer_name": "ras", "tracer_time": "2026-05-11 16:58:47.328 +0800", "tracer_type": "auto", "tracer_data": { "dev": "MEM", "event": "EDAC", "type": "Corrected", "timestamp": 537792166031, "info": "{\"err_count\":0,\"err_type\":\"Corrected\",\"err_msg\":\"memory read error\",\"label\":\"CPU_SrcID#0_Ha#0_Chan#0_DIMM#0\",\"mc_index\":0,\"top_layer\":0,\"mid_layer\":0,\"low_layer\":-1,\"addr\":7860269056,\"grain\":128,\"syndrome\":0,\"driver\":\" area:DRAM err_code:0000:009f socket:0 ha:0 channel_mask:1 rank:0\"}" } }字段名 含义 Device发生错误的硬件部件标识(如 CPU/MEM、MEM、ACPI、PCIe 0000:01:00.0)Event事件子类型( MCE、EDAC、APIC、AER)ErrType错误严重级别(见下表) Timestamp时间戳 Info具体事件的详细字段 错误类型 含义 典型来源 Corrected已由硬件自动纠正,系统无感知 MCE CE, EDAC CE, ACPI Sev=1, AER Severity=2 UncorrectedRecoverable硬件无法纠正,但系统软件可修复的错误 MCE UE, EDAC UE, ACPI Sev=2, AER Severity=0 UncorrectedDeferred硬件无法纠正,需要延迟处理的错误 MCE MCI_STATUS_DEFERRED, EDAC HW_EVENT_ERR_DEFERRED UncorrectedFatal硬件无法纠正的致命错误,需立即重启 EDAC FATAL, ACPI Sev=3, AER Severity=0 Info期望系统记录日志信息的错误类型 EDAC HW_EVENT_ERR_INFO, ACPI Sev=0
详细说明
-
MCE
监控部件:CPU 核心、L1/L2/L3 Cache、TLB、内存控制器(IMC)、互连总线(QPI/UPI/Infinity Fabric)。
字段名 MSR 来源 含义 mcg_cpu_capMCG_CAP机器检查全局能力寄存器。低 8 位( Count)表示系统中 MC Bank 的数量。mcg_msr_statusMCG_STATUS机器检查全局状态寄存器**。 banks_msr_statusMCi_STATUSBank 状态寄存器(最核心字段)。低 16 位为 MCA 错误代码(分类错误类型,如内存层次错误、总线错误等);高位包含 UC(不可纠正)、EN(已使能)、MISCV(MISC 有效)、ADDRV(ADDR 有效)、PCC(处理器上下文损坏)等控制位。banks_msr_addrMCi_ADDR发生错误的物理内存地址(仅当 MCi_STATUS.ADDRV=1时有效)。可用于定位故障 DIMM 或 Cache Line。banks_msr_miscMCi_MISC补充信息寄存器(仅当 MCi_STATUS.MISCV=1时有效)。mca_synd_msrMCA_SYND综合征寄存器(AMD 专用)。 mca_ipid_msrMCA_IPID实例 ID 寄存器(AMD 专用)。 instr_pointerRIP 寄存器 发生 MCE 时的指令指针(仅当 MCG_STATUS.EIPV=1时可靠)。tsc_timestampTSC 发生错误时的 CPU 时间戳计数器值(可与内核时钟换算为绝对时间)。 walltime内核时间 发生错误时的 Unix 时间戳(秒)。 cpu— 发生 MCE 的逻辑 CPU 编号。 cpuidCPUID 发生 MCE 的 CPU 的 CPUID 值(包含 Family/Model/Stepping)。 apicidAPIC ID 发生 MCE 的 CPU 对应的 APIC ID(可映射到物理核/超线程)。 socketid— CPU 插槽编号(Socket ID)。多路服务器场景下用于区分物理 CPU。 code_segCS 寄存器 发生 MCE 时的代码段寄存器值(用于判断特权级)。 bank— Bank 编号(通常 Bank 0=L1I,Bank 1=L1D,Bank 2=L2,Bank 4+=内存控制器,但编号因平台而异)。 cpuvendor— CPU 厂商标识: 0=Intel,1=未知,2=AMD。 -
EDAC
监控部件:内存 ECC 错误。
字段名 含义 err_count本次事件中累计的错误次数。 err_type错误严重级别。 err_msg人类可读错误描述字符串(如 "CE memory read error on CPU#0Channel#0_DIMM#0 (channel:0 slot:0 page:0x12345 offset:0x0 grain:8 syndrome:0x0)")。label内存条物理位置标签(如 "CPU_SrcID#0_Ha#0_Chan#0_DIMM#0"),由 EDAC 驱动根据 DIMM 拓扑生成,可直接对应机器内部的内存插槽位置。mc_index内存控制器编号(0-based)。多内存控制器服务器上用于区分不同 IMC。 top_layer内存层次结构顶层索引(通常为 Channel 编号,即内存通道号,-1 表示无效)。 mid_layer内存层次结构中层索引(通常为 Slot/Rank 编号,-1 表示无效)。 low_layer内存层次结构底层索引(通常为 Bank/Row 编号,-1 表示无效)。 addr发生错误的物理内存地址(64-bit 无符号整数,0 表示地址无效)。 grain错误粒度(Grain Size,字节数)。表示可能受影响的最小内存单元大小。 syndromeECC 综合征值。 driverEDAC 驱动名称(如 "amd64_edac"、"sb_edac")。 -
ACPI GHES
监控部件:平台特定硬件错误。
字段名 含义 severityACPI/CPER 错误严重级别原始值。 sec_type错误部分类型 GUID(16 字节,十六进制字符串)。由 UEFI 规范和各硬件厂商定义,标识错误记录所属的硬件类别(如内存错误部分、PCIe 错误部分、ARM 处理器错误部分等)。 fru_idFRU(Field Replaceable Unit,现场可替换单元)标识符 GUID(16 字节,十六进制字符串)。唯一标识发生错误的可更换硬件组件(如某块内存条、某个 PCIe 卡)。 fru_textFRU 人类可读描述字符串(如 "CPU0_DIMM_A1")。data_len原始错误数据载荷长度(字节数)。 raw_data原始错误数据的十六进制转储(空格分隔字节)。用于深度诊断,需结合具体硬件厂商文档解析。 -
PCIe AER
监控设备包括 GPU、NVMe SSD、RDMA 网卡/HCA、FPGA 加速卡、PCIe Switch 等。
字段名 含义 dev_namePCIe 设备名称(BDF 格式),如 "0000:03:00.0",分别对应 Domain:Bus:Device.Function。err_type错误严重级别( Corrected/Uncorrected/Fatal)。err_reason具体错误原因描述字符串,由 AER 状态寄存器的比特位解码得出(见下方两张表)。 tlp_header触发错误的 TLP(Transaction Layer Packet)头部四元组(格式: {dword0, dword1, dword2, dword3},十六进制)。TLP 头部包含事务类型、地址、请求者 ID 等信息,是定位错误根因的关键数据。若TlpHeaderValid=0则显示"not available"。 -
PCIe 可纠正错误类型
位掩码 含义 0x00000001接收端错误。物理层接收到不符合规范的数据符号,通常由信号完整性问题引起(如过长连线、阻抗不匹配)。 0x00000040TLP(事务层数据包)错误。数据包的 LCRC(链路层 CRC)校验失败,表明事务层数据在传输中发生翻转,PCIe 链路层会自动重传该 TLP。 0x00000080DLLP(数据链路层数据包)错误。链路层控制包(如 ACK/NAK、流控更新)CRC 校验失败。 0x00000100重传序列号溢出。 REPLAY_NUM字段用于追踪重传次数,该错误表明自上次 ACK 以来已发生过多次重传,通常意味着链路质量持续较差。0x00001000重传计时器超时。发送方在规定时间内未收到 ACK,触发 TLP 重传。持续出现表明链路延迟异常或接收端处理能力不足。 0x00002000顾问性非致命错误。本质上是一个不可纠正但被软件降级为可纠正处理的错误(需启用 AER capability 中的 ANFE 功能),常见于接收到 Unsupported Request Completion 的场景。 0x00004000已纠正内部错误。设备内部 ECC 或奇偶校验错误,已由设备自主纠正。 0x00008000头部日志溢出。AER 头部日志寄存器已满,后续错误的 TLP 头部无法被记录(但错误本身仍被计数)。 -
PCIe 不可纠正错误类型
位掩码 含义 0x00000001未定义错误。保留位被置位,通常表明固件或硬件存在不合规行为。 0x00000010数据链路协议错误。收到了违反 DLLP 协议规范的数据包,属于严重的链路层故障。 0x00000020意外下线错误。物理链路在未经 Hot-Plug 通知的情况下突然断开(如设备意外掉电或接触不良),为热插拔场景下的高危错误。 0x00001000毒化 TLP。接收到数据有效位(EP,Error Poisoning)被主动设置为 1 的 TLP,表明上游发送方知晓该数据已损坏。此机制用于错误传播和隔离,避免静默数据损坏。 0x00002000流控协议错误。接收到违反 PCIe 流控信用(Credit)规则的数据包,属于严重的协议违规。 0x00004000完成超时。请求方(Requester)发出非 Posted 事务(如 Memory Read)后,在规定超时时间内未收到完成包(Completion)。常见于 NVMe 盘固件异常、RDMA 网卡驱动 Bug 或 PCIe 链路中断。 0x00008000完成方中止。接收端显式返回 CA(Completer Abort)状态的 Completion,表示请求被完成方拒绝。 0x00010000意外完成包。收到了无法与任何已发出的请求匹配的 Completion(Tag 不匹配),通常由设备固件 Bug 或数据路径错误引起。 0x00020000接收缓冲区溢出。接收端流控信用信息显示其缓冲区未满,但实际发生了溢出,属于严重的流控违规。 0x00040000格式错误的 TLP。数据包头部字段违反规范(如非法长度、保留字段被置位、不合法的地址范围),通常表明设备固件存在严重缺陷。 0x00080000端到端 CRC 错误。TLP 尾部的 ECRC 校验失败(需双端设备均支持 ECRC 功能),表明数据在整个传输链路(含 PCIe Switch 内部交换)中发生损坏,是高可靠性场景中的关键指标。 0x00100000不支持的请求错误。接收端返回 UR(Unsupported Request)状态,表明请求的事务类型或地址范围不被该设备支持。 0x00200000ACS(Access Control Services)违规。PCIe ACS 机制用于防止 PCIe 设备之间的对等(Peer-to-Peer)DMA 绕过 IOMMU,此错误表明发生了违反 ACS 策略的数据访问,在虚拟化安全场景中需重点关注。 0x00400000不可纠正的内部错误。设备内部发生无法自行纠正的 ECC 或奇偶校验错误(如 SRAM 双比特错误),通常意味着设备硬件损坏。 0x00800000多播(MC)TLP 被阻断。PCIe 多播(Multicast)TLP 被 ACS 或 MC 控制机制阻止。 0x01000000原子操作出口被阻断。AtomicOp(原子操作请求,如 FetchAdd、Swap、CAS)因 ACS 控制被阻止出站,常见于 RDMA/GPU 直连场景。 0x02000000TLP 前缀被阻断。带有 End-End TLP Prefix 的数据包被 ACS 或其他机制阻止转发。
总结
推荐在生产环境中部署华佗,实现全面的硬件错误监控与主动运维。