← Documents Documentation/mm/hwpoison.rst GitHub 원문 ↗

Linux 6.18.37 · Memory management

hwpoison

Hardware memory corruption을 poisoned page로 격리하고 process에 알리는 recovery 모드, 사용자 제어와 injection test interface를 설명합니다.

Source pathDocumentation/mm/hwpoison.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

hwpoison.rst:1-182

Hwpoison은 hardware가 손상됐다고 보고한 physical page를 VM에서 격리하고, 연결된 process에 `SIGBUS`를 전달하며, 해당 page를 다시 할당하지 않게 하는 memory-failure recovery 기반입니다. Background에서 발견된 손상은 아직 CPU가 소비하지 않았을 수 있으므로 일반 VM lock을 지키며 신중하게 정리하고, 실제 접근 중 발견된 손상은 실행 중인 process를 즉시 종료할 수 있습니다.

Hardware memory failure 처리
ECC·cache failureMachine check`mm/memory-failure.c`Page poisonedMapping·process 탐색`SIGBUS` 또는 panic향후 재사용 금지

손상 감지부터 page 격리와 process 통지까지의 중심 흐름입니다.

Memory failure recovery 모드
모드통지 시점주 용도
Recovery offMemory failure 즉시 panic복구를 허용하지 않는 system
Early killError 감지 즉시 `SIGBUS`KVM qemu, 자체 복구 application
Late kill손상 page 접근 시 `SIGBUS`Memory-error 비인지 application, 기본값

System 정책과 application의 error 인식 수준에 따라 통지 시점이 달라집니다.

`PR_MCE_KILL` 제어
Operation효과
`PR_MCE_KILL_CLEAR`System 기본값으로 복귀
`PR_MCE_KILL_SET + EARLY`Thread를 early kill로 설정
`PR_MCE_KILL_SET + LATE`Thread를 late kill로 설정
`PR_MCE_KILL_SET + DEFAULT`전역 기본값 사용
`PR_MCE_KILL_GET`현재 모드 조회

Process 또는 지정 thread에서 early/late 정책을 선택합니다.

Hwpoison injection 검사 경로
`MADV_HWPOISON`Process page 선택Poison injectionRecovery 검증
`/sys/kernel/debug/hwpoison/`Device·memcg·flag filter`corrupt-pfn`Poison injection
Linux-injected failure`unpoison-pfn`Page 재사용

실제 hardware failure 없이 page 종류와 대상 범위를 제한해 recovery를 검사합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ========
2 hwpoison
3 ========
4
5 What is hwpoison?
6 =================
7
8 Upcoming Intel CPUs have support for recovering from some memory errors
9 (``MCA recovery``). This requires the OS to declare a page "poisoned",
10 kill the processes associated with it and avoid using it in the future.
11
12 This patchkit implements the necessary infrastructure in the VM.
13
14 To quote the overview comment::
15
16 High level machine check handler. Handles pages reported by the
17 hardware as being corrupted usually due to a 2bit ECC memory or cache
18 failure.
19
20 This focusses on pages detected as corrupted in the background.
21 When the current CPU tries to consume corruption the currently
22 running process can just be killed directly instead. This implies
23 that if the error cannot be handled for some reason it's safe to
24 just ignore it because no corruption has been consumed yet. Instead
25 when that happens another machine check will happen.
26
27 Handles page cache pages in various states. The tricky part
28 here is that we can access any page asynchronous to other VM
29 users, because memory failures could happen anytime and anywhere,
30 possibly violating some of their assumptions. This is why this code
31 has to be extremely careful. Generally it tries to use normal locking
32 rules, as in get the standard locks, even if that means the
33 error handling takes potentially a long time.
34
35 Some of the operations here are somewhat inefficient and have non
36 linear algorithmic complexity, because the data structures have not
37 been optimized for this case. This is in particular the case
38 for the mapping from a vma to a process. Since this case is expected
39 to be rare we hope we can get away with this.
40
41 The code consists of a the high level handler in mm/memory-failure.c,
42 a new page poison bit and various checks in the VM to handle poisoned
43 pages.
44
45 The main target right now is KVM guests, but it works for all kinds
46 of applications. KVM support requires a recent qemu-kvm release.
47
48 For the KVM use there was need for a new signal type so that
49 KVM can inject the machine check into the guest with the proper
50 address. This in theory allows other applications to handle
51 memory failures too. The expectation is that most applications
52 won't do that, but some very specialized ones might.
53
54 Failure recovery modes
55 ======================
56
57 There are two (actually three) modes memory failure recovery can be in:
58
59 vm.memory_failure_recovery sysctl set to zero:
60 All memory failures cause a panic. Do not attempt recovery.
61
62 early kill
63 (can be controlled globally and per process)
64 Send SIGBUS to the application as soon as the error is detected
65 This allows applications who can process memory errors in a gentle
66 way (e.g. drop affected object)
67 This is the mode used by KVM qemu.
68
69 late kill
70 Send SIGBUS when the application runs into the corrupted page.
71 This is best for memory error unaware applications and default
72 Note some pages are always handled as late kill.
73
74 User control
75 ============
76
77 vm.memory_failure_recovery
78 See sysctl.txt
79
80 vm.memory_failure_early_kill
81 Enable early kill mode globally
82
83 PR_MCE_KILL
84 Set early/late kill mode/revert to system default
85
86 arg1: PR_MCE_KILL_CLEAR:
87 Revert to system default
88 arg1: PR_MCE_KILL_SET:
89 arg2 defines thread specific mode
90
91 PR_MCE_KILL_EARLY:
92 Early kill
93 PR_MCE_KILL_LATE:
94 Late kill
95 PR_MCE_KILL_DEFAULT
96 Use system global default
97
98 Note that if you want to have a dedicated thread which handles
99 the SIGBUS(BUS_MCEERR_AO) on behalf of the process, you should
100 call prctl(PR_MCE_KILL_EARLY) on the designated thread. Otherwise,
101 the SIGBUS is sent to the main thread.
102
103 PR_MCE_KILL_GET
104 return current mode
105
106 Testing
107 =======
108
109 * madvise(MADV_HWPOISON, ....) (as root) - Poison a page in the
110 process for testing
111
112 * hwpoison-inject module through debugfs ``/sys/kernel/debug/hwpoison/``
113
114 corrupt-pfn
115 Inject hwpoison fault at PFN echoed into this file. This does
116 some early filtering to avoid corrupted unintended pages in test suites.
117
118 unpoison-pfn
119 Software-unpoison page at PFN echoed into this file. This way
120 a page can be reused again. This only works for Linux
121 injected failures, not for real memory failures. Once any hardware
122 memory failure happens, this feature is disabled.
123
124 Note these injection interfaces are not stable and might change between
125 kernel versions
126
127 corrupt-filter-dev-major, corrupt-filter-dev-minor
128 Only handle memory failures to pages associated with the file
129 system defined by block device major/minor. -1U is the
130 wildcard value. This should be only used for testing with
131 artificial injection.
132
133 corrupt-filter-memcg
134 Limit injection to pages owned by memgroup. Specified by inode
135 number of the memcg.
136
137 Example::
138
139 mkdir /sys/fs/cgroup/mem/hwpoison
140
141 usemem -m 100 -s 1000 &
142 echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks
143
144 memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ')
145 echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg
146
147 page-types -p `pidof init` --hwpoison # shall do nothing
148 page-types -p `pidof usemem` --hwpoison # poison its pages
149
150 corrupt-filter-flags-mask, corrupt-filter-flags-value
151 When specified, only poison pages if ((page_flags & mask) ==
152 value). This allows stress testing of many kinds of
153 pages. The page_flags are the same as in /proc/kpageflags. The
154 flag bits are defined in include/linux/kernel-page-flags.h and
155 documented in Documentation/admin-guide/mm/pagemap.rst
156
157 * Architecture specific MCE injector
158
159 x86 has mce-inject, mce-test
160
161 Some portable hwpoison test programs in mce-test, see below.
162
163 References
164 ==========
165
166 http://halobates.de/mce-lc09-2.pdf
167 Overview presentation from LinuxCon 09
168
169 git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git
170 Test suite (hwpoison specific portable tests in tsrc)
171
172 git://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git
173 x86 specific injector
174
175
176 Limitations
177 ===========
178 - Not all page types are supported and never will. Most kernel internal
179 objects cannot be recovered, only LRU pages for now.
180
181 ---
182 Andi Kleen, Oct 2009
183

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Hwpoison의 목적과 처리 범위

1-53

출시 예정인 Intel CPU는 일부 memory error에서 복구하는 `MCA recovery`를 지원합니다. 이를 위해 OS는 page를 'poisoned'로 표시하고, 그 page와 연결된 process를 종료하며, 이후에는 해당 page를 사용하지 않아야 합니다.

이 patchkit은 이를 위해 VM에 필요한 기반 구조를 구현합니다.

Overview comment의 내용을 옮기면 다음과 같습니다.

High-level machine check handler는 hardware가 손상됐다고 보고한 page를 처리합니다. 보통 2-bit ECC memory 또는 cache failure가 원인입니다.

이 handler는 background에서 손상이 감지된 page에 초점을 둡니다. 현재 CPU가 손상된 데이터를 소비하려 한다면 현재 실행 중인 process를 바로 종료할 수 있습니다. 반면 background 감지 시에는 아직 손상된 데이터를 소비하지 않았으므로 어떤 이유로 error를 처리할 수 없어도 무시하는 것이 안전합니다. 그 경우 나중에 또 다른 machine check가 발생합니다.

여러 상태의 page-cache page를 처리합니다. Memory failure는 언제 어디서나 일어나 다른 VM 사용자의 가정을 깨뜨릴 수 있으므로, 다른 사용자의 동작과 비동기적으로 어떤 page에도 접근할 수 있다는 점이 까다롭습니다. 이 때문에 코드는 극도로 조심해야 합니다. Error handling이 오래 걸릴 수 있더라도 일반적인 locking rule을 따르고 표준 lock을 얻으려고 합니다.

여기서 수행하는 일부 operation은 비효율적이고 algorithm complexity가 비선형입니다. 자료 구조가 이 상황에 최적화되지 않았기 때문입니다. 특히 VMA에서 process를 찾는 mapping이 그렇습니다. 이 상황은 드물 것으로 예상하므로 감수할 수 있기를 기대합니다.

코드는 `mm/memory-failure.c`의 high-level handler, 새 page poison bit, poisoned page를 처리하기 위한 VM의 여러 검사로 구성됩니다.

현재 주 대상은 KVM guest지만 모든 종류의 application에서 동작합니다. KVM 지원에는 최신 `qemu-kvm` release가 필요합니다.

KVM이 올바른 주소로 guest에 machine check를 inject할 수 있도록 새 signal type이 필요했습니다. 이론상 다른 application도 memory failure를 처리할 수 있습니다. 대부분의 application은 그렇게 하지 않을 것으로 예상하지만, 매우 특수한 일부 application은 처리할 수 있습니다.

========
hwpoison
========

What is hwpoison?
=================

Upcoming Intel CPUs have support for recovering from some memory errors
(``MCA recovery``). This requires the OS to declare a page "poisoned",
kill the processes associated with it and avoid using it in the future.

This patchkit implements the necessary infrastructure in the VM.

To quote the overview comment::

        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.

The code consists of a the high level handler in mm/memory-failure.c,
a new page poison bit and various checks in the VM to handle poisoned
pages.

The main target right now is KVM guests, but it works for all kinds
of applications. KVM support requires a recent qemu-kvm release.

For the KVM use there was need for a new signal type so that
KVM can inject the machine check into the guest with the proper
address. This in theory allows other applications to handle
memory failures too. The expectation is that most applications
won't do that, but some very specialized ones might.

Failure recovery 모드

54-73

Memory failure recovery에는 두 가지, 엄밀히 말하면 세 가지 모드가 있습니다.

  • `vm.memory_failure_recovery` sysctl이 0: 모든 memory failure가 panic을 일으킵니다. 복구를 시도하지 않습니다.
  • Early kill: 전역 또는 process별로 제어할 수 있습니다. Error를 감지하는 즉시 application에 `SIGBUS`를 보냅니다. 영향을 받은 object를 버리는 것처럼 memory error를 점진적으로 처리할 수 있는 application에 적합하며 KVM qemu가 사용하는 모드입니다.
  • Late kill: Application이 손상된 page에 실제로 접근할 때 `SIGBUS`를 보냅니다. Memory error를 인식하지 못하는 application에 가장 적합하며 기본값입니다. 일부 page는 언제나 late kill로 처리합니다.
Failure recovery modes
======================

There are two (actually three) modes memory failure recovery can be in:

vm.memory_failure_recovery sysctl set to zero:
        All memory failures cause a panic. Do not attempt recovery.

early kill
        (can be controlled globally and per process)
        Send SIGBUS to the application as soon as the error is detected
        This allows applications who can process memory errors in a gentle
        way (e.g. drop affected object)
        This is the mode used by KVM qemu.

late kill
        Send SIGBUS when the application runs into the corrupted page.
        This is best for memory error unaware applications and default
        Note some pages are always handled as late kill.

사용자 제어

74-105

`vm.memory_failure_recovery`의 설명은 `sysctl.txt`를 참조하십시오.

`vm.memory_failure_early_kill`은 전역 early-kill 모드를 활성화합니다.

`PR_MCE_KILL`은 early 또는 late kill 모드를 설정하거나 system 기본값으로 되돌립니다.

  • `arg1 = PR_MCE_KILL_CLEAR`: system 기본값으로 되돌립니다.
  • `arg1 = PR_MCE_KILL_SET`: `arg2`가 thread별 모드를 정합니다.
  • `arg2 = PR_MCE_KILL_EARLY`: early kill을 사용합니다.
  • `arg2 = PR_MCE_KILL_LATE`: late kill을 사용합니다.
  • `arg2 = PR_MCE_KILL_DEFAULT`: system 전역 기본값을 사용합니다.

Process를 대신해 `SIGBUS(BUS_MCEERR_AO)`를 처리하는 전용 thread를 두려면 지정 thread에서 `prctl(PR_MCE_KILL_EARLY)`을 호출해야 합니다. 그렇지 않으면 `SIGBUS`가 main thread로 전달됩니다.

`PR_MCE_KILL_GET`은 현재 모드를 반환합니다.

User control
============

vm.memory_failure_recovery
        See sysctl.txt

vm.memory_failure_early_kill
        Enable early kill mode globally

PR_MCE_KILL
        Set early/late kill mode/revert to system default

        arg1: PR_MCE_KILL_CLEAR:
                Revert to system default
        arg1: PR_MCE_KILL_SET:
                arg2 defines thread specific mode

                PR_MCE_KILL_EARLY:
                        Early kill
                PR_MCE_KILL_LATE:
                        Late kill
                PR_MCE_KILL_DEFAULT
                        Use system global default

        Note that if you want to have a dedicated thread which handles
        the SIGBUS(BUS_MCEERR_AO) on behalf of the process, you should
        call prctl(PR_MCE_KILL_EARLY) on the designated thread. Otherwise,
        the SIGBUS is sent to the main thread.

PR_MCE_KILL_GET
        return current mode

검사와 fault injection

106-162

Root 권한으로 `madvise(MADV_HWPOISON, ....)`를 호출하면 검사를 위해 process의 page 하나를 poison할 수 있습니다.

`hwpoison-inject` module은 debugfs의 `/sys/kernel/debug/hwpoison/` 아래에서 다음 interface를 제공합니다.

  • `corrupt-pfn`: 이 file에 echo한 PFN에 hwpoison fault를 inject합니다. Test suite에서 의도하지 않은 page를 손상시키지 않도록 일부 초기 filtering을 수행합니다.
  • `unpoison-pfn`: 이 file에 echo한 PFN의 page를 software 방식으로 unpoison해 다시 사용할 수 있게 합니다. Linux가 inject한 failure에만 동작하고 실제 memory failure에는 동작하지 않습니다. Hardware memory failure가 한 번이라도 일어나면 이 기능은 비활성화됩니다.

이 injection interface들은 안정된 ABI가 아니며 kernel version 사이에서 바뀔 수 있습니다.

`corrupt-filter-dev-major`와 `corrupt-filter-dev-minor`는 지정한 block-device major/minor로 정의되는 filesystem과 연결된 page의 memory failure만 처리합니다. `-1U`가 wildcard 값입니다. Artificial injection을 이용한 검사에만 사용해야 합니다.

`corrupt-filter-memcg`는 memgroup이 소유한 page로 injection을 제한합니다. Memcg inode number로 지정합니다.

사용 예는 다음과 같습니다.

		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만 poison합니다. 여러 종류의 page를 stress test할 수 있습니다. `page_flags`는 `/proc/kpageflags`와 같고, flag bit는 `include/linux/kernel-page-flags.h`에 정의되며 `Documentation/admin-guide/mm/pagemap.rst`에 문서화돼 있습니다.

Architecture별 MCE injector도 있습니다. x86에는 `mce-inject`와 `mce-test`가 있으며, `mce-test`에는 portable hwpoison test program도 일부 들어 있습니다.

Testing
=======

* madvise(MADV_HWPOISON, ....) (as root) - Poison a page in the
  process for testing

* hwpoison-inject module through debugfs ``/sys/kernel/debug/hwpoison/``

  corrupt-pfn
        Inject hwpoison fault at PFN echoed into this file. This does
        some early filtering to avoid corrupted unintended pages in test suites.

  unpoison-pfn
        Software-unpoison page at PFN echoed into this file. This way
        a page can be reused again.  This only works for Linux
        injected failures, not for real memory failures. Once any hardware
        memory failure happens, this feature is disabled.

  Note these injection interfaces are not stable and might change between
  kernel versions

  corrupt-filter-dev-major, corrupt-filter-dev-minor
        Only handle memory failures to pages associated with the file
        system defined by block device major/minor.  -1U is the
        wildcard value.  This should be only used for testing with
        artificial injection.

  corrupt-filter-memcg
        Limit injection to pages owned by memgroup. Specified by inode
        number of the memcg.

        Example::

                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
        When specified, only poison pages if ((page_flags & mask) ==
        value).  This allows stress testing of many kinds of
        pages. The page_flags are the same as in /proc/kpageflags. The
        flag bits are defined in include/linux/kernel-page-flags.h and
        documented in Documentation/admin-guide/mm/pagemap.rst

* Architecture specific MCE injector

  x86 has mce-inject, mce-test

  Some portable hwpoison test programs in mce-test, see below.

참고 자료

163-175
  • `http://halobates.de/mce-lc09-2.pdf`: LinuxCon 09 overview presentation입니다.
  • `git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git`: test suite이며 hwpoison 전용 portable test는 `tsrc`에 있습니다.
  • `git://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git`: x86 전용 injector입니다.
References
==========

http://halobates.de/mce-lc09-2.pdf
        Overview presentation from LinuxCon 09

git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git
        Test suite (hwpoison specific portable tests in tsrc)

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

제한 사항

176-182

모든 page type을 지원하는 것은 아니며 앞으로도 그럴 것입니다. 대부분의 kernel 내부 object는 복구할 수 없고 현재는 LRU page만 복구할 수 있습니다.

Andi Kleen, 2009년 10월

Limitations
===========
- Not all page types are supported and never will. Most kernel internal
  objects cannot be recovered, only LRU pages for now.

---
Andi Kleen, Oct 2009