在大型生产环境中,硬件故障无声无息地侵蚀着系统稳定性。RAS(Reliability, Availability, Serviceability) 子系统是 Linux 内核应对硬件错误的最后防线——它能在 DRAM bit flip 演变为内核 panic 之前将其捕获、纠正并隔离。本文从 x86 Machine Check Architecture 的硬件寄存器开始,深度剖析 MCE 异常处理流程、EDAC 子系统架构、PCIe AER 错误传播,以及如何构建生产级 RAS 监控告警体系。
一、为什么需要 RAS?——无声的数据腐化
现代 x86 服务器每条内存通道以 4.8 GT/s(DDR5-4800)速率传输数据,信号完整性面临串扰、阻抗失配和软错误(Soft Error)的三重威胁。研究数据显示,每 GB DRAM 平均每年会发生 0.2–10 次 Correctable Error(CE),而 Uncorrectable Error(UE)的 MTBF 约为数万台服务器年一次——在万台规模的数据中心里,每天至少发生数起 UE 事件。
没有 RAS 子系统,CE 错误会被静默忽略直到累积爆发;UE 错误则直接导致内核 panic 或更糟——数据腐化被写入磁盘后传播到其他节点。RAS 的设计目标有三层:
- Availability:CE 发生时维持系统在线,UE 尽可能做 targeted panic 而非全局 panic
- Serviceability:精确定位故障 DIMM 槽位,指导运维更换
- Reliability:通过内存巡检(Scrubbing)主动清除 CE 累积
二、x86 Machine Check Architecture(MCA)硬件基础
x86 CPU 通过一组特权寄存器实现错误检测,统称为 MCA 寄存器组,由以下部分组成:
2.1 MCA 寄存器体系
MCA 寄存器层次:
├── IA32_MCG_CAP (MSR 0x179) - 全局能力: 错误报告 bank 数量、CMCI 支持
├── IA32_MCG_STATUS (MSR 0x17A) - 全局状态: RIPV/EIPV/MCIP 三位
├── IA32_MCG_CTL (MSR 0x17B) - 全局控制: 各 bank 总使能
├── IA32_MCi_CTL (MSR 0x400+) - 每 bank 错误类型使能
├── IA32_MCi_STATUS (MSR 0x401+) - 每 bank 错误状态: MCA Error Code + Model Error Code
├── IA32_MCi_ADDR (MSR 0x402+) - 错误发生时的物理地址
└── IA32_MCi_MISC (MSR 0x403+) - 补充信息: 通道号、rank 号
其中 MCi_STATUS 寄存器结构最为关键:
63 61 60 58 57 56 55 54 53 52 38 37 32
┌───────┬──────────┬──────────┬──────────┬──────────┬────────────┬──────────┐
│ VAL │ OVER │ UC │ EN │ MISCV │ ADDRV │ 其他标志 │ MCA Code│
│(有效) │(溢出) │(不可纠正)│(已使能) │ (MISC │ (ADDR │ │ │
│ │ │ │ │ 有效) │ 有效) │ │ │
└───────┴──────────┴──────────┴──────────┴──────────┴────────────┴──────────┘
31 16 15 0
┌──────────────────────┬──────────────────────────────────┐
│ Model Specific Code│ MCA Error Code │
└──────────────────────┴──────────────────────────────────┘
每个 bank 对应一类错误检测单元:Bank 0 通常是 IFU(Instruction Fetch Unit),Bank 1 是 DCU(Data Cache Unit),Bank 2–4 对应 Load/Store 单元,后续 bank 则对应内存控制器(Memory Controller)的 CE/UE 报告。
2.2 Error Code 结构
MCA Error Code(位 [15:0])分为三个层级:
// arch/x86/include/asm/mce.h
#define MCI_STATUS_VAL BIT_64(63)
#define MCI_STATUS_OVER BIT_64(61)
#define MCI_STATUS_UC BIT_64(60) // Uncorrected
#define MCI_STATUS_EN BIT_64(59)
#define MCI_STATUS_MISCV BIT_64(58)
#define MCI_STATUS_ADDRV BIT_64(57)
#define MCI_STATUS_PCC BIT_64(55) // Processor Context Corrupt
/* MCA Error Code 层次结构 */
// Bit [3:0] = Transaction Type (TT): Generic/Read/Write/Data-IO
// Bit [7:5] = Level/Layer (LL): L0/L1/L2/L3/Generic
// Bit [11:8] = Request Type (RRRR): Generic/Read/Write/Addr-Herrick
// Bit [13:12] = Error operation type (PP): Processor/MemoryIO/Generic
// Bit [15:14] = Error topic (TTT): Timer/Cache/HW-Misc
三、MCE 异常处理内核流程
3.1 do_machine_check():MCE 核心分发
当硬件检测到不可恢复错误时,会触发 #MC(Machine Check Exception,向量号 18),CPU 跳转到入口点 do_machine_check()。这是 NMI-like 上下文(不可屏蔽中断),不能调用可能睡眠的函数:
// arch/x86/kernel/cpu/mce/core.c
void noinstr do_machine_check(struct pt_regs *regs)
{
struct mce m; // MCE 事件结构体
// 1. 从 IA32_MCi_STATUS MSR 读取 bank 状态
m.misc = 0;
m.addr = 0;
m.bank = -1;
// 2. 读取全局状态判断是否值得继续
rdmsrl(MSR_IA32_MCG_STATUS, status);
if (!(status & MCG_STATUS_RIPV)) {
// RIPV=0: 返回地址不可信,无法安全恢复
// 必须做Die → Panic 路径
mcg_flags |= MCG_STATUS_RIPV_UNKNOWN;
}
// 3. 逐 bank 扫描:哪些 bank 触发了错误
for (i = 0; i < mca_cfg.banks; i++) {
if (!mce_bank_valid(i))
continue;
mce_read_aux(&m, i);
if (!(m.status & MCI_STATUS_VAL))
continue;
m.bank = i;
// 4. 判断严重程度等级
severity = mce_severity(&m, regs, &msg, true);
switch (severity) {
case MCE_KEEP: // 可忽略(已处理的 throttle)
break;
case MCE_RECOVERABLE: // 可恢复 - 隔离错误页
mce_log(&m);
break;
case MCE_AR: // Action Required - 必须隔离
if (mce_us_address(m.addr))
kernel_pagefault_fixup();
break;
case MCE_PANIC: // 严重 → 直接 panic
mce_panic("Fatal machine check", &m, msg);
}
}
}
3.2 mce_severity():五级严重度判定
// arch/x86/kernel/cpu/mce/severity.c
enum mce_severity_levels mce_severity(struct mce *m, struct pt_regs *regs,
char **msg, bool is_excp)
{
if (!(m->status & MCI_STATUS_UC)) {
// Corrected Error
if (m->status & MCI_STATUS_ADDRV && memory_error(m))
return MCE_AR; // 内存 CE 到达 threshold → Action Required
return MCE_KEEP; // 普通 CE,记录日志即可
}
// Uncorrected Error
if (m->status & MCI_STATUS_PCC)
return MCE_PANIC; // 处理器上下文损坏,无法继续
// TLB/Cache 硬件部分可能恢复
switch (m->bank) {
case MCE_TLB_BANK:
case MCE_MEM_BANK:
if (mce_us_address(m->addr) && recoverable_address(m))
return MCE_AR; // 用户态地址 + 可隔离 → kill 进程
...
}
return MCE_PANIC;
}
3.3 CMCI(Corrected Machine Check Interrupt)
现代 Intel 处理器为高频率 CE 引入了 CMCI——基于 threshold 的轮询式中断,避免逐条 CE 触发中断导致性能抖动:
CE 到达 → Bank STATUS 更新 → Counter +1
→ 当 Counter ≥ Threshold(默认 50)→ 触发 LVT CMCI 中断
→ 中断处理函数 mce_threshold_kernel() 读取 counter 并上报 EDAC
四、EDAC 子系统架构
EDAC(Error Detection And Correction)子系统在内核中独立于 MCE 运行,它从两个来源收集错误事件:
4.1 架构分层
┌──────────────────────────────────────────────────┐
│ 用户空间 (edac-util / rasdaemon) │
├──────────────────────────────────────────────────┤
│ sysfs (/sys/devices/system/edac/mc/) │
│ ├── mc*/ce_count - CE 计数 │
│ ├── mc*/ce_noinfo_count - 无地址 CE 计数 │
│ ├── mc*/ue_count - UE 计数 │
│ ├── mc*/ue_noinfo_count - 无地址 UE 计数 │
│ ├── mc*/dimm*/dimm_ce_count - DIMM 级计数 │
│ ├── mc*/dimm*/dimm_location - 物理槽位 │
│ └── mc*/dimm*-label - DIMM 标签 │
├──────────────────────────────────────────────────┤
│ EDAC Core (drivers/edac/edac_mc.c) │
│ ├── edac_mc_alloc() - 分配 MC 控制器 │
│ ├── edac_mc_add_mc() - 注册到 sysfs │
│ ├── edac_mc_handle_error() - 上报错误统一入口 │
│ └── edac_raw_mc_event() - 推送 netlink 事件 │
├──────────────────────────────────────────────────┤
│ Chipset Driver Layer │
│ ├── i7core_edac (Nehalem) │
│ ├── sb_edac (Sandy Bridge+) │
│ ├── skx_edac (Skylake/Cascade Lake) │
│ ├── i10nm_edac (Ice Lake/Sapphire Rapids) │
│ └── amd64_edac (AMD Opteron/EPYC) │
├──────────────────────────────────────────────────┤
│ MCE / CMCI 注入层 │
│ └── mce_inject → mce_threshold → edac_mc 上报 │
└──────────────────────────────────────────────────┘
4.2 edac_mc_handle_error():统一错误上报入口
这是 EDAC 子系统的核心函数,所有 chipset 驱动通过它上报 CE/UE 事件:
// drivers/edac/edac_mc.c
void edac_mc_handle_error(const enum hw_event_err_type type,
struct mem_ctl_info *mci,
const u16 error_count,
const unsigned long page_frame_number,
const unsigned long offset_in_page,
const unsigned long syndrome,
const int row, const int chan,
const char *msg)
{
// 1. 分级判断: CE vs UE
if (type == HW_EVENT_ERR_CORRECTED) {
mci->ce_count += error_count;
if (chan >= 0)
mci->ce_per_layer[0][chan] += error_count;
if (row >= 0)
mci->ce_per_layer[1][row] += error_count;
} else {
mci->ue_count += error_count;
if (chan >= 0)
mci->ue_per_layer[0][chan] += error_count;
}
// 2. 写入 sysfs: 暴露给 userspace 查询
// /sys/devices/system/edac/mc/mc0/ce_count
// /sys/devices/system/edac/mc/mc0/dimm0/dimm_ce_count
// 3. 触发 netlink 事件: 通知 rasdaemon
edac_raw_mc_event(mci, ce_notifier_list, type, ...);
// 4. 检查 page offline 条件: CE 累积超过阈值
if (type == HW_EVENT_ERR_CORRECTED && edac_mc_get_ce_count(mci, row, chan)
> edac_mc_get_ce_threshold(mci)) {
// 触发 memory_failure() 隔离问题页
soft_offline_page(page_frame_number);
}
}
4.3 sysfs 接口结构
EDAC 通过 sysfs 暴露完整的 DIMM 拓扑和计数信息:
$ tree /sys/devices/system/edac/mc/
/sys/devices/system/edac/mc/
├── mc0/ # Memory Controller 0
│ ├── ce_count # 该 MC 总 CE 计数
│ ├── ce_noinfo_count # 无法映射地址的 CE
│ ├── ue_count # 该 MC 总 UE 计数
│ ├── ue_noinfo_count # 无法映射地址的 UE
│ ├── seconds_count # UEFI 记录的时间戳
│ ├── size_mb # 总容量
│ ├── mc_name # "i10nm" / "sb" ...
│ ├── dimm0/
│ │ ├── dimm_ce_count # 该 DIMM 的 CE 总数
│ │ ├── dimm_location # "Processor 1 DIMM E1"
│ │ ├── dimm_mem_type # "DDR4"
│ │ ├── dimm_dev_type # "x4" / "x8"
│ │ ├── dimm_edac_mode # S4ECD4ED
│ │ └── dimm_label # "CPU1_Channel1_Dimm0"
│ ├── dimm1/ ...
│ └── csrow0/ # Chip-Select Row
│ ├── ce_count
│ ├── ue_count
│ └── ch0_dimm_label
├── mc1/
└── mc2/
五、syndrome 与 DIMM 定位算法
5.1 Syndrome(症状码)
当内存控制器检测到 ECC 错误时,会生成一个 syndrome 码(8-bit for SECDED, 16-bit for Chipkill),它是一个汉明码校验结果的映射,直接反映了出错的 bit 位置。
对于 x4/x8 DIMM,syndrome 值可以直接映射到特定的 DRAM 芯片位:
// 简化版 syndrome 解码: 对 DDR4 x8 组织
static void ecc_syndrome_to_chip(uint32_t syndrome, int *chip, int *bit)
{
if (syndrome == 0)
return; // 无错误
// syndrome 的低位直接对应 ECC 校验矩阵
// 具体映射由 JEDEC 规范定义,与 chip-select 和 bit 位置相关
*chip = (syndrome >> 5) & 0x7; // 高3位 → DRAM chip index
*bit = syndrome & 0x1F; // 低5位 → bit position
}
5.2 Row/Channel 映射
现代内存控制器通过 CSROW(Chip-Select Row)和 Channel 组织物理内存。EDAC 驱动需要将 MCi_STATUS.ADDR 解析为:
物理地址 → Memory Controller选择 (socket)
→ Channel 选择 (interleave 算法)
→ DIMM 选择 (channel interleave)
→ Rank 选择
→ Row/Column 定位
Intel 芯片组的 i10nm_edac 驱动使用 skx_init() 阶段从 PCI config space 读取内存映射配置表,建立地址到 DIMM 的映射关系。
六、PCIe AER(Advanced Error Reporting)
6.1 AER 错误类型
PCIe AER 是 RAS 在总线层的延伸,通过 PCIe Capability Structure(偏移 0x100)暴露:
AER 错误分为两类:
├── Correctable Errors(可纠正):
│ ├── Receiver Error - 物理层 8b/10b 编码错误
│ ├── Bad TLP - TLP 链路层 CRC 错误
│ ├── Bad DLLP - DLLP 链路层 CRC 错误
│ ├── Replay Timer Timeout
│ └── Advisory Non-Fatal - 非致命提示
│
└── Uncorrectable Errors(不可纠正):
├── Data Link Protocol Error - 致命
├── Poisoned TLP - 致命
├── Flow Control Protocol - 致命
├── Completion Timeout - 致命
├── ACS Violation - 致命
├── Unsupported Request - 致命
└── ACS / ECRC 检查失败
6.2 AER 内核处理流程
// drivers/pci/pcie/aer.c
static void aer_error_detected(struct pci_dev *dev)
{
struct aer_err_info *info = &dev->aer_info;
// 1. 读取 AER 错误状态寄存器
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &cor_status);
// 2. 判断 severity: fatal / nonfatal
sever = cci_error_severity(dev, status);
if (sever == AER_FATAL) {
// 致命错误: 必须隔离相关子系统
// 首先尝试 per-port 层面的 recovery
pcie_do_recovery(dev, pci_channel_io_frozen, sever);
// recovery 策略(按优先级):
// bus reset → secondary bus reset
// downstream port reset
// link retrain → slot reset
// 最终手段: remove and rescan
} else {
// 可纠正错误: 清除状态位,继续运行
pci_write_config_dword(dev, pos+PCI_ERR_COR_STATUS, cor_status);
}
}
6.3 AER → MCE 联合上报
当 PCIe AER 错误涉及内存映射 I/O 地址时,其可能通过 MCi_STATUS 的 Model-Specific Code 与 MCE 关联:
PCIe 事务失败 → Root Port AER 记录
→ 如果是 Memory Read/Write 访问
→ 内存控制器 bank 检测为 Transaction Timeout
→ MCE 触发,bank 为 MEM_BANK
→ severity = AR → 隔离该地址对应页
生产价值的体现: 若该地址属于 NVMe 设备 BAR → 定位到 NVMe 控制器故障
七、Page Offline:错误页隔离
RAS 最关键的作用不是"发现问题",而是"阻止恶化"。当某个物理页重复出现 CE 错误,说明该 DRAM 单元已开始退化,必须将其从可用池中移除。
7.1 memory_failure() 核心流程
// mm/memory-failure.c
int memory_failure(unsigned long pfn, int flags)
{
struct page *p = pfn_to_page(pfn);
// 1. 锁定该页,阻止新映射
if (!get_hwpoison_page(p, flags))
return -EBUSY;
// 2. 判断页类型并分类处理
if (PageHuge(p)) {
// Huge page poisoning - 必须打破为 4K 页
if (!TestSetPageHWPoison(split_huge_page(p)))
return -EBUSY;
}
if (PageLRU(p)) {
// LRU 页: 直接移出
if (isolate_lru_page(p)) {
// 移除后若引用计数归零 → 放入 hwpoison 队列
if (!put_page_testzero(p))
return 0;
}
} else if (PageAnon(p) || PageMappingAgnostic(p)) {
// 匿名页或文件映射: 通知所有持有者
kill_procs(pfn, flags, ...
// 清除所有 PTE 映射,插入 poisoned PTE
unmap_mapping_range(mapping, ...);
}
// 3. 最终标记
SetPageHWPoison(p);
// 4. 通知用户空间(可选)
me_memory_event(pfn, MH_ACTION_POISONED);
pr_err("Memory error on physical address %#lx: page offline\n",
(unsigned long)pfn << PAGE_SHIFT);
return 0;
}
7.2 soft_offline_page vs hard_offline_page
| 场景 | 触发方 | 行为 | 破坏性 |
|---|---|---|---|
| CE 累积超阈 | EDAC driver | soft_offline | 非阻塞,数据可恢复 |
| UE 即时触发 | MCE handler | hard_offline | 立即移除,不保证数据安全 |
| 手动注入 | sysfs/mce-inject | 可控参数 | 测试用 |
八、生产级 RAS 监控告警体系
8.1 rasdaemon:推荐的统一监控方案
rasdaemon 是 AMD/Mellanox 等厂商维护的替代 mcelog 的 RAS 监控 daemon,通过 netlink 接收 EDAC/MCE 事件并持久化到 SQLite:
# /etc/rasdaemon/ras-mc-handler.conf
# 1. 启动服务
$ systemctl enable --now rasdaemon
# 2. 查询事件记录
$ ras-mc-ctl --errors
mc0: 1 Corrected err - CSROW 3 channel 1 DIMM 2
Syndrome: 0xab12
Count: 847 (last 24h)
$ ras-mc-ctl --error-count
DIMM: CPU1_Channel0_Dimm0
CE: 12,349 ( lifetime )
UE: 0
CE/day: 156 ( trending ↑ )
# 3. 查询 Extlog(AER 与 MCE 关联)
$ ras-mc-ctl --extlog-errors-count
PCIe AER: 23 (correctable), 1 (fatal NVMe timeout)
8.2 edac-util:轻量统计工具
# edac-util 直接读取 sysfs
$ edac-util --status
mc0: EDAC driver 'i10mm' CSROW 0: 3 CE, 0 UE
mc0: EDAC driver 'i10mm' CSROW 1: 0 CE, 0 UE
$ edac-util --report=dimm
mc0:dimm0: 847 CE, 0 UE, type DDR4, size 32 GB, speed 3200 MT/s
mc0:dimm1: 23 CE, 0 UE, type DDR4, size 32 GB, speed 3200 MT/s
mc0:dimm2: 12,349 CE, 0 UE, type DDR4, size 32 GB, speed 3200 MT/s
mc0:dimm3: 0 CE, 0 UE, type DDR4, size 32 GB, speed 3200 MT/s
8.3 Prometheus + Grafana 监控方案
# prometheus-edac-exporter 自定义 collector
python script:
import os, glob
def collect_edac_metrics():
for mc in glob.glob('/sys/devices/system/edac/mc/mc*'):
mc_name = os.path.basename(mc)
ce = read_int(f'{mc}/ce_count')
ue = read_int(f'{mc}/ue_count')
yield GaugeMetricFamily(
'node_edac_ce_total',
'Corrected error count per MC',
value=ce,
labels=[f'mc={mc_name}']
)
for dimm in glob.glob(f'{mc}/dimm*'):
dimm_ce = read_int(f'{dimm}/dimm_ce_count')
dimm_label = read_str(f'{dimm}/dimm_label')
yield GaugeMetricFamily(
'node_edac_dimm_ce_total',
'DIMM-level corrected errors',
value=dimm_ce,
labels=[f'mc={mc_name}', f'dimm={dimm_label}']
)
# Prometheus 告警规则
groups:
- name: ras_alerts
rules:
- alert: CorrectibleErrorRateHigh
expr: rate(node_edac_ce_total[1h]) > 50
for: 30m
labels:
severity: warning
annotations:
summary: "DIMM {{ $labels.dimm }} CE rate > 50/h, plan replacement"
- alert: HighRiskUEImminent
expr: rate(node_edac_dimm_ce_total[24h]) > 1000
labels:
severity: critical
annotations:
summary: "DIMM showing degraded ECC, UE imminent"
- alert: PCIeAFatalError
expr: increase(node_edac_pcie_aer_fatal_total[5m]) > 0
labels:
severity: critical
annotations:
summary: "PCIe fatal AER error detected"
8.4 memory_failure 自动处理
Linux 提供了 madvise(MADV_HWPOISON) 和 sysfs 自动页隔离接口:
# 查看系统已隔离的 poisoned page 数量
$ cat /sys/devices/system/memory/hwpoison_count
3
# 手动测试: inject a CE using mce-inject (仅测试用)
$ echo "0 0 0 0 1 0 0x8c00020040c00080 0 0 0" > /sys/devices/system/machinecheck/machinecheck0/inject
# 验证页是否被正确隔离
$ dmesg | grep -i "HardwareCorrupted"
HardwareCorrupted: 48 kB
# 查看页面状态
$ grep -r "HardwareCorrupted" /proc/meminfo
HardwareCorrupted: 48 kB
九、MCE 注入测试:验证 RAS 链路的快速方法
对于无法等待真实硬件故障的运维团队,Linux 提供了 mce-inject 模块用于模拟错误:
# 加载注入模块
$ modprobe mce-inject
# 构造注入: 物理地址 + 错误类型
# 格式: bank status addr misc
$ cat > /tmp/inject.txt << EOF
# Bank 4 (memory controller), CE, ADDRV=1
4 0x8c00020040c00080 0x10000000 0x0
EOF
$ cat /tmp/inject.txt > /sys/devices/system/machinecheck/machinecheck/inject
# 验证 edac 是否正确上报
$ edac-util --status # ce_count 应增加
$ ras-mc-ctl --errors # 应出现新事件记录
# 模拟 UE (uncorrected, PCC=1)
$ echo "4 0x9c00020040c00080 0x20000000 0x0" > inject # PCC=1 → panic!
十、AMD EPYC 的特殊 RAS 实现
AMD EPYC 平台对 RAS 有额外增强:
- MCA/X (Extended MCA):Bank 32+ 扩展用于 DF 错误报告
- SMCA (Scaled MCA):AMD Zen 架构引入,增加 IPID 和 Synd 寄存的更细粒度区分
- FRMCA (First MCA via PSP):通过 PSP 协处理器在 pre-boot 阶段记录 MCE
- PPIN (Protected Processor Inventory Number):硬件级 CPU 序列号,用于备件追踪
AMD EDAC 驱动 amd64_edac 对应的 sysfs 路径:
# AMD EPYC 的 DIMM 拓扑更复杂(3DS RDIMM、LRDIMM、3-stacked)
$ cat /sys/devices/system/edac/mc/mc0/dimm0/dimm_label
"PSP_ce_count" "PSP_ue_count" # AMD 特有的 PSP-reported 计数器
十一、未来方向:CXL 2.0/3.0 的 RAS 扩展
CXL(Compute Express Link)引入了基于 PCIe 的物理层但带缓存一致性语义的新互连协议,RAS 挑战更加严峻:
- CXL.io:继承 PCIe AER,所有错误类型直接映射
- CXL.cache:缓存一致性协议错误需要新的
cxl_aer驱动处理 - CXL.mem:内存扩展场景下的 RAS 策略——是隔离还是 kill host?
- Persistent Memory RAS:CXL-attached 持久内存的错误恢复与 ADR(Asynchronous DRAM Refresh)
内核正在合的补丁包括 cxl_pci AER 处理、cxl_mem MCE 交互、以及 cxl_acpi 的 RAS 报告。
总结
Linux RAS 子系统是一个横跨硬件、固件、内核驱动、用户态工具链的复杂工程体系。本文涵盖了从 x86 MCA 寄存器、MCE handler 的 severity 判断、EDAC 子系统的 chipset driver 层,到 AER 错误传播和 page offline 隔离的完整链路。
关键 best practice 总结:
• 必须部署 rasdaemon(而非过时的 mcelog),确保 CE/UE 事件持久化
• CE ≠ UE:CE 率突增是的前兆,应设置 rate(ce_total[1h]) > 50 告警
• Page Offline 是最有效的防护:在 UE 发生前主动隔离退化页
• syndrome 追踪:长期追踪单个 DIMM 的 syndrome 模式可预判特定 DRAM chip 失效
• CXL 来了:新一代内存扩展协议正在要求 RAS 子系统重建
RAS 是服务器稳定性的隐形防火墙——看不见,但缺了它迟早出事。
相关延伸阅读:Linux 内核 documentation/x86/mce.rst、drivers/edac/README.edac、PCIe Base Spec Section 6.2

发表评论 取消回复