固件辅助转储¶
2011年7月
固件辅助转储的目标是实现崩溃系统的转储,并且通过完全重置的系统来完成,同时将系统恢复投入生产使用所需的总耗时降至最低。
固件辅助转储 (FADump) 基础设施旨在取代现有的 phyp 辅助转储。
Fadump 使用与 phyp 辅助转储相同的固件接口和内存预留模型。
与 phyp 转储不同,FADump 以与 kdump 相同的方式通过 /proc/vmcore 以 ELF 格式导出内存转储。这有助于我们复用 kdump 基础设施来进行转储捕获和过滤。
与 phyp 转储不同,用户空间工具在读取 /proc/vmcore 时无需引用任何 sysfs 接口。
与 phyp 转储不同,FADump 允许用户通过单次操作 echo 1 > /sys/kernel/fadump_release_mem 来释放为转储预留的所有内存。
一旦通过内核启动参数启用,FADump 就可以通过 /sys/kernel/fadump_registered 接口(参见下文 sysfs 文件部分)进行启动/停止,并且可以轻松地与 kdump 服务的启动/停止初始化脚本集成。
与 kdump 或其他策略相比,固件辅助转储具有几个强大而实用的优势
与 kdump 不同,系统已被重置,并加载了全新复制的内核。特别是,PCI 和 I/O 设备已重新初始化,处于干净、一致的状态。
转储复制完成后,保存转储的内存立即可供运行中的内核使用。因此,与 kdump 不同,FADump 不需要第二次重启即可将系统恢复到生产配置。
上述操作只能通过与 Power 固件的协调和协助来完成。步骤如下
第一个内核在操作系统初始化期间向 Power 固件注册内存区域以保存转储。这些注册的内存区域由第一个内核在早期引导阶段预留。
当系统崩溃时,Power 固件会将注册的低内存区域(引导内存)从源区域复制到目标区域。它还将保存硬件 PTE。
- 注意
术语“引导内存”是指在受限内存下引导时,内核成功引导所需的低内存块大小。默认情况下,引导内存大小为系统 RAM 的 5% 或 256MB 中的较大者。或者,用户也可以通过引导参数 ‘crashkernel=’ 指定引导内存大小,这将覆盖默认计算的大小。如果默认引导内存大小不足以让第二个内核成功引导,请使用此选项。有关 crashkernel= 参数的语法,请参考 Kdump 文档 - 基于 kexec 的崩溃转储解决方案。如果在 crashkernel= 参数中提供了任何偏移量,它将被忽略,因为 FADump 使用预定义的偏移量来预留内存,以便在发生崩溃时保存引导内存转储。
保存低内存(引导内存)区域后,固件将重置 PCI 和其他硬件状态。它不会清除 RAM。然后,它将像往常一样启动引导加载程序。
刚引导的内核会注意到设备树中有一个新节点(pSeries 上的 rtas/ibm,kernel-dump 或 OPAL 平台上的 ibm,opal/dump/mpipl-boot),表明有来自前一次引导的可用崩溃数据。在早期引导期间,操作系统将预留引导内存大小之上的其余内存,从而有效地以受限内存大小进行引导。这将确保该内核(也称为第二个内核或捕获内核)不会触及任何转储内存区域。
用户空间工具将读取 /proc/vmcore 以获取内存内容,其中以 ELF 格式保存了先前崩溃的内核转储。用户空间工具可根据需要将此信息复制到磁盘、网络、nas、san、iscsi 等。
用户空间工具完成转储保存后,它将向 /sys/kernel/fadump_release_mem 写入 ‘1’,以将预留内存释放回通用状态,但下一次固件辅助转储注册所需的内存除外。
例如:
# echo 1 > /sys/kernel/fadump_release_mem
请注意,固件辅助转储功能仅适用于 pSeries (PowerVM) 平台上的 POWER6 及以上系统,以及 PowerNV (OPAL) 平台上带有 OP940 或更高固件版本的 POWER9 及以上系统。注意,当 PowerNV 平台支持 FADump 时,OPAL 固件会导出 ibm,opal/dump 节点。
在基于 OPAL 的机器上,系统在引导进入捕获内核之前,会先引导进入一个间歇内核(称为 petitboot 内核)。该内核具有用于处理崩溃数据的最低限度的内核和/或用户空间支持。此类内核需要保留先前崩溃的内核的内存,以便后续的捕获内核引导来处理这些崩溃数据。必须在此类内核中启用内核配置选项 CONFIG_PRESERVE_FA_DUMP,以确保保存崩溃数据以供稍后处理。
- -- 在基于 OPAL 的机器 (PowerNV) 上,如果内核构建时带有
CONFIG_OPAL_CORE=y,则崩溃时的 OPAL 内存也会作为 /sys/firmware/opal/mpipl/core 文件导出。此 procfs 文件有助于使用 GDB 调试 OPAL 崩溃。通过向 /sys/firmware/opal/mpipl/release_core 节点写入 ‘1’,可以释放用于导出此 procfs 文件的内核内存。
- 例如:
# echo 1 > /sys/firmware/opal/mpipl/release_core
- -- 支持 Fadump 中的附加内核参数
Fadump 具有一项允许向 fadump 内核传递附加内核参数的功能。此功能的主要设计目的是禁用 fadump 内核不需要的内核功能,并在收集转储时减少其内存占用。
向 Fadump 添加附加内核参数的命令:例如 # echo “nr_cpus=16” > /sys/kernel/fadump/bootargs_append
上述命令足以向 fadump 添加附加参数。不需要显式重启服务。
检索附加 Fadump 参数的命令:例如 # cat /sys/kernel/fadump/bootargs_append
- 注意:带有 HASH MMU 的 fadump 的附加内核参数仅
在 RMA 大小大于 768 MB 时受支持。如果 RMA 大小小于 768 MB,内核将不会导出 /sys/kernel/fadump/bootargs_append sysfs 节点。
实现细节:¶
在引导期间,会进行检查以查看固件是否在该特定机器上支持此功能。如果支持,我们会检查是否有活动的转储在等待我们处理。如果是,则在早期引导期间预留除引导内存大小之外的所有 RAM(参见图 2)。一旦我们完成从运行的用户态脚本(例如 kdump 脚本)中收集转储,该区域就会被释放。如果有转储数据,则会创建 /sys/kernel/fadump_release_mem 文件,并且保留预留内存。
如果没有等待的转储数据,通常仅在大于引导内存大小的偏移量处预留保存 CPU 状态、HPTE 区域、引导内存转储和 FADump 头所需的内存(参见图 1)。该区域不会被释放:该区域将保持永久预留,以便在发生崩溃时,它可以用作引导内存内容(以及 CPU 状态和 HPTE 区域)副本的容器。
由于此预留内存区域仅在系统崩溃后使用,因此阻止生产内核使用这块巨大的内存毫无意义。因此,如果内核配置了 CMA,实现会使用 Linux 内核的连续内存分配器 (CMA) 进行内存预留。通过 CMA 预留,此内存将可供应用程序使用,同时阻止内核使用它。这样,FADump 仍将能够捕获所有内核内存和大部分用户空间内存,但存在于 CMA 区域中的用户页面除外
o Memory Reservation during first kernel
Low memory Top of memory
0 boot memory size |<------ Reserved dump area ----->| |
| | | Permanent Reservation | |
V V | | V
+-----------+-----/ /---+---+----+-----------+-------+----+-----+
| | |///|////| DUMP | HDR |////| |
+-----------+-----/ /---+---+----+-----------+-------+----+-----+
| ^ ^ ^ ^ ^
| | | | | |
\ CPU HPTE / | |
-------------------------------- | |
Boot memory content gets transferred | |
to reserved area by firmware at the | |
time of crash. | |
FADump Header |
(meta area) |
|
|
Metadata: This area holds a metadata structure whose
address is registered with f/w and retrieved in the
second kernel after crash, on platforms that support
tags (OPAL). Having such structure with info needed
to process the crashdump eases dump capture process.
Fig. 1
o Memory Reservation during second kernel after crash
Low memory Top of memory
0 boot memory size |
| |<------------ Crash preserved area ------------>|
V V |<--- Reserved dump area --->| |
+----+---+--+-----/ /---+---+----+-------+-----+-----+-------+
| |ELF| | |///|////| DUMP | HDR |/////| |
+----+---+--+-----/ /---+---+----+-------+-----+-----+-------+
| | | | | |
----- ------------------------------ ---------------
\ | |
\ | |
\ | |
\ | ----------------------------
\ | /
\ | /
\ | /
/proc/vmcore
+---+
|///| -> Regions (CPU, HPTE & Metadata) marked like this in the above
+---+ figures are not always present. For example, OPAL platform
does not have CPU & HPTE regions while Metadata region is
not supported on pSeries currently.
+---+
|ELF| -> elfcorehdr, it is created in second kernel after crash.
+---+
Note: Memory from 0 to the boot memory size is used by second kernel
Fig. 2
目前,转储将在用户干预下从 /proc/vmcore 复制到新文件中。通过 /proc/vmcore 获取的转储数据将采用 ELF 格式。因此,现有的用于保存转储的 kdump 基础设施(kdump 脚本)只需进行微小的修改即可正常工作。主流发行版上的 KDump 脚本已经过修改,当使用 FADump 代替 KDump 作为转储机制时,可以无缝工作(保存转储时无需用户干预)。
检查转储的工具将与 kdump 使用的工具相同。
如何启用固件辅助转储 (FADump):¶
设置配置选项 CONFIG_FA_DUMP=y 并构建内核。
使用 ‘fadump=on’ 内核命令行选项引导进入 linux 内核。默认情况下,FADump 预留内存将被初始化为 CMA 区域。或者,用户可以使用 ‘fadump=nocma’ 引导 linux 内核以阻止 FADump 使用 CMA。
可选地,用户还可以设置 ‘crashkernel=’ 内核命令行来指定为保存引导内存转储而预留的内存大小。
- 注意
‘fadump_reserve_mem=’ 参数已被废弃。请改用 ‘crashkernel=’ 来指定为保存引导内存转储而预留的内存大小。
如果固件辅助转储未能预留内存,且内核命令行中设置了 ‘crashkernel=’ 选项,它将回退到现有的 kdump 机制。
如果用户想要捕获所有用户空间内存,并且能够接受预留内存不可用于生产系统,则可以使用 ‘fadump=nocma’ 内核参数回退到旧的行为。
Sysfs/debugfs 文件:¶
固件辅助转储功能使用 sysfs 文件系统来存放控制文件,并使用 debugfs 文件来显示内存预留区域。
以下是内核 sysfs 下的文件列表
- /sys/kernel/fadump_enabled
这用于显示 FADump 状态。
0 = FADump 已禁用
1 = FADump 已启用
kdump 初始化脚本可以使用此接口来识别内核中是否启用了 FADump,并做出相应的处理。
- /sys/kernel/fadump_registered
这用于显示 FADump 注册状态以及控制(启动/停止)FADump 注册。
0 = FADump 未注册。
1 = FADump 已注册并准备好处理系统崩溃。
要注册 FADump 请执行 echo 1 > /sys/kernel/fadump_registered;要注销并停止 FADump 请执行 echo 0 > /sys/kernel/fadump_registered。一旦 FADump 被注销,系统崩溃将不会被处理,也不会捕获 vmcore。该接口可以轻松地与 kdump 服务的启动/停止集成。
/sys/kernel/fadump/mem_reserved
这用于显示 FADump 为保存崩溃转储而预留的内存。
- /sys/kernel/fadump_release_mem
此文件仅在 FADump 在第二个内核期间处于活动状态时可用。它用于释放为保存崩溃转储而持有的预留内存区域。要释放预留内存,请向其写入 1
echo 1 > /sys/kernel/fadump_release_mem执行 echo 1 后,/sys/kernel/debug/powerpc/fadump_region 文件的内容将更改以反映新的内存预留情况。
可以轻松增强现有的用户空间工具(kdump 基础设施),使其能够使用此接口释放为转储预留的内存,并在无需第二次重启的情况下继续运行。
- 注意:/sys/kernel/fadump_release_opalcore sysfs 已移至
/sys/firmware/opal/mpipl/release_core
/sys/firmware/opal/mpipl/release_core
此文件仅在基于 OPAL 的机器上且 FADump 在捕获内核期间处于活动状态时可用。它用于释放内核用于导出 /sys/firmware/opal/mpipl/core 文件的内存。要释放此内存,请向其写入 ‘1’
echo 1 > /sys/firmware/opal/mpipl/release_core
注意:以下 FADump sysfs 文件已被废弃。
已废弃 |
替代方案 |
/sys/kernel/fadump_enabled |
/sys/kernel/fadump/enabled |
/sys/kernel/fadump_registered |
/sys/kernel/fadump/registered |
/sys/kernel/fadump_release_mem |
/sys/kernel/fadump/release_mem |
以下是 powerpc debugfs 下的文件列表:(假设 debugfs 已挂载在 /sys/kernel/debug 目录下。)
- /sys/kernel/debug/powerpc/fadump_region
如果启用了 FADump,该文件将显示预留的内存区域,否则该文件为空。输出格式为
<region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>对于内核 DUMP 区域,格式为
DUMP: Src: <src-addr>, Dest: <dest-addr>, Size: <size>, Dumped: # bytes
例如:在第一个内核期间注册 FADump 时的内容
# cat /sys/kernel/debug/powerpc/fadump_region CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0 HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0 DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0在第二个内核期间 FADump 处于活动状态时的内容
# cat /sys/kernel/debug/powerpc/fadump_region CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020 HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000 DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000 : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
- 注意
关于如何挂载 debugfs 文件系统,请参考 DebugFS。
待办事项:¶
需要想出更好的方法,来找出内核在受限内存下成功引导所需的更准确的引导内存大小。
作者:Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
本文档基于由 Linas Vepstas 和 Manish Ahuja 为 phyp
辅助转储编写的原始文档。