可靠性、可用性和可服务性 (RAS)

本文档介绍了内核中存在的 RAS 功能的不同方面。

RAS 概念

可靠性、可用性和可服务性 (RAS) 是一个用于服务器的概念,旨在衡量其稳健性。

可靠性 (Reliability)

是系统产生正确输出的概率。

  • 通常以平均无故障时间 (MTBF) 来衡量

  • 通过有助于避免、检测和修复硬件故障的功能来增强

可用性 (Availability)

是系统在给定时间处于运行状态的概率

  • 通常以一段时间内停机时间的百分比来衡量

  • 通常使用在运行时检测和纠正硬件故障的机制;

可服务性 (Serviceability,或可维护性)

是系统修复或维护的简单程度和速度

  • 通常按平均修复时间 (MTBR) 衡量

提高 RAS

为了减少系统停机时间,系统应该能够检测硬件错误,并在可能的情况下在运行时纠正它们。它还应提供检测硬件老化的机制,以便警告系统管理员在导致数据丢失或系统停机之前采取更换组件的操作。

在监测措施中,最常见的包括

  • CPU – 检测指令执行以及 L1/L2/L3 缓存中的错误;

  • 内存 – 添加纠错逻辑 (ECC) 以检测和纠正错误;

  • I/O – 为传输的数据添加 CRC 校验和;

  • 存储 – RAID、日志文件系统、校验和、自我监控、分析和报告技术 (SMART)。

通过监控错误检测的发生次数,可以识别硬件错误的概率是否正在增加,在这种情况下,可以进行预防性维护,在这些错误尚可纠正时更换老化的组件。

错误类型

现代系统中使用的大多数机制都使用汉明码 (Hamming Codes) 等技术,这些技术允许在位包错误数低于阈值时进行纠错。如果错误数超过阈值,这些机制可以以高度置信度指示发生了错误,但无法纠正。

此外,有时错误发生在未使用的组件上。例如,当前未分配的一块内存。

这定义了一些错误类别

  • 可纠正错误 (CE) - 错误检测机制检测并纠正了错误。此类错误通常不是致命的,尽管某些内核机制允许系统管理员将其视为致命错误。

  • 不可纠正错误 (UE) - 发生的错误数量超过了纠错阈值,系统无法自动纠正。

  • 致命错误 (Fatal Error) - 当 UE 错误发生在系统的关键组件上时(例如,内核的一部分被 UE 损坏),避免数据损坏的唯一可靠方法是挂起或重启机器。

  • 非致命错误 (Non-fatal Error) - 当 UE 错误发生在未使用的组件(如处于断电状态的 CPU 或未使用的内存库)上时,系统可能仍会运行,最终通过热备件(如果有)更换受影响的硬件。

    此外,当用户空间进程发生错误时,也可以终止该进程并让用户空间重新启动它。

处理非致命错误的机制通常很复杂,可能需要一些用户空间应用程序的帮助,以便应用系统管理员所需的策略。

识别坏的硬件组件

仅检测硬件缺陷通常是不够的,因为系统需要精确指向应更换的最小可更换单元 (MRU),以使硬件再次可靠。

因此,它不仅需要错误日志记录设施,还需要将错误消息转换为 MRU 的丝网印刷或组件标签的机制。

通常,对于内存来说非常复杂,因为现代 CPU 会交错来自不同内存模块的内存,以提供更好的性能。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 0”,如 bank locator 字段所示。请注意,在这样的系统上,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 内存模块位于系统内存中,标记为“DIMM_A1”,如 locator 字段所示。请注意,此内存模块的 data width 为 64 位,total width 为 72 位。因此,它有 8 个额外的位供错误检测和纠正机制使用。这种内存被称为纠错码内存 (ECC memory)。

更糟糕的是,板卡上带有不同标签的系统使用完全相同的 BIOS 并不罕见,这意味着 BIOS 提供的标签将与实际标签不匹配。

ECC 内存

如前一节所述,ECC 内存具有用于纠错的额外位。在上面的示例中,内存模块的 data width 为 64 位,total width 为 72 位。用于错误检测和纠正机制的额外 8 位被称为 syndrome (校验子)[1][2]

因此,当 CPU 请求内存控制器写入一个具有 data width 大小的字时,内存控制器使用汉明码或其他纠错码(如 SECDED+)实时计算 syndrome,生成一个 total width 大小的码。然后该码被写入内存模块。

读取时,total width 位的码被转换回来,使用写入时使用的相同 ECC 码,产生一个 data width 的字和一个 syndrome。即使发生错误,data width 的字也会被发送到 CPU。

内存控制器还会查看 syndrome 以检查是否存在错误,以及 ECC 码是否能够修复该错误。如果错误已纠正,则发生了可纠正错误 (CE)。如果没有,则发生了不可纠正错误 (UE)。

有关 CE/UE 错误的信息存储在内存控制器的一些特殊寄存器中,可以通过读取这些寄存器进行访问,访问方式可以是 BIOS、某些特殊的 CPU 或 Linux EDAC 驱动程序。在 x86 64 位 CPU 上,此类错误也可以通过机器检查架构 (MCA) 获取[3]

EDAC - 错误检测和纠正

注意

“bluesmoke” 是该设备驱动程序子系统在“树外”并在 http://bluesmoke.sourceforge.net 维护时的名称。该站点现在大多已过时,仅供参考。

当该子系统首次推送到上游内核 2.6.16 时,它被重命名为 EDAC

目的

edac 内核模块的目标是检测并报告运行在 linux 下的计算机系统中发生的硬件错误。

内存

内存可纠正错误 (CE) 和不可纠正错误 (UE) 是采集的主要错误。这些类型的错误由 edac_mc 设备采集。

检测 CE 事件,然后采集并报告这些事件,可以但并不一定能预测未来的 UE 事件。仅发生 CE 事件时,系统可以且将继续运行,因为数据尚未损坏。

然而,对表现出 CE 的内存模块进行预防性维护和主动部件更换,可以降低发生可怕的 UE 事件和系统崩溃 (panic) 的可能性。

其他硬件元素

EDAC 的一个新功能,即 edac_device 类设备,在内核 2.6.23 版本中添加。

这种新的设备类型允许非内存类型的 ECC 硬件检测器将其状态采集并通过 sysfs 界面呈现给用户空间。

某些架构具有 L1、L2 和 L3 缓存的 ECC 检测器,以及 DMA 引擎、结构交换机、主数据路径交换机、互连和各种其他硬件数据路径。如果硬件报告它,那么可能可以构建一个 edac_device 设备来采集并呈现给用户空间。

PCI 总线扫描

此外,还会扫描 PCI 设备以查找 PCI 总线奇偶校验错误和 SERR 错误,以便确定数据传输过程中是否发生了错误。

必须以审慎的态度对待 PCI 奇偶校验错误的存在。有几个附加适配器在奇偶校验生成和报告方面遵循 PCI 规范。规范说,如果供应商不打算生成奇偶校验,则应将奇偶校验状态位绑定为 0。一些供应商不这样做,因此奇偶校验位可能会“漂移”产生误报。

在 sysfs 中有一个由 EDAC PCI 扫描代码检查的 PCI 设备属性。如果设置了该属性,则跳过该设备的 PCI 奇偶校验/错误扫描。该属性是:

broken_parity_status

并且位于 PCI 设备的 /sys/devices/pci<XXX>/0000:XX:YY.Z 目录中。

版本控制

EDAC 由一个“核心”模块 (edac_core.ko) 和几个内存控制器 (MC) 驱动模块组成。在给定的系统上,将加载 CORE 和一个 MC 驱动程序。CORE 和 MC 驱动程序 (或 edac_device 驱动程序) 都有反映其各自模块当前发布级别的单独版本。

因此,要“报告”系统正在运行的版本,必须同时报告 CORE 和 MC 驱动程序的版本。

加载

如果 edac 是静态链接到内核的,则无需加载。如果 edac 是作为模块构建的,则只需 modprobe 您需要的 edac 部分。您应该能够 modprobe 特定硬件的模块,并由依赖项加载必要的核心模块。

示例

$ modprobe amd76x_edac

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

Sysfs 接口

EDAC 提供了一个用于控制和报告目的的 sysfs 接口。它位于 /sys/devices/system/edac 目录中。

目前该目录下有两个组件:

mc

内存控制器系统

pci

PCI 控制和状态系统

内存控制器 (mc) 模型

每个 mc 设备控制一组内存模块 [4]。这些模块排列在片选行 (csrowX) 和通道表 (chX) 中。可以有多个 csrow 和多个通道。

内存控制器允许几个 csrow,8 个 csrow 是一个典型值。然而,实际的 csrow 数量取决于给定主板的布局、内存控制器和内存模块的特性。

双通道允许在 CPU 和内存之间进行双倍数据长度(例如 64 位系统上为 128 位)的数据传输。一些较新的芯片组允许超过 2 个通道,如全缓冲 DIMM (FB-DIMM) 内存控制器。以下示例假设有 2 个通道:

片选行 (CS Rows)

通道 (Channels)

通道 0 (ch0)

通道 1 (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 所在的插槽分配其 csrow 分配。因此,当每个通道放置 1 个 DIMM 时,csrow 跨越两个 DIMM。

内存 DIMM 分为“单排”(single ranked) 或“双排”(dual ranked)。Rank 是一个已填充的 csrow。在上面的例子中,同样放置了 2 个双排 DIMM。因此,csrow0 和 csrow1 都已填充。另一方面,当在插槽 DIMM_A0 和 DIMM_B0 中放置 2 个单排 DIMM 时,它们将只有一个 csrow (csrow0),而 csrow1 将为空。这种模式在 csrow2 和 csrow3 上重复。另请注意,某些内存控制器没有任何逻辑来识别内存模块,请参阅下面的 rankX 目录。

上述表示反映在 EDAC 的 sysfs 接口的目录树中。从目录 /sys/devices/system/edac/mc 开始,每个内存控制器将由其自己的 mcX 目录表示,其中 X 是 MC 的索引:

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

在每个 mcX 目录中都有几个 EDAC 控制和属性文件。

mcX 目录

mcX 目录中,是该内存控制器 X 实例的 EDAC 控制和属性文件。

有关 sysfs API 的描述,请参阅:

dimmXrankX 目录

使用 EDAC 子系统的推荐方法是查看 dimmXrankX 目录提供的信息 [5]

一个典型的 EDAC 系统在 /sys/devices/system/edac/ 下具有以下结构 [6]

/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 目录中,是该 X 内存模块的 EDAC 控制和属性文件

  • size - 由此 csrow 属性文件管理的总内存

    此属性文件以兆字节 (MB) 为单位显示此 csrow 包含的内存量。

  • dimm_ue_count - 不可纠正错误计数属性文件

    此属性文件显示此 DIMM 上发生的不可纠正错误的总数。如果设置了 panic_on_ue,则此计数器将没有机会递增,因为 EDAC 会使系统挂起。

  • dimm_ce_count - 可纠正错误计数属性文件

    此属性文件显示此 DIMM 上发生的可纠正错误的总数。检查这个计数非常重要。CE 提供了 DIMM 开始失效的早期迹象。应对此计数字段的非零值进行监控,并向系统管理员报告此类信息。

  • dimm_dev_type - 设备类型属性文件

    此属性文件将显示此 DIMM 上使用的 DRAM 设备类型。例如:

    • x1

    • x2

    • x4

    • x8

  • dimm_edac_mode - EDAC 操作模式属性文件

    此属性文件将显示正在使用的错误检测和纠正类型。

  • dimm_label - 内存模块标签控制文件

    此控制文件允许为此 DIMM 分配标签。有了模块中的这个标签,当发生错误时,输出可以在系统日志中提供 DIMM 标签。这对于隔离 UE 事件原因的紧急事件至关重要。

    DIMM 标签必须在引导后分配,其信息应能够正确标识物理插槽及其丝网印刷标签。目前这些信息非常依赖主板,目前必须在用户空间确定这些信息。

  • dimm_location - 内存模块的位置

    位置最多可有 3 个层级,描述内存控制器如何识别内存模块的位置。取决于内存和内存控制器的类型,它可以是:

    • csrowchannel - 在内存控制器无法识别单个 DIMM 时使用 - 例如在 rankX 目录中;

    • branchchannelslot - 通常用于 FB-DIMM 内存控制器;

    • channelslot - 用于 Nehalem 及更新的 Intel 驱动程序。

  • dimm_mem_type - 内存类型属性文件

    此属性文件将显示此 csrow 上当前的内存类型。通常是缓冲 (buffered) 或无缓冲 (unbuffered) 内存。例如:

    • Registered-DDR

    • Unbuffered-DDR

系统日志

如果启用了 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

错误校验子 (syndrome)

0xb741

内存行 (row)

row 0

内存通道 (channel)

channel 1

DIMM 标签(如果之前已设置)

DIMM B1

以及一个可选的驱动程序特定消息,可能包含其他信息。

对于没有信息的 UE 和 CE,将只显示内存控制器、错误类型、“no info”提示,以及可选的驱动程序特定错误消息。

PCI 总线奇偶校验检测

对于 Header Type 00 设备,无论设备上是否启用了奇偶校验,都会查看主要状态是否存在任何奇偶校验错误。(规范指示在某些情况下会生成奇偶校验)。对于 Header Type 01 桥接器,还会查看次要状态寄存器,以查看桥接器另一侧的总线上是否发生了奇偶校验。

Sysfs 配置

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

  • check_pci_parity - 启用/禁用 PCI 奇偶校验检查控制文件

    此控制文件启用或禁用 PCI 总线奇偶校验扫描操作。向此文件写入 1 启用扫描。向此文件写入 0 禁用扫描。

    启用

    echo "1" >/sys/devices/system/edac/pci/check_pci_parity
    

    禁用

    echo "0" >/sys/devices/system/edac/pci/check_pci_parity
    
  • pci_parity_count - 奇偶校验计数

    此属性文件将显示检测到的奇偶校验错误数。

模块参数

  • edac_mc_panic_on_ue - 遇到 UE 时挂起 (panic) 控制文件

    不可纠正错误将导致机器挂起。这通常是符合预期的。发生不可纠正错误时继续运行是个坏主意 - 无法确定什么未被纠正,操作系统上下文可能被严重破坏,以至于继续运行会导致进一步的损坏。如果内核配置了 MCE,则 EDAC 永远不会注意到 UE。

    加载时间

    module/kernel parameter: edac_mc_panic_on_ue=[0|1]
    

    运行时间

    echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
    
  • edac_mc_log_ue - 记录 UE 控制文件

    生成描述不可纠正错误的内核消息。这些错误通过系统消息日志系统报告。即使禁用了 UE 记录,也会累积 UE 统计信息。

    加载时间

    module/kernel parameter: edac_mc_log_ue=[0|1]
    

    运行时间

    echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
    
  • edac_mc_log_ce - 记录 CE 控制文件

    生成描述可纠正错误的内核消息。这些错误通过系统消息日志系统报告。即使禁用了 CE 记录,也会累积 CE 统计信息。

    加载时间

    module/kernel parameter: edac_mc_log_ce=[0|1]
    

    运行时间

    echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
    
  • edac_mc_poll_msec - 轮询周期控制文件

    轮询错误信息的时间周期(以毫秒为单位)。值太小会浪费资源。值太大可能会延迟必要的错误处理,并可能丢失用于定位错误的有价值信息。1000 毫秒(每秒一次)是当前的默认值。需要尽可能多带宽的系统可以增加此值。

    加载时间

    module/kernel parameter: edac_mc_poll_msec=[0|1]
    

    运行时间

    echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
    
  • panic_on_pci_parity - 发生 PCI 奇偶校验错误时挂起

    此控制文件启用或禁用在检测到奇偶校验错误时挂起系统。

    模块/内核参数

    edac_panic_on_pci_pe=[0|1]
    

    启用

    echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
    

    禁用

    echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
    

EDAC 设备类型

在头文件 edac_pci.h 中,有一系列针对 EDAC_DEVICE 的 edac_device 结构和 API。

用户空间通过 sysfs 接口访问 edac_device。

/sys/devices/system/edac (sysfs) 位置会出现新的 edac_device 设备。

在上述 edac 目录下有一个三层结构的树。例如,test_device_edac 设备(可在 http://bluesmoke.sourceforget.net 网站找到)将其自身安装为:

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

该目录中有各种控制文件、一个符号链接以及一个或多个 instance 目录。

标准默认控件包括:

log_ce

布尔值,用于记录 CE 事件

log_ue

布尔值,用于记录 UE 事件

panic_on_ue

布尔值,如果遇到 UE 则使系统挂起 (panic)(默认关闭,可通过启动脚本设置为 true)

poll_msec

事件轮询周期的时间

test_device_edac 设备至少添加了一个自己的自定义控制项:

test_bits

在当前的测试驱动程序中,除了显示它是如何安装的之外什么也不做。移植的驱动程序可以为特定用途添加一个或多个此类控制项和/或属性。一个树外驱动程序在此处使用控制项,以允许对硬件注入寄存器进行错误注入 (ERROR INJECTION) 操作。

符号链接指向为该 edac_device 注册的 ‘struct dev’。

实例 (Instances)

存在一个或多个实例目录。对于 test_device_edac 情况:

test-instance0

在该目录中有两个默认计数器属性,它们是更深子目录中计数器的总和。

ce_count

子目录中 CE 事件的总计

ue_count

子目录中 UE 事件的总计

块 (Blocks)

在最低目录层级是 block 目录。每个实例中可以指定 0、1 或多个块:

test-block0

该目录中的默认属性为:

ce_count

它是正在监控的硬件 block 的 CE 事件计数器

ue_count

它是正在监控的硬件 block 的 UE 事件计数器

test_device_edac 设备增加了 4 个属性和 1 个控制项:

test-block-bits-0

每个轮询周期此计数器递增一次

test-block-bits-1

每 10 个周期此计数器增加一次,并将 test-block-bits-0 设置为 0

test-block-bits-2

每 100 个周期此计数器增加一次,并将 test-block-bits-1 设置为 0

test-block-bits-3

每 1000 个周期此计数器增加一次,并将 test-block-bits-2 设置为 0

reset-counters

向此控制项写入任何内容都将重置上述所有计数器。

使用 test_device_edac 驱动程序应该能使其他人能够为他们的硬件系统创建自己独特的驱动程序。

test_device_edac 示例驱动程序位于 EDAC 的 http://bluesmoke.sourceforge.net 项目站点。

在 Nehalem 及更新的 Intel CPU 上使用 EDAC API

在较旧的 Intel 架构中,内存控制器是北桥芯片组的一部分。Nehalem、Sandy Bridge、Ivy Bridge、Haswell、Sky Lake 及更新的 Intel 架构在 CPU 内部集成了增强版的内存控制器 (MC)。

本章将介绍在较新的 Intel CPU 上发现的增强型内存控制器的差异,如 i7core_edacsb_edacsbx_edac 驱动程序。

注意

Xeon E7 处理器系列使用独立的芯片作为内存控制器,称为 Intel Scalable Memory Buffer (可扩展内存缓冲)。本节不适用于此类系列。

  1. 每个 Quick Patch Interconnect (QPI) 有一个内存控制器。在驱动程序中,术语“插槽”(socket) 表示一个 QPI。这与物理 CPU 插槽相关联。

    每个 MC 有 3 个物理读取通道、3 个物理写入通道和 3 个逻辑通道。驱动程序目前将其视为仅 3 个通道。每个通道最多可容纳 3 个 DIMM。

    已知最小单位是 DIMM。没有关于 csrow 的信息。由于 EDAC API 映射的最小单位是 csrow,因此驱动程序会按顺序将通道/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 节点:

    • inject_addrmatch/*:

      控制错误注入掩码寄存器。可以指定地址的若干特征来匹配错误代码:

      dimm = the affected dimm. Numbers are relative to a channel;
      rank = the memory rank;
      channel = the channel that will generate an error;
      bank = the affected bank;
      page = the page address;
      column (or col) = the address column.
      

      上述每个值都可以设置为“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
      
      To return to the default behaviour of matching any, you can do::
      
              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 缓存段将发生错误

      3 for both
      2 for the highest
      1 for the lowest
      
    • 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. 可纠正错误内存寄存器计数器

    这些较新的 MC 具有一些计数内存错误的寄存器。驱动程序使用这些寄存器来报告带寄存器的 DIMM (RDIMM) 设备上的可纠正错误。

    然而,这些计数器不适用于不带寄存器的 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 的计数;

    硬件会在 csrow0、csrow2 或 csrow3 上的第二个 dimm 发生错误时增加 udimm1 的计数;

    硬件会在 csrow0、csrow2 或 csrow3 上的第三个 dimm 发生错误时增加 udimm2 的计数;

  4. 标准错误计数器

    当驱动程序收到 mcelog 错误时,会生成标准错误计数器。由于使用 UDIMM 时这是由软件计数的,因此可能会丢失一些错误。对于 RDIMM,它们显示寄存器的内容:

amd64_edac 使用的参考文档

amd64_edac 模块基于以下文档(可从 http://support.amd.com/en-us/search/tech-docs 获取):

  1. 标题:

    AMD Athlon 64 和 AMD Opteron 处理器 BIOS 与内核开发者指南

    AMD 出版物编号 #:

    26094

    修订版本:

    3.26

    链接:

    http://support.amd.com/TechDocs/26094.PDF

  2. 标题:

    AMD NPT Family 0Fh 处理器 BIOS 与内核开发者指南

    AMD 出版物编号 #:

    32559

    修订版本:

    3.00

    发布日期:

    2006 年 5 月

    链接:

    http://support.amd.com/TechDocs/32559.pdf

  3. 标题:

    AMD Family 10h 处理器 BIOS 与内核开发者指南 (BKDG)

    AMD 出版物编号 #:

    31116

    修订版本:

    3.00

    发布日期:

    2007 年 9 月 7 日

    链接:

    http://support.amd.com/TechDocs/31116.pdf

  4. 标题:

    AMD Family 15h Models 30h-3Fh 处理器 BIOS 与内核开发者指南 (BKDG)

    AMD 出版物编号 #:

    49125

    修订版本:

    3.06

    发布日期:

    2015 年 2 月 12 日(最新版本)

    链接:

    http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf

  5. 标题:

    AMD Family 15h Models 60h-6Fh 处理器 BIOS 与内核开发者指南 (BKDG)

    AMD 出版物编号 #:

    50742

    修订版本:

    3.01

    发布日期:

    2015 年 7 月 23 日(最新版本)

    链接:

    http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf

  6. 标题:

    AMD Family 16h Models 00h-0Fh 处理器 BIOS 与内核开发者指南 (BKDG)

    AMD 出版物编号 #:

    48751

    修订版本:

    3.03

    发布日期:

    2015 年 2 月 23 日(最新版本)

    链接:

    http://support.amd.com/TechDocs/48751_16h_bkdg.pdf

致谢

  • 由 Doug Thompson 编写 <dougthompson@xmission.com>

    • 2005 年 12 月 7 日

    • 2007 年 7 月 17 日更新

  • © Mauro Carvalho Chehab

    • 2009 年 8 月 5 日 Nehalem 接口

    • 2016 年 10 月 26 日转换为 ReST 并清理 Nehalem 章节

  • EDAC 作者/维护者

    • Doug Thompson, Dave Jiang, Dave Peterson et al,

    • Mauro Carvalho Chehab

    • Borislav Petkov

    • 原作者: Thayne Harbaugh