mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 02:44:41 +01:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
221 lines
4.6 KiB
C
221 lines
4.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* kexec_handover_debugfs.c - kexec handover debugfs interfaces
|
|
* Copyright (C) 2023 Alexander Graf <graf@amazon.com>
|
|
* Copyright (C) 2025 Microsoft Corporation, Mike Rapoport <rppt@kernel.org>
|
|
* Copyright (C) 2025 Google LLC, Changyuan Lyu <changyuanl@google.com>
|
|
* Copyright (C) 2025 Google LLC, Pasha Tatashin <pasha.tatashin@soleen.com>
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "KHO: " fmt
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/libfdt.h>
|
|
#include <linux/mm.h>
|
|
#include "kexec_handover_internal.h"
|
|
|
|
static struct dentry *debugfs_root;
|
|
|
|
struct fdt_debugfs {
|
|
struct list_head list;
|
|
struct debugfs_blob_wrapper wrapper;
|
|
struct dentry *file;
|
|
};
|
|
|
|
static int __kho_debugfs_fdt_add(struct list_head *list, struct dentry *dir,
|
|
const char *name, const void *fdt)
|
|
{
|
|
struct fdt_debugfs *f;
|
|
struct dentry *file;
|
|
|
|
f = kmalloc_obj(*f);
|
|
if (!f)
|
|
return -ENOMEM;
|
|
|
|
f->wrapper.data = (void *)fdt;
|
|
f->wrapper.size = fdt_totalsize(fdt);
|
|
|
|
file = debugfs_create_blob(name, 0400, dir, &f->wrapper);
|
|
if (IS_ERR(file)) {
|
|
kfree(f);
|
|
return PTR_ERR(file);
|
|
}
|
|
|
|
f->file = file;
|
|
list_add(&f->list, list);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name,
|
|
const void *fdt, bool root)
|
|
{
|
|
struct dentry *dir;
|
|
|
|
if (root)
|
|
dir = dbg->dir;
|
|
else
|
|
dir = dbg->sub_fdt_dir;
|
|
|
|
return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt);
|
|
}
|
|
|
|
void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt)
|
|
{
|
|
struct fdt_debugfs *ff;
|
|
|
|
list_for_each_entry(ff, &dbg->fdt_list, list) {
|
|
if (ff->wrapper.data == fdt) {
|
|
debugfs_remove(ff->file);
|
|
list_del(&ff->list);
|
|
kfree(ff);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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++)
|
|
seq_printf(m, "0x%llx\n", kho_scratch[i].addr);
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(scratch_phys);
|
|
|
|
static int scratch_len_show(struct seq_file *m, void *v)
|
|
{
|
|
for (int i = 0; i < kho_scratch_cnt; i++)
|
|
seq_printf(m, "0x%llx\n", kho_scratch[i].size);
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(scratch_len);
|
|
|
|
__init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt)
|
|
{
|
|
struct dentry *dir, *sub_fdt_dir;
|
|
int err, child;
|
|
|
|
INIT_LIST_HEAD(&dbg->fdt_list);
|
|
|
|
dir = debugfs_create_dir("in", debugfs_root);
|
|
if (IS_ERR(dir)) {
|
|
err = PTR_ERR(dir);
|
|
goto err_out;
|
|
}
|
|
|
|
sub_fdt_dir = debugfs_create_dir("sub_fdts", dir);
|
|
if (IS_ERR(sub_fdt_dir)) {
|
|
err = PTR_ERR(sub_fdt_dir);
|
|
goto err_rmdir;
|
|
}
|
|
|
|
err = __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt);
|
|
if (err)
|
|
goto err_rmdir;
|
|
|
|
fdt_for_each_subnode(child, fdt, 0) {
|
|
int len = 0;
|
|
const char *name = fdt_get_name(fdt, child, NULL);
|
|
const u64 *fdt_phys;
|
|
|
|
fdt_phys = fdt_getprop(fdt, child, "fdt", &len);
|
|
if (!fdt_phys)
|
|
continue;
|
|
if (len != sizeof(*fdt_phys)) {
|
|
pr_warn("node %s prop fdt has invalid length: %d\n",
|
|
name, len);
|
|
continue;
|
|
}
|
|
err = __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name,
|
|
phys_to_virt(*fdt_phys));
|
|
if (err) {
|
|
pr_warn("failed to add fdt %s to debugfs: %pe\n", name,
|
|
ERR_PTR(err));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
dbg->dir = dir;
|
|
dbg->sub_fdt_dir = sub_fdt_dir;
|
|
|
|
return;
|
|
err_rmdir:
|
|
debugfs_remove_recursive(dir);
|
|
err_out:
|
|
/*
|
|
* Failure to create /sys/kernel/debug/kho/in does not prevent
|
|
* reviving state from KHO and setting up KHO for the next
|
|
* kexec.
|
|
*/
|
|
if (err) {
|
|
pr_err("failed exposing handover FDT in debugfs: %pe\n",
|
|
ERR_PTR(err));
|
|
}
|
|
}
|
|
|
|
__init int kho_out_debugfs_init(struct kho_debugfs *dbg)
|
|
{
|
|
struct dentry *dir, *f, *sub_fdt_dir;
|
|
|
|
INIT_LIST_HEAD(&dbg->fdt_list);
|
|
|
|
dir = debugfs_create_dir("out", debugfs_root);
|
|
if (IS_ERR(dir))
|
|
return -ENOMEM;
|
|
|
|
sub_fdt_dir = debugfs_create_dir("sub_fdts", dir);
|
|
if (IS_ERR(sub_fdt_dir))
|
|
goto err_rmdir;
|
|
|
|
f = debugfs_create_file("scratch_phys", 0400, dir, NULL,
|
|
&scratch_phys_fops);
|
|
if (IS_ERR(f))
|
|
goto err_rmdir;
|
|
|
|
f = debugfs_create_file("scratch_len", 0400, dir, NULL,
|
|
&scratch_len_fops);
|
|
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;
|
|
|
|
err_rmdir:
|
|
debugfs_remove_recursive(dir);
|
|
return -ENOENT;
|
|
}
|
|
|
|
__init int kho_debugfs_init(void)
|
|
{
|
|
debugfs_root = debugfs_create_dir("kho", NULL);
|
|
if (IS_ERR(debugfs_root))
|
|
return -ENOENT;
|
|
return 0;
|
|
}
|