요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
========
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 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.
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
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.
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
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
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-73Memory 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-162Root 권한으로 `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
요약·해설
hwpoison.rst:1-182Hwpoison은 hardware가 손상됐다고 보고한 physical page를 VM에서 격리하고, 연결된 process에 `SIGBUS`를 전달하며, 해당 page를 다시 할당하지 않게 하는 memory-failure recovery 기반입니다. Background에서 발견된 손상은 아직 CPU가 소비하지 않았을 수 있으므로 일반 VM lock을 지키며 신중하게 정리하고, 실제 접근 중 발견된 손상은 실행 중인 process를 즉시 종료할 수 있습니다.
손상 감지부터 page 격리와 process 통지까지의 중심 흐름입니다.
System 정책과 application의 error 인식 수준에 따라 통지 시점이 달라집니다.
Process 또는 지정 thread에서 early/late 정책을 선택합니다.
실제 hardware failure 없이 page 종류와 대상 범위를 제한해 recovery를 검사합니다.