news 2026/9/7 15:51:26

Linux 内核 RAS 框架深度解析:从 EDAC 子系统的错误处理原理到 sysfs 实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 内核 RAS 框架深度解析:从 EDAC 子系统的错误处理原理到 sysfs 实战

Linux 内核 RAS 框架深度解析:从 EDAC 子系统的错误处理原理到 sysfs 实战

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

Linux 内核文档 Documentation/admin-guide/RAS/main.rst 系统阐述了面向服务器的可靠性(Reliability)、可用性(Availability)与可服务性(Serviceability,合称 RAS)在内核中的实现:从硬件错误的分类与 ECC 纠错原理,到内核 EDAC(Error Detection And Correction)子系统如何采集内存 CE/UE 错误、通过 sysfs 上报给管理程序,再到 PCI 总线奇偶校验扫描与 Intel 新架构的错误注入接口。读完本篇,你将能够理解服务器硬件错误的完整检测链路,并掌握在/sys/devices/system/edac下查看计数器、配置模块参数、定位故障 DIMM(最小可更换单元)的全部实操方法。

RAS 概念与改进手段

RAS 是衡量服务器鲁棒性的三个维度:

  • Reliability(可靠性):系统产生正确输出的概率,通常以平均故障间隔时间(MTBF)衡量,靠帮助避免、检测并修复硬件故障的特性来增强;
  • Availability(可用性):系统在任意给定时刻处于运行状态的概率,通常以一段时间内的停机百分比衡量,常借助运行时检测并纠正硬件故障的机制;
  • Serviceability(可服务性/可维护性):系统被修复或维护的简易程度与速度,通常以平均修复时间(MTBR)衡量。

为降低系统停机时间,一个具备良好 RAS 能力的系统应当能够检测硬件错误、尽可能在运行时纠正它们,同时提供硬件劣化侦测机制,在组件造成数据丢失或停机之前提醒管理员更换。文档列出的最常见监控手段包括:

  • CPU——检测指令执行及 L1/L2/L3 缓存中的错误;
  • 内存——增加 ECC 纠错逻辑以检测和纠正错误;
  • I/O——为传输的数据增加 CRC 校验;
  • 存储——RAID、日志文件系统、校验和、SMART(Self-Monitoring, Analysis and Reporting Technology)。

通过监控错误发生次数的趋势,可以判断硬件错误概率是否在上升;若如此,就应在这些错误仍属可纠正的阶段进行预防性维护,更换正在劣化的组件。

错误分类:CE、UE、Fatal 与 Non-fatal

现代系统大多采用汉明码(Hamming Code)一类的技术,当一组比特中的错误数低于阈值时可以纠错;超过阈值时则能高置信度地判定“出错了”却无法纠正。另外,错误也可能发生在未被使用的组件上(例如尚未分配的内存)。由此形成四类错误:

  • Correctable Error(CE,可纠正错误):检测机制发现并纠正了错误,通常不致命,但某些内核机制允许管理员将其视为致命;
  • Uncorrectable Error(UE,不可纠正错误):错误数超过纠错阈值,系统无法自动纠正;
  • Fatal Error(致命错误):UE 发生在系统关键组件上(例如内核自身被 UE 破坏),此时唯一可靠的避免数据损坏的方式是挂起或重启机器;
  • Non-fatal Error(非致命错误):UE 发生在未使用的组件上(如处于断电状态的 CPU、未使用的内存 bank),系统可能仍能运行,甚至可用热备件替换受影响硬件;若错误发生在用户态进程,也可以杀掉该进程让其重启。

非致命错误的处理机制通常较复杂,可能需要用户态应用配合,以执行管理员期望的策略。

定位故障硬件:指向最小可更换单元(MRU)

仅仅检测到硬件缺陷通常是不够的:系统需要定位到应当更换的最小可更换单元(Minimal Replaceable Unit, MRU),才能让硬件恢复可靠。这要求不仅有错误记录能力,还要能把错误消息翻译成主板丝印或组件标签。

以内存为例,由于现代 CPU 会将不同内存条的数据交叉(interlace)以提升性能,定位非常复杂。DMI BIOS 通常保存有内存模块标签列表,可用dmidecode工具查看。例如某台桌面机器的输出:

Memory Device Total Width: 64 bits Data Width: 64 bits Size: 16384 MB Form Factor: SODIMM Set: None Locator: ChannelA-DIMM0 Bank Locator: BANK 0 Type: DDR4 Type Detail: Synchronous Speed: 2133 MHz Rank: 2 Configured Clock Speed: 2133 MHz

上例中这块 DDR4 SO-DIMM 位于bank locator字段标示的 "BANK 0"。注意其total width等于data width,意味着该内存模块没有纠错机制。

而在另一台较老的服务器上,dmidecode输出可能是:

Memory Device Array Handle: 0x1000 Error Information Handle: Not Provided Total Width: 72 bits Data Width: 64 bits Size: 8192 MB Form Factor: DIMM Set: 1 Locator: DIMM_A1 Bank Locator: Not Specified Type: DDR3 Type Detail: Synchronous Registered (Buffered) Speed: 1600 MHz Rank: 2 Configured Clock Speed: 1600 MHz

此例中 DDR3 RDIMM 位于locator字段标示的 "DIMM_A1"。该模块data width为 64 位、total width为 72 位,多出的 8 位用于检错/纠错——这类内存即ECC 内存。更麻烦的是,不同丝印标签的主板可能使用完全相同的 BIOS,导致 BIOS 给出的标签与实物不符。

ECC 内存的工作原理

ECC 内存的额外位用于纠错。以上例 64 位数据 + 72 位总宽为例,多出的 8 位用于检错/纠错,称为syndrome(校验子)

写路径:当 CPU 请求内存控制器写入一个data width宽度的字时,内存控制器实时用汉明码或其他纠错码(如 SECDED+)计算 syndrome,生成total width大小的码字写入内存模块。

读路径:读回total width比特后用相同 ECC 码还原,得到一个data width宽度的字和 syndrome;即使发生错误,数据字也会被送往 CPU。内存控制器同时检查 syndrome 判断是否发生错误、以及 ECC 是否成功纠正:纠正成功即 CE,纠正失败即 UE。

CE/UE 信息保存在内存控制器的特殊寄存器中,可经 BIOS、特定 CPU 或 Linux EDAC 驱动读取;在 x86 64 位 CPU 上,这些错误还能通过 Machine Check Architecture(MCA)获取,详见内核文档 arch/x86/x86_64/machinecheck.rst。

两种值得注意的特殊内存模式(原文脚注):

  • Lock-Step(锁步)模式:部分内存控制器可将两个内存模块编组、以 128 位读/写工作,从而提供 16 位纠错能力,显著提升纠错效果;代价是一旦出错无法确定是哪块模块的错,只能同时归咎两块模块;
  • Mirror(镜像)模式:同一数据写入两块模块,读时比对一致性。出错时同样无法定位单块模块,只能归咎两块(若同时处于 Lock-step 模式则归咎四块)。

EDAC 子系统:目标与组成

历史背景:该驱动子系统在树外维护时期名为 "bluesmoke"(原网站现已陈旧,仅供历史参考);当它在 2.6.16 内核首次推送上游时,被改名为EDAC

EDAC 在当前内核源码中位于 drivers/edac 目录,核心由edac_mc内存控制器模块与众多具体的 Memory Controller(MC)驱动组成,例如 amd76x_edac.c、amd64_edac.c、i7core_edac.c、sb_edac.c 等。

内存错误采集(edac_mc)

内存的 CE/UE 是 EDAC 采集的首要错误类型,由edac_mc设备负责。需要强调文档中的重要告诫:CE 事件的采集与上报“可以”但并非必然地预示未来 UE 事件——仅有 CE 时系统可以且会继续正常运行,因为数据尚未损坏。不过,对表现出 CE 的内存模块做预防性维护和主动更换,确实能降低出现 UE 和系统宕机的概率。

其他硬件元素(edac_device)

2.6.23 版本内核引入了新的edac_device设备类(实现见 drivers/edac/edac_device.c)。它让非内存类的 ECC 硬件检测器——如 L1/L2/L3 缓存 ECC 检测器、DMA 引擎、fabric 交换、主数据通路交换、互连等——也能把状态经 sysfs 呈现给用户态。只要硬件有上报,通常就可以构造一个 edac_device 来采集并呈现。

PCI 总线扫描

EDAC 还会扫描 PCI 设备的 Bus Parity 与 SERR 错误,判断数据传输期间是否发生错误。PCI Parity 错误须谨慎看待:PCI 规范要求厂商若不打算产生奇偶校验,应把奇偶状态位系到 0;但有些厂商不这样做,导致奇偶位“浮空”产生假阳性。EDAC 的 PCI 扫描代码会检查 sysfs 中的 PCI 设备属性:

broken_parity_status

它位于/sys/devices/pci<XXX>/0000:XX:YY.Z目录下,该属性置位后,对应设备将跳过 PCI 奇偶/错误扫描。当前源码中,奇偶校验检查入口与pci_parity_count计数器的维护逻辑分别位于 drivers/edac/edac_pci.c 与 drivers/edac/edac_pci_sysfs.c。

版本号与模块加载

EDAC 由一个"核心"模块(原文称edac_core.ko,从当前源码树结构看,核心模块由 drivers/edac/edac_mc.c 构建)和若干 MC 驱动模块组成。在给定系统上,核心被加载后只加载一个 MC 驱动;核心与 MC 驱动(或 edac_device 驱动)各有独立版本号,因此报告系统运行版本时须同时报告两者。

edac静态链接进内核则无需加载;若构建成模块,直接 modprobe 所需部件即可,加载硬件特定模块时依赖会自动带出核心模块。例如:

$ modprobe amd76x_edac

该命令会同时加载amd76x_edac.ko内存控制器模块和edac_mc.ko核心模块。

sysfs 接口总览

EDAC 提供位于/sys/devices/system/edac的 sysfs 接口用于控制与上报。该目录下有两个主要组件:

组件说明
mc内存控制器系统
pciPCI 控制与状态系统

完整的 sysfs 属性语义(含各文件的用途说明)定义在 ABI 文档 Documentation/ABI/testing/sysfs-devices-edac 中,建议配合阅读。

Memory Controller(mc)模型

每个mc设备控制一组内存模块。模块按Chip-Select Row(csrowXChannel 表(chX布局,可以有多个 csrow 和多个通道。典型系统有 8 个 csrow,但实际数量取决于主板布局、内存控制器与内存模块特性。

双通道允许双数据宽度(如 64 位系统上的 128 位)对 CPU 读写内存;部分新芯片组(如 FB-DIMM 内存控制器)支持更多通道。以 2 通道为例,模块布局如下:

+------------+-----------------------+ | CS Rows | Channels | +------------+-----------+-----------+ | | ch0 | ch1 | +============+===========+===========+ | |**DIMM_A0**|**DIMM_B0**| +------------+-----------+-----------+ | csrow0 | rank0 | rank0 | +------------+-----------+-----------+ | csrow1 | rank1 | rank1 | +------------+-----------+-----------+ | |**DIMM_A1**|**DIMM_B1**| +------------+-----------+-----------+ | csrow2 | rank0 | rank0 | +------------+-----------+-----------+ | csrow3 | rank1 | rank1 | +------------+-----------+-----------+

对应主板上 4 个物理 DIMM 槽位:

+---------+---------+ | DIMM_A0 | DIMM_B0 | +---------+---------+ | DIMM_A1 | DIMM_B1 | +---------+---------+

槽位标签通常丝印在主板上:A槽是通道 0,B槽是通道 1。注意一个物理 DIMM 可能对应两个 csrow——csrow 的分配基于 DIMM 所插入的槽位,因此每个通道各插 1 条 DIMM 时,csrow 会横跨两条 DIMM。

内存 DIMM 分单 rank 和双 rank,一个 rank 即一个被占用的 csrow。例如两条双 rank DIMM 分别插到 DIMM_A0/DIMM_B0 与 DIMM_A1/DIMM_B1 时,csrow0、csrow1 均被占用;若两条单 rank DIMM 只插在 DIMM_A0/DIMM_B0,则只有 csrow0 被占用,csrow1 为空。另外,有些内存控制器没有任何识别内存模块的逻辑,对应 sysfs 目录见下文rankX

sysfs 目录树中,/sys/devices/system/edac/mc下每个内存控制器以mcX目录表示(X 为 MC 索引):

..../edac/mc/ | |->mc0 |->mc1 |->mc2 ....

术语说明(原文脚注):如今 DIMM(Dual In-line Memory Module)被广泛用来指代内存模块,但还有 SO-DIMM、SIMM 等封装形式。UEFI 规范(2.7 版)在 CPER(Common Platform Error Record)一节将内存模块定义为 SMBIOS Memory Device(Type 17)。本文档与 EDAC 子系统内部统一用 "dimm" 指代所有内存模块,不论其封装形式。

推荐的查看方式:dimmX / rankX 目录

使用 EDAC 子系统的推荐方式是查看dimmXrankX目录提供的信息。典型 EDAC 系统下/sys/devices/system/edac/的结构如下(其中power目录与subsystem符号链接由 sysfs 子系统自动创建,目前无实际用途):

/sys/devices/system/edac/ ├── mc │ ├── mc0 │ │ ├── ce_count │ │ ├── ce_noinfo_count │ │ ├── dimm0 │ │ │ ├── dimm_ce_count │ │ │ ├── dimm_dev_type │ │ │ ├── dimm_edac_mode │ │ │ ├── dimm_label │ │ │ ├── dimm_location │ │ │ ├── dimm_mem_type │ │ │ ├── dimm_ue_count │ │ │ ├── size │ │ │ └── uevent │ │ ├── max_location │ │ ├── mc_name │ │ ├── reset_counters │ │ ├── seconds_since_reset │ │ ├── size_mb │ │ ├── ue_count │ │ ├── ue_noinfo_count │ │ └── uevent │ ├── mc1 │ │ ├── ce_count │ │ ├── ce_noinfo_count │ │ ├── dimm0 │ │ │ ├── dimm_ce_count │ │ │ ├── dimm_dev_type │ │ │ ├── dimm_edac_mode │ │ │ ├── dimm_label │ │ │ ├── dimm_location │ │ │ ├── dimm_mem_type │ │ │ ├── dimm_ue_count │ │ │ ├── size │ │ │ └── uevent │ │ ├── max_location │ │ ├── mc_name │ │ ├── reset_counters │ │ ├── seconds_since_reset │ │ ├── size_mb │ │ ├── ue_count │ │ ├── ue_noinfo_count │ │ └── uevent │ └── uevent └── uevent

dimmX目录包含该内存模块的控制与属性文件:

  • size——该 csrow 管理的内存总量,以 MB 为单位显示;
  • dimm_ue_count——该 DIMM 上发生的不可纠正错误总计数。若panic_on_ue置位,此计数将没有机会增长,因为 EDAC 会让系统 panic;
  • dimm_ce_count——该 DIMM 上发生的可纠正错误总计数。这是最值得重点关注的字段:CE 是 DIMM 开始失效的早期信号,应监控其非零值并把信息报告给系统管理员;
  • dimm_dev_type——该 DIMM 上使用的 DRAM 器件类型,取值如x1x2x4x8。从源码 drivers/edac/edac_mc_sysfs.c 可见,dev_types表实际覆盖x1x64
  • dimm_edac_mode——正在使用的检错/纠错类型。源码 drivers/edac/edac_mc_sysfs.c 中的edac_caps表列出的可能取值包括:NonePARITYECSECDEDS2ECD2EDS4ECD4EDS8ECD8EDS16ECD16ED
  • dimm_label——内存模块标签控制文件(可写)。为该 DIMM 赋予标签后,错误发生时系统日志中可输出 DIMM 标签,这在 panic 事件中定位 UE 根因至关重要。注意标签须在启动后、用与主板丝印标签一致的信息在用户态分配,因为该信息目前非常依赖主板型号;
  • dimm_location——内存模块位置,最多 3 级,描述内存控制器如何识别模块位置,依内存与控制器类型不同而不同:
    • csrow+channel——内存控制器无法识别单条 DIMM 时使用,对应rankX目录;
    • branch+channel+slot——FB-DIMM 内存控制器常见;
    • channel+slot——Nehalem 及更新 Intel 驱动所用;
  • dimm_mem_type——该 csrow 上的内存类型,通常为 buffered 或 unbuffered,例如Registered-DDRUnbuffered-DDR

关于dimmXrankX的区别(原文脚注):当内存控制器没有任何识别内存模块的逻辑时,目录名为rankX;在现代 Intel 内存控制器上,控制器能直接识别内存模块,目录名为dimmX

系统日志消息格式

若启用了 UE/CE 日志,系统日志将包含错误检测信息,例如:

EDAC MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0, channel 1 "DIMM_B1": amd76x_edac EDAC MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0, channel 1 "DIMM_B1": amd76x_edac

消息结构如下:

内容示例
内存控制器MC0
错误类型CE
内存页0x283
页内偏移0xce0
错误的字节粒度/分辨率grain 8
错误 syndrome0xb741
内存行row 0
内存通道channel 1
DIMM 标签(若事先设置)DIMM B1
可选的驱动特定附加信息

所有信息缺失(no info)的 UE 与 CE,消息中只保留内存控制器、错误类型、"no info" 提示及可选的驱动特定错误消息。

PCI Bus Parity 检测

对 Header Type 00 的设备,无论奇偶校验是否启用,都会检查主状态寄存器(规范指明某些情况下会生成奇偶);对 Header Type 01 桥,还会检查次级状态寄存器,判断桥另一侧的总线上是否发生了奇偶错误。

/sys/devices/system/edac/pci下有如下控制与属性文件:

  • check_pci_parity——启用/禁用 PCI Parity 扫描。写1启用,写0禁用:
# Enable echo "1" >/sys/devices/system/edac/pci/check_pci_parity # Disable echo "0" >/sys/devices/system/edac/pci/check_pci_parity
  • pci_parity_count——显示已检测到的奇偶错误数。当前源码中该计数器在 drivers/edac/edac_pci_sysfs.c 中以原子变量维护,每次扫描发现奇偶错误时自增。

模块参数

EDAC 核心暴露以下模块参数(定义于 drivers/edac/edac_mc_sysfs.c,均可在加载时与运行时调整)。

edac_mc_panic_on_ue —— UE 时 panic

发生不可纠正错误时将引发机器 panic,这通常是期望的行为——UE 之后继续运行是坏主意:无法确定什么数据未被纠正,操作系统上下文可能已严重错乱,继续运行会导致进一步损坏。若内核配置了 MCE,则 EDAC 根本不会"注意到"该 UE(MCE 会先处理)。

  • 加载时:module/kernel parameter: edac_mc_panic_on_ue=[0|1]
  • 运行时:echo "1" > /sys/module/edac_mc/parameters/edac_mc_panic_on_ue

edac_mc_log_ue —— UE 日志开关

生成描述不可纠正错误的内核消息(经系统消息日志上报)。即使禁用 UE 日志,UE 统计仍会累积。源码默认值为 1(开启日志)。

  • 加载时:edac_mc_log_ue=[0|1]
  • 运行时:echo "1" > /sys/module/edac_mc/parameters/edac_mc_log_ue

edac_mc_log_ce —— CE 日志开关

生成描述可纠正错误的内核消息。同样,即使禁用 CE 日志,CE 统计仍会累积。默认值 1。

  • 加载时:edac_mc_log_ce=[0|1]
  • 运行时:echo "1" > /sys/module/edac_mc/parameters/edac_mc_log_ce

edac_mc_poll_msec —— 轮询周期

轮询错误信息的周期,单位毫秒。值太小浪费资源,太大可能延迟必要的错误处理、丢失定位错误所需的信息。当前默认 1000 ms(每秒一次),对带宽要求极苛刻的系统可以适当调大。源码默认值即 1000(见 drivers/edac/edac_mc_sysfs.c),且设置函数edac_set_poll_msec会拒绝小于 1000 的值(drivers/edac/edac_mc_sysfs.c),即最小可配置周期为 1000 ms

  • 加载时:edac_mc_poll_msec=<毫秒值>
  • 运行时:echo "1000" > /sys/module/edac_mc/parameters/edac_mc_poll_msec

edac_panic_on_pci_pe —— PCI 奇偶错误时 panic

检测到奇偶错误时是否 panic:

# module/kernel parameter edac_panic_on_pci_pe=[0|1] # Enable echo "1" > /sys/module/edac_mc/parameters/edac_panic_on_pci_pe # Disable echo "0" > /sys/module/edac_mc/parameters/edac_panic_on_pci_pe

说明:原文档将该参数列于edac_core模块下;从当前源码树看,MC 相关参数集中声明于edac_mc模块中,而 PCI 奇偶相关的属性与计数逻辑位于edac_pci*源文件。实际使用时请以所在系统/sys/module/下真实存在的参数文件为准。

EDAC device 类型:三层树状 sysfs

drivers/edac/edac_pci.h(原文所述头文件)及 edac_device 相关头文件中有一系列edac_device结构与 API。用户态通过 sysfs 访问 edac_device:新设备会出现在/sys/devices/system/edac下,其下是一个三层目录树

以测试驱动test_device_edac为例,它注册为:

/sys/devices/system/edac/test-instance

该目录下有各种控制项、一个符号链接和一个或多个instance目录。标准默认控制项:

控制项说明
log_ce是否记录 CE 事件(布尔)
log_ue是否记录 UE 事件(布尔)
panic_on_ue遇到 UE 时是否 panic(默认 off,可在启动脚本中置 true)
poll_msec事件 POLL 周期

test_device_edac还会添加至少一个自定义控制:test_bits——在当前测试驱动中不产生任何实际作用,仅演示如何安装控制/属性;移植驱动可添加一个或多个这样的控制项(例如某些树外驱动在此暴露 ERROR INJECTION 控制,用于向硬件注入寄存器写入错误)。符号链接指向该 edac_device 注册的struct dev

Instance 层

存在一个或多个 instance 目录,如test-instance0。其中有两个默认计数器属性,为更深层子目录计数之和:

属性说明
ce_count子目录 CE 事件总数
ue_count子目录 UE 事件总数

Block 层

最底层目录是block,每个 instance 可包含 0、1 个或多个 block,如test-block0。默认属性:

属性说明
ce_count该块被监控硬件的 CE 事件计数
ue_count该块被监控硬件的 UE 事件计数

test_device_edac另添加 4 个属性和 1 个控制:

  • test-block-bits-0——每个 POLL 周期递增一次;
  • test-block-bits-1——每 10 个周期递增一次,同时将 bits-0 清零;
  • test-block-bits-2——每 100 个周期递增一次,同时将 bits-1 清零;
  • test-block-bits-3——每 1000 个周期递增一次,同时将 bits-2 清零;
  • reset-counters——向该控制写任何内容都会重置上述全部计数器。

test_device_edac样例驱动的意义在于:让其他开发者可以仿照它为各自硬件编写独特的 edac_device 驱动。

Intel Nehalem 及更新架构上的 EDAC API 用法

在较老的 Intel 架构上,内存控制器属于 North Bridge 芯片组;从 Nehalem、Sandy Bridge、Ivy Bridge、Haswell、Sky Lake 到更新架构,增强版内存控制器(MC)被集成进 CPU 内部。本节(对应驱动如i7core_edacsb_edacsbx_edac,源码分别为 i7core_edac.c、sb_edac.c)描述这些增强 MC 的差异。

注意:Xeon E7 处理器家族使用独立的内存控制器芯片——Intel Scalable Memory Buffer,本节不适用于这些家族。

1) 通道与 DIMM 到 csrow 的映射

每个 Quick Path Interconnect(QPI)对应一个内存控制器;驱动中 "socket" 一词指一个 QPI,关联一个物理 CPU 插座。每个 MC 有 3 个物理读通道、3 个物理写通道和 3 个逻辑通道,驱动当前将其视作 3 个通道,每个通道最多可插 3 条 DIMM。

最小的已知单元是 DIMM,没有任何 csrow 信息;由于 EDAC API 把最小单元映射为 csrow,驱动按序把 channel/DIMM 映射到不同 csrow。例如以下布局:

Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400 dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400 Ch1 phy rd1, wr1 (0x063f4031): 2 ranks, UDIMMs dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400 Ch2 phy rd3, wr3 (0x063f4031): 2 ranks, UDIMMs dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400

驱动将映射为:

csrow0: channel 0, dimm0 csrow1: channel 0, dimm1 csrow2: channel 1, dimm0 csrow3: channel 2, dimm0

即每个 csrow 导出一条 DIMM,且每个 QPI 作为独立内存控制器导出。

2) 错误注入节点

新 MC 具备错误注入能力用于测试驱动。驱动通过/sys/devices/system/edac/mc/mc?/下的一组 sysfs 节点实现(如 i7core_edac.c、amd64_edac.c 中实现的inject_*属性,Kconfig 说明见 drivers/edac/Kconfig):

  • inject_addrmatch/*:控制错误注入的地址匹配掩码寄存器,可指定多个地址特征以匹配错误:

    • dimm——受影响的 dimm(编号相对通道);
    • rank——内存 rank;
    • channel——将产生错误的通道;
    • bank——受影响的 bank;
    • page——页地址;
    • column(或col)——地址列。

    以上每个值均可设为any以匹配任意合法值;驱动初始化时全部为 any。例如在 dimm 2 的 rank 1 上生成错误(任意通道、bank、页、列):

    echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm echo 1 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank

    恢复默认"任意匹配"行为:

    echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
  • inject_eccmask:指定哪些比特将出错;

  • inject_section:指定哪个 ECC cache 段发生错误:3表示两段都、2表示最高段、1表示最低段;

  • inject_type:指定错误类型,为以下位组合——bit 0: repeat、bit 1: ecc、bit 2: parity;

  • inject_enable:写入非 0 值即启动错误生成。

所有 inject 变量均可读;写需要 root 权限。数据手册声明错误仅在向匹配inject_addrmatch的地址执行写操作后生成,但实际观察中读操作也会产生错误

完整示例——在 socket 0、通道 2 上对任意 DIMM/地址的写访问生成错误:

echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/channel echo 2 >/sys/devices/system/edac/mc/mc0/inject_type echo 64 >/sys/devices/system/edac/mc/mc0/inject_eccmask echo 3 >/sys/devices/system/edac/mc/mc0/inject_section echo 1 >/sys/devices/system/edac/mc/mc0/inject_enable dd if=/dev/mem of=/dev/null seek=16k bs=4k count=1 >& /dev/null

对 socket 1,把上述命令中的mc0替换为mc1。生成的错误消息形如:

EDAC MC0: UE row 0, channel-a= 0 channel-b= 0 labels "-": NON_FATAL (addr = 0x0075b980, socket=0, Dimm=0, Channel=2, syndrome=0x00000040, count=1, Err=8c0000400001009f:4000080482 (read error: read ECC error))

3) Corrected Error 内存寄存器计数器

新 MC 提供若干计数内存错误的寄存器,驱动使用它们为 Registered DIMM 上报 CE。但这些计数器对 Unregistered DIMM(UDIMM)无效;由于芯片组另有一些对 UDIMM 也有效(但粒度不如默认计数器精细)的计数器,驱动为 UDIMM 内存暴露了这些寄存器,通过all_channel_counts/读取:

$ for i in /sys/devices/system/edac/mc/mc0/all_channel_counts/*; do echo $i; cat $i; done /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm0 0 /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm1 0 /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm2 0

其工作方式是:不同 csrow 但相同 dimm 编号上的错误会递增同一个计数器。在上文的内存映射(csrow0: channel 0 dimm0;csrow1: channel 0 dimm1;csrow2: channel 1 dimm0;csrow3: channel 2 dimm0)下:csrow0/csrow2/csrow3 上第一条 dimm 的错误都会递增udimm0,第二条 dimm 递增udimm1,第三条递增udimm2

4) 标准错误计数器

标准错误计数器在驱动收到 mcelog 错误时生成。由于 UDIMM 情形下这是由软件计数的,可能丢失部分错误;RDIMM 情形下则直接显示寄存器内容。

amd64_edac 的参考文档

amd64_edac模块(源码 drivers/edac/amd64_edac.c)基于 AMD 官方 BKDG(BIOS and Kernel Developer's Guide)文档,原文档列出的参考包括(可通过 AMD 技术支持站点检索,此处不附外部链接):

  1. BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD Opteron Processors(AMD 出版物 26094,Rev 3.26);
  2. BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors(出版物 32559,Rev 3.00,2006 年 5 月);
  3. BKDG For AMD Family 10h Processors(出版物 31116,Rev 3.00,2007 年 9 月 7 日);
  4. BKDG for AMD Family 15h Models 30h-3Fh Processors(出版物 49125,Rev 3.06,2015 年 2 月 12 日);
  5. BKDG for AMD Family 15h Models 60h-6Fh Processors(出版物 50742,Rev 3.01,2015 年 7 月 23 日);
  6. BKDG for AMD Family 16h Models 00h-0Fh Processors(出版物 48751,Rev 3.03,2015 年 2 月 23 日)。

实操速查与小结

场景操作
查看某 DIMM 的 CE 计数(早期失效信号)cat /sys/devices/system/edac/mc/mc0/dimm0/dimm_ce_count
为 DIMM 写丝印标签以便 panic 定位dimm_label写入与主板丝印一致的标签
重置 mc 计数器reset_counters
调整错误轮询周期(≥1000 ms)echo 2000 > /sys/module/edac_mc/parameters/edac_mc_poll_msec
UE 时立即 panicecho 1 > /sys/module/edac_mc/parameters/edac_mc_panic_on_ue
开启/关闭 PCI 奇偶扫描/sys/devices/system/edac/pci/check_pci_parity1/0
排除坏奇偶状态设备确认该设备broken_parity_status属性
Intel 新架构注入测试错误配置mc?/inject_*节点后触发匹配地址访问

RAS 与 EDAC 的完整脉络可总结为:硬件(ECC/MCA/PCI 奇偶)产生错误信号 → 内核 EDAC 核心(edac_mc/edac_pci/edac_device)经 MC 驱动采集 → 通过/sys/devices/system/edac下的计数器与日志消息上报 → 用户态监控 CE 趋势、写入 DIMM 标签、调整 panic/日志/轮询策略,最终定位 MRU 完成预防性维护。相关文档入口为 Documentation/admin-guide/RAS/index.rst(含本主题及错误解码、地址翻译等子文档),属性语义权威定义见 Documentation/ABI/testing/sysfs-devices-edac,x86 平台的 MCA 细节见 arch/x86/x86_64/machinecheck.rst。

(原文档作者:Doug Thompson;Nehalem 接口部分由 Mauro Carvalho Chehab 增补并完成 ReST 转换;EDAC 作者/维护者还包括 Dave Jiang、Dave Peterson、Borislav Petkov,原始作者为 Thayne Harbaugh。)

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 15:50:03

Triton 自动调优上手:让 GPU 内核自己挑最快的那套参数

Triton 自动调优上手&#xff1a;让 GPU 内核自己挑最快的那套参数 【免费下载链接】triton Development repository for the Triton language and compiler 项目地址: https://gitcode.com/GitHub_Trending/tri/triton 写过 GPU 内核的人都遇到过这种场面&#xff1a;周…

作者头像 李华
网站建设 2026/9/7 15:49:55

NVIDIA AGX Xavier开发板原理图深度解析与调试实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 15:49:00

Git Hooks 实战:用 husky + lint-staged 实现提交前 ESLint 与 Prettier 自动校验

1. 为什么偏要在 commit 之前加一道拦截门先说个特别常见的尴尬场景&#xff1a;本地写完代码&#xff0c;git commit的时候也没做检查&#xff0c;推到远端后 CI 开始跑 lint 和类型检查&#xff0c;结果红灯亮了。你看着那一长串报错&#xff0c;心里其实很清楚——这个问题在…

作者头像 李华
网站建设 2026/9/7 15:48:52

FileZilla Server全栈实操:从安装到端口映射与权限管理

只要碰过服务器文件备份、公司资料交接、网站目录维护这类活儿&#xff0c;FileZilla这个名字一定绕不开。但很多人对它的印象只停留在“一个FTP客户端”&#xff0c;需要下载文件时打开连一下&#xff0c;完事就关掉。这其实浪费了FileZilla最大的一层价值——它根本不是单一软…

作者头像 李华
网站建设 2026/9/7 15:48:47

服务器安全基线核查脚本实战:Linux与Windows检查项设计与排错

简介&#xff1a;面向运维安全人员的Windows与Linux基线核查脚本资源包&#xff0c;用于帮助企业IT、安全运维及等保合规建设人员快速完成系统安全配置检查。包内整合了Windows与Linux两套核查脚本、配套基线配置文档、配置文件、结果导出报表以及常见报错处理指南&#xff0c;…

作者头像 李华