mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
kho: remove finalize state and clients
Eliminate the `kho_finalize()` function and its associated state from the KHO subsystem. The transition to a radix tree for memory tracking makes the explicit "finalize" state and its serialization step obsolete. Remove the `kho_finalize()` and `kho_finalized()` APIs and their stub implementations. Update KHO client code and the debugfs interface to no longer call or depend on the `kho_finalize()` mechanism. Complete the move towards a stateless KHO, simplifying the overall design by removing unnecessary state management. Link: https://lkml.kernel.org/r/20260206021428.3386442-3-jasonmiu@google.com Signed-off-by: Jason Miu <jasonmiu@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Alexander Graf <graf@amazon.com> Cc: Baoquan He <bhe@redhat.com> Cc: Changyuan Lyu <changyuanl@google.com> Cc: David Matlack <dmatlack@google.com> Cc: David Rientjes <rientjes@google.com> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: Pratyush Yadav <pratyush@kernel.org> Cc: Ran Xiaokai <ran.xiaokai@zte.com.cn> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
@@ -28,20 +28,10 @@ per NUMA node scratch regions on boot.
|
||||
Perform a KHO kexec
|
||||
===================
|
||||
|
||||
First, before you perform a KHO kexec, you need to move the system into
|
||||
the :ref:`KHO finalization phase <kho-finalization-phase>` ::
|
||||
|
||||
$ echo 1 > /sys/kernel/debug/kho/out/finalize
|
||||
|
||||
After this command, the KHO FDT is available in
|
||||
``/sys/kernel/debug/kho/out/fdt``. Other subsystems may also register
|
||||
their own preserved sub FDTs under
|
||||
``/sys/kernel/debug/kho/out/sub_fdts/``.
|
||||
|
||||
Next, load the target payload and kexec into it. It is important that you
|
||||
use the ``-s`` parameter to use the in-kernel kexec file loader, as user
|
||||
space kexec tooling currently has no support for KHO with the user space
|
||||
based file loader ::
|
||||
To perform a KHO kexec, load the target payload and kexec into it. It
|
||||
is important that you use the ``-s`` parameter to use the in-kernel
|
||||
kexec file loader, as user space kexec tooling currently has no
|
||||
support for KHO with the user space based file loader ::
|
||||
|
||||
# kexec -l /path/to/bzImage --initrd /path/to/initrd -s
|
||||
# kexec -e
|
||||
@@ -52,40 +42,19 @@ For example, if you used ``reserve_mem`` command line parameter to create
|
||||
an early memory reservation, the new kernel will have that memory at the
|
||||
same physical address as the old kernel.
|
||||
|
||||
Abort a KHO exec
|
||||
================
|
||||
|
||||
You can move the system out of KHO finalization phase again by calling ::
|
||||
|
||||
$ echo 0 > /sys/kernel/debug/kho/out/active
|
||||
|
||||
After this command, the KHO FDT is no longer available in
|
||||
``/sys/kernel/debug/kho/out/fdt``.
|
||||
|
||||
debugfs Interfaces
|
||||
==================
|
||||
|
||||
These debugfs interfaces are available when the kernel is compiled with
|
||||
``CONFIG_KEXEC_HANDOVER_DEBUGFS`` enabled.
|
||||
|
||||
Currently KHO creates the following debugfs interfaces. Notice that these
|
||||
interfaces may change in the future. They will be moved to sysfs once KHO is
|
||||
stabilized.
|
||||
|
||||
``/sys/kernel/debug/kho/out/finalize``
|
||||
Kexec HandOver (KHO) allows Linux to transition the state of
|
||||
compatible drivers into the next kexec'ed kernel. To do so,
|
||||
device drivers will instruct KHO to preserve memory regions,
|
||||
which could contain serialized kernel state.
|
||||
While the state is serialized, they are unable to perform
|
||||
any modifications to state that was serialized, such as
|
||||
handed over memory allocations.
|
||||
|
||||
When this file contains "1", the system is in the transition
|
||||
state. When contains "0", it is not. To switch between the
|
||||
two states, echo the respective number into this file.
|
||||
|
||||
``/sys/kernel/debug/kho/out/fdt``
|
||||
When KHO state tree is finalized, the kernel exposes the
|
||||
flattened device tree blob that carries its current KHO
|
||||
state in this file. Kexec user space tooling can use this
|
||||
The kernel exposes the flattened device tree blob that carries its
|
||||
current KHO state in this file. Kexec user space tooling can use this
|
||||
as input file for the KHO payload image.
|
||||
|
||||
``/sys/kernel/debug/kho/out/scratch_len``
|
||||
@@ -100,8 +69,8 @@ stabilized.
|
||||
it should place its payload images.
|
||||
|
||||
``/sys/kernel/debug/kho/out/sub_fdts/``
|
||||
In the KHO finalization phase, KHO producers register their own
|
||||
FDT blob under this directory.
|
||||
KHO producers can register their own FDT or another binary blob under
|
||||
this directory.
|
||||
|
||||
``/sys/kernel/debug/kho/in/fdt``
|
||||
When the kernel was booted with Kexec HandOver (KHO),
|
||||
|
||||
@@ -71,18 +71,6 @@ for boot memory allocations and as target memory for kexec blobs, some parts
|
||||
of that memory region may be reserved. These reservations are irrelevant for
|
||||
the next KHO, because kexec can overwrite even the original kernel.
|
||||
|
||||
.. _kho-finalization-phase:
|
||||
|
||||
KHO finalization phase
|
||||
======================
|
||||
|
||||
To enable user space based kexec file loader, the kernel needs to be able to
|
||||
provide the FDT that describes the current kernel's state before
|
||||
performing the actual kexec. The process of generating that FDT is
|
||||
called serialization. When the FDT is generated, some properties
|
||||
of the system may become immutable because they are already written down
|
||||
in the FDT. That state is called the KHO finalization phase.
|
||||
|
||||
Kexec Handover Radix Tree
|
||||
=========================
|
||||
|
||||
|
||||
@@ -68,8 +68,7 @@ early_param("kho", kho_parse_enable);
|
||||
|
||||
struct kho_out {
|
||||
void *fdt;
|
||||
bool finalized;
|
||||
struct mutex lock; /* protects KHO FDT finalization */
|
||||
struct mutex lock; /* protects KHO FDT */
|
||||
|
||||
struct kho_radix_tree radix_tree;
|
||||
struct kho_debugfs dbg;
|
||||
@@ -80,7 +79,6 @@ static struct kho_out kho_out = {
|
||||
.radix_tree = {
|
||||
.lock = __MUTEX_INITIALIZER(kho_out.radix_tree.lock),
|
||||
},
|
||||
.finalized = false,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1241,23 +1239,6 @@ void kho_restore_free(void *mem)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kho_restore_free);
|
||||
|
||||
int kho_finalize(void)
|
||||
{
|
||||
if (!kho_enable)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
guard(mutex)(&kho_out.lock);
|
||||
kho_out.finalized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kho_finalized(void)
|
||||
{
|
||||
guard(mutex)(&kho_out.lock);
|
||||
return kho_out.finalized;
|
||||
}
|
||||
|
||||
struct kho_in {
|
||||
phys_addr_t fdt_phys;
|
||||
phys_addr_t scratch_phys;
|
||||
|
||||
@@ -76,24 +76,6 @@ void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt)
|
||||
}
|
||||
}
|
||||
|
||||
static int kho_out_finalize_get(void *data, u64 *val)
|
||||
{
|
||||
*val = kho_finalized();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kho_out_finalize_set(void *data, u64 val)
|
||||
{
|
||||
if (val)
|
||||
return kho_finalize();
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(kho_out_finalize_fops, kho_out_finalize_get,
|
||||
kho_out_finalize_set, "%llu\n");
|
||||
|
||||
static int scratch_phys_show(struct seq_file *m, void *v)
|
||||
{
|
||||
for (int i = 0; i < kho_scratch_cnt; i++)
|
||||
@@ -199,11 +181,6 @@ __init int kho_out_debugfs_init(struct kho_debugfs *dbg)
|
||||
if (IS_ERR(f))
|
||||
goto err_rmdir;
|
||||
|
||||
f = debugfs_create_file("finalize", 0600, dir, NULL,
|
||||
&kho_out_finalize_fops);
|
||||
if (IS_ERR(f))
|
||||
goto err_rmdir;
|
||||
|
||||
dbg->dir = dir;
|
||||
dbg->sub_fdt_dir = sub_fdt_dir;
|
||||
return 0;
|
||||
|
||||
@@ -22,9 +22,6 @@ struct kho_debugfs {};
|
||||
extern struct kho_scratch *kho_scratch;
|
||||
extern unsigned int kho_scratch_cnt;
|
||||
|
||||
bool kho_finalized(void);
|
||||
int kho_finalize(void);
|
||||
|
||||
#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS
|
||||
int kho_debugfs_init(void);
|
||||
void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt);
|
||||
|
||||
@@ -230,17 +230,7 @@ int liveupdate_reboot(void)
|
||||
|
||||
luo_flb_serialize();
|
||||
|
||||
err = kho_finalize();
|
||||
if (err) {
|
||||
pr_err("kho_finalize failed %d\n", err);
|
||||
/*
|
||||
* kho_finalize() may return libfdt errors, to aboid passing to
|
||||
* userspace unknown errors, change this to EAGAIN.
|
||||
*/
|
||||
err = -EAGAIN;
|
||||
}
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
/* from arch/x86/include/asm/setup.h */
|
||||
#define COMMAND_LINE_SIZE 2048
|
||||
|
||||
#define KHO_FINALIZE "/debugfs/kho/out/finalize"
|
||||
#define KERNEL_IMAGE "/kernel"
|
||||
|
||||
static int mount_filesystems(void)
|
||||
@@ -22,22 +21,6 @@ static int mount_filesystems(void)
|
||||
return mount("proc", "/proc", "proc", 0, NULL);
|
||||
}
|
||||
|
||||
static int kho_enable(void)
|
||||
{
|
||||
const char enable[] = "1";
|
||||
int fd;
|
||||
|
||||
fd = open(KHO_FINALIZE, O_RDWR);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (write(fd, enable, sizeof(enable)) != sizeof(enable))
|
||||
return 1;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long kexec_file_load(int kernel_fd, int initrd_fd,
|
||||
unsigned long cmdline_len, const char *cmdline,
|
||||
unsigned long flags)
|
||||
@@ -78,9 +61,6 @@ int main(int argc, char *argv[])
|
||||
if (mount_filesystems())
|
||||
goto err_reboot;
|
||||
|
||||
if (kho_enable())
|
||||
goto err_reboot;
|
||||
|
||||
if (kexec_load())
|
||||
goto err_reboot;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user