Kexec Handover 用法

Kexec HandOver (KHO) 是一种允许 Linux 在 kexec 过程中保留内存区域的机制,这些内存区域可能包含序列化的系统状态。

本文档假定您熟悉基本的 KHO 概念。如果您尚未阅读它们,请立即阅读。

先决条件

当内核编译时设置了 CONFIG_KEXEC_HANDOVER 为 y 时,KHO 可用。每个 KHO 生产者可能都有自己的配置选项,如果您希望在 kexec 过程中保留它们各自的状态,则需要启用该选项。

要使用 KHO,请使用 kho=on 命令行参数启动内核。您可以使用 kho_scratch 参数来定义 scratch 区域的大小。例如,kho_scratch=16M,512M,256M 将在启动时保留一个 16 MiB 的低内存 scratch 区域、一个 512 MiB 的全局 scratch 区域和 256 MiB 的每个 NUMA 节点的 scratch 区域。

执行 KHO kexec

首先,在执行 KHO kexec 之前,您需要将系统移动到 KHO 最终确定阶段

$ echo 1 > /sys/kernel/debug/kho/out/finalize

执行此命令后,KHO FDT 在 /sys/kernel/debug/kho/out/fdt 中可用。其他子系统也可能在 /sys/kernel/debug/kho/out/sub_fdts/ 下注册它们自己的保留的子 FDT。

接下来,加载目标有效负载并 kexec 到其中。重要的是,您使用 -s 参数来使用内核中的 kexec 文件加载器,因为用户空间 kexec 工具目前不支持使用基于用户空间的文件加载器的 KHO

# kexec -l /path/to/bzImage --initrd /path/to/initrd -s
# kexec -e

新的内核将启动并包含先前内核的某些状态。

例如,如果您使用 reserve_mem 命令行参数来创建早期内存预留,则新内核将在与旧内核相同的物理地址处拥有该内存。

中止 KHO 执行

您可以通过调用以下命令再次将系统移出 KHO 最终确定阶段

$ echo 0 > /sys/kernel/debug/kho/out/active

执行此命令后,KHO FDT 将不再在 /sys/kernel/debug/kho/out/fdt 中可用。

debugfs 接口

目前,KHO 创建以下 debugfs 接口。请注意,这些接口将来可能会更改。一旦 KHO 稳定,它们将被移动到 sysfs。

/sys/kernel/debug/kho/out/finalize

Kexec HandOver (KHO) 允许 Linux 将兼容驱动程序的状态转换到下一个 kexec 的内核中。为此,设备驱动程序将指示 KHO 保留内存区域,这些区域可能包含序列化的内核状态。在状态被序列化时,它们无法对序列化的状态(例如移交的内存分配)执行任何修改。

当此文件包含“1”时,系统处于转换状态。当包含“0”时,系统不处于转换状态。要在两种状态之间切换,请将相应的数字回显到此文件中。

/sys/kernel/debug/kho/out/fdt

当 KHO 状态树被最终确定时,内核会在此文件中公开扁平化的设备树 blob,该 blob 携带其当前的 KHO 状态。Kexec 用户空间工具可以使用它作为 KHO 有效负载镜像的输入文件。

/sys/kernel/debug/kho/out/scratch_len

KHO scratch 区域的长度,这些区域是物理上连续的内存区域,将始终可用于未来的 kexec 分配。Kexec 用户空间工具可以使用此文件来确定其有效负载镜像的放置位置。

/sys/kernel/debug/kho/out/scratch_phys

KHO scratch 区域的物理位置。Kexec 用户空间工具可以结合 scratch_phys 使用此文件来确定其有效负载镜像的放置位置。

/sys/kernel/debug/kho/out/sub_fdts/

在 KHO 最终确定阶段,KHO 生产者在此目录下注册它们自己的 FDT blob。

/sys/kernel/debug/kho/in/fdt

当内核使用 Kexec HandOver (KHO) 启动时,携带有关先前内核状态的元数据的状态树位于此文件中,格式为扁平化设备树。当它的所有使用者完成对其元数据的解释时,此文件可能会消失。

/sys/kernel/debug/kho/in/sub_fdts/

kho/out/sub_fdts/ 类似,但包含从旧内核传递的 KHO 生产者的子 FDT blob。