英文

hwpoison

什么是 hwpoison?

即将推出的 Intel CPU 支持从一些内存错误中恢复 (MCA recovery)。 这要求操作系统声明一个页面为“已中毒”,杀死与其关联的进程,并避免将来使用它。

此补丁集在 VM 中实现了必要的基础架构。

引用概述注释

High level machine check handler. Handles pages reported by the
hardware as being corrupted usually due to a 2bit ECC memory or cache
failure.

This focusses on pages detected as corrupted in the background.
When the current CPU tries to consume corruption the currently
running process can just be killed directly instead. This implies
that if the error cannot be handled for some reason it's safe to
just ignore it because no corruption has been consumed yet. Instead
when that happens another machine check will happen.

Handles page cache pages in various states. The tricky part
here is that we can access any page asynchronous to other VM
users, because memory failures could happen anytime and anywhere,
possibly violating some of their assumptions. This is why this code
has to be extremely careful. Generally it tries to use normal locking
rules, as in get the standard locks, even if that means the
error handling takes potentially a long time.

Some of the operations here are somewhat inefficient and have non
linear algorithmic complexity, because the data structures have not
been optimized for this case. This is in particular the case
for the mapping from a vma to a process. Since this case is expected
to be rare we hope we can get away with this.

该代码由 mm/memory-failure.c 中的高级处理程序、新的页面中毒位以及 VM 中用于处理中毒页面的各种检查组成。

目前的主要目标是 KVM 客户机,但它适用于所有类型的应用程序。 KVM 支持需要最新的 qemu-kvm 版本。

对于 KVM 用途,需要一种新的信号类型,以便 KVM 可以使用正确的地址将机器检查注入到客户机中。 从理论上讲,这也允许其他应用程序处理内存故障。 预计大多数应用程序不会这样做,但一些非常专业的应用程序可能会这样做。

故障恢复模式

内存故障恢复有两种(实际上是三种)模式

vm.memory_failure_recovery sysctl 设置为零

所有内存故障都会导致 panic。 不要尝试恢复。

提前杀死

(可以全局和按进程控制)一旦检测到错误,就向应用程序发送 SIGBUS。 这允许能够以温和的方式处理内存错误的应用程序(例如,删除受影响的对象)。 这是 KVM qemu 使用的模式。

延迟杀死

当应用程序遇到损坏的页面时发送 SIGBUS。 这最适合未感知内存错误的应用程序和默认值。 请注意,某些页面始终作为延迟杀死处理。

用户控制

vm.memory_failure_recovery

请参阅 sysctl.txt

vm.memory_failure_early_kill

全局启用提前杀死模式

PR_MCE_KILL

设置提前/延迟杀死模式/恢复为系统默认值

arg1: PR_MCE_KILL_CLEAR

恢复为系统默认值

arg1: PR_MCE_KILL_SET

arg2 定义线程特定模式

PR_MCE_KILL_EARLY

提前杀死

PR_MCE_KILL_LATE

延迟杀死

PR_MCE_KILL_DEFAULT

使用系统全局默认值

请注意,如果您希望有一个专门的线程代表进程处理 SIGBUS(BUS_MCEERR_AO),您应该在指定的线程上调用 prctl(PR_MCE_KILL_EARLY)。 否则,SIGBUS 将发送到主线程。

PR_MCE_KILL_GET

返回当前模式

测试

  • madvise(MADV_HWPOISON, ....) (作为 root) - 在进程中中毒一个页面进行测试

  • 通过 debugfs 的 hwpoison-inject 模块 /sys/kernel/debug/hwpoison/

    corrupt-pfn

    在回显到此文件的 PFN 处注入 hwpoison 故障。 这会进行一些早期过滤,以避免在测试套件中损坏意外的页面。

    unpoison-pfn

    软件取消中毒回显到此文件的 PFN 处的页面。 这样就可以再次重复使用该页面。 这仅适用于 Linux 注入的故障,不适用于真实的内存故障。 一旦发生任何硬件内存故障,此功能将被禁用。

    请注意,这些注入接口不稳定,并且可能在内核版本之间发生变化

    corrupt-filter-dev-major, corrupt-filter-dev-minor

    仅处理与由块设备主/次定义的文件系统关联的页面的内存故障。 -1U 是通配符值。 这应该仅用于人工注入的测试。

    corrupt-filter-memcg

    将注入限制为 memgroup 拥有的页面。 由 memcg 的 inode 编号指定。

    例子

    mkdir /sys/fs/cgroup/mem/hwpoison
    
    usemem -m 100 -s 1000 &
    echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks
    
    memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ')
    echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg
    
    page-types -p `pidof init`   --hwpoison  # shall do nothing
    page-types -p `pidof usemem` --hwpoison  # poison its pages
    
    corrupt-filter-flags-mask, corrupt-filter-flags-value

    如果指定,仅当 ((page_flags & mask) == value) 时才中毒页面。 这允许对多种类型的页面进行压力测试。 page_flags 与 /proc/kpageflags 中的相同。 标志位在 include/linux/kernel-page-flags.h 中定义,并在 检查进程页表 中记录。

  • 特定于架构的 MCE 注入器

    x86 具有 mce-inject, mce-test

    mce-test 中一些可移植的 hwpoison 测试程序,请参见下文。

参考

http://halobates.de/mce-lc09-2.pdf

LinuxCon 09 的概述演示

git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git

测试套件(tsrc 中特定于 hwpoison 的可移植测试)

git://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git

x86 特定注入器

限制

  • 并非所有页面类型都受支持,并且永远不会受支持。 大多数内核内部对象无法恢复,目前只能恢复 LRU 页面。

--- Andi Kleen, 2009 年 10 月