"hwpoison"是什么?
即将推出的英特尔CPU支持从一些内存错误(MCA恢复)中恢复。这需要操作系统声明一个页面为“毒害”,终止与之关联的进程,并避免将来使用它。
这个补丁包在虚拟机中实现了必要的基础设施。
引用概述评论:
高级机器检查处理程序。处理硬件报告的页面通常由于2位ECC内存或缓存故障而被损坏。
这专注于在后台检测到损坏的页面。当当前CPU尝试消耗损坏时,当前运行的进程可以直接被终止。这意味着,如果由于某种原因无法处理错误,那么安全地忽略它是可以的,因为尚未发生任何损坏。相反,当发生这种情况时,将会发生另一个机器检查。
处理各种状态的页面缓存页面。这里的棘手之处在于我们可以异步访问任何页面,因为内存故障可能随时发生,可能违反一些假设。这就是为什么这段代码必须非常小心谨慎。通常情况下,它试图使用正常的锁定规则,即获取标准锁定,即使这可能意味着错误处理需要很长时间。
这里的一些操作有些低效,并且具有非线性的算法复杂性,因为数据结构并未针对这种情况进行优化。这特别适用于从VMA到进程的映射。由于这种情况预计是罕见的,我们希望可以摆脱这一点。
代码包括mm/memory-failure.c中的高级处理程序、新的页面毒害位以及虚拟机中处理毒害页面的各种检查。
目前的主要目标是KVM客户端,但适用于各种应用程序。KVM支持需要最新的qemu-kvm版本。
对于KVM的使用,需要一种新的信号类型,以便KVM可以将机器检查注入到具有适当地址的客户端。理论上,这也允许其他应用程序处理内存故障。预期大多数应用程序不会这样做,但一些非常专业的应用程序可能会。
故障恢复模式
内存故障恢复有两种(实际上是三种)模式:
- 将
vm.memory_failure_recovery
设置为零:
所有内存故障都会导致系统崩溃,不会尝试恢复。 - 早期终止(可以全局和每个进程单独控制):
一旦检测到错误,立即向应用程序发送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 /sys/kernel/debug/hwpoison/中的hwpoison-inject模块
- 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测试程序,见下文。
参考资料
限制
并非所有页面类型都受支持,而且永远也不会受支持。目前只能恢复大多数内核内部对象,仅支持LRU页面。
--- Andi Kleen,2009年10月