On Wed, Mar 11, 2026 at 01:46:09AM +0530, Mukesh Ojha wrote:
> From: Eugen Hristev <[email protected]>
> 
> With this driver, the registered regions are copied to a shared memory
> zone at register time. The shared memory zone is supplied via OF. This
> driver will select only regions that are of interest, and keep only
> addresses. The format of the list is Kinfo compatible, with devices like
> Google Pixel phone. The firmware is only interested in some symbols'
> addresses.
> 
> Signed-off-by: Eugen Hristev <[email protected]>
> Signed-off-by: Mukesh Ojha <[email protected]>
> ---
>  MAINTAINERS                |   1 +
>  drivers/of/platform.c      |   1 +
>  kernel/meminspect/Kconfig  |  11 ++
>  kernel/meminspect/Makefile |   1 +
>  kernel/meminspect/kinfo.c  | 284 
> +++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 298 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2504b7df0e7d..48b5457fae98 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -16597,6 +16597,7 @@ M:    Eugen Hristev <[email protected]>
>  M:   Mukesh Ojha <[email protected]>
>  S:   Maintained
>  F:   Documentation/devicetree/bindings/reserved-memory/google,kinfo.yaml
> +F:   kernel/meminspect/kinfo.c
>  
>  MEMBLOCK AND MEMORY MANAGEMENT INITIALIZATION
>  M:   Mike Rapoport <[email protected]>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 2a7111e8354d..09047e021de4 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -495,6 +495,7 @@ static const struct of_device_id reserved_mem_matches[] = 
> {
>       { .compatible = "ramoops" },
>       { .compatible = "nvmem-rmem" },
>       { .compatible = "google,open-dice" },
> +     { .compatible = "google,debug-kinfo" },

place it before open-dice

>       {}
>  };
>  
> diff --git a/kernel/meminspect/Kconfig b/kernel/meminspect/Kconfig
> index fa2b5a84b251..396510908e47 100644
> --- a/kernel/meminspect/Kconfig
> +++ b/kernel/meminspect/Kconfig
> @@ -17,3 +17,14 @@ config MEMINSPECT
>  
>         Note that modules using this feature must be rebuilt if option
>         changes.
> +
> +config MEMINSPECT_KINFO
> +     tristate "Shared memory KInfo compatible driver"
> +     depends on MEMINSPECT
> +     help
> +       Say y here to enable the Shared memory KInfo compatible driver
> +       With this driver, the registered regions are copied to a shared
> +       memory zone at register time.
> +       The shared memory zone is supplied via OF.
> +       This driver will select only regions that are of interest,
> +       and keep only addresses. The format of the list is Kinfo compatible.
> diff --git a/kernel/meminspect/Makefile b/kernel/meminspect/Makefile
> index 09fd55e6d9cf..283604d892e5 100644
> --- a/kernel/meminspect/Makefile
> +++ b/kernel/meminspect/Makefile
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  obj-$(CONFIG_MEMINSPECT) += meminspect.o
> +obj-$(CONFIG_MEMINSPECT_KINFO) += kinfo.o
> diff --git a/kernel/meminspect/kinfo.c b/kernel/meminspect/kinfo.c
> new file mode 100644
> index 000000000000..79918908968d
> --- /dev/null
> +++ b/kernel/meminspect/kinfo.c
> @@ -0,0 +1,284 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *
> + * Copyright 2002 Rusty Russell <[email protected]> IBM Corporation
> + * Copyright 2021 Google LLC
> + * Copyright 2025 Linaro Ltd. Eugen Hristev <[email protected]>
> + */
> +#include <linux/container_of.h>
> +#include <linux/kallsyms.h>
> +#include <linux/meminspect.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/utsname.h>
> +
> +#define BUILD_INFO_LEN               256
> +#define DEBUG_KINFO_MAGIC    0xcceeddff
> +
> +/*
> + * Header structure must be byte-packed, since the table is provided to
> + * bootloader.
> + */
> +struct kernel_info {
> +     /* For kallsyms */
> +     u8 enabled_all;
> +     u8 enabled_base_relative;
> +     u8 enabled_absolute_percpu;
> +     u8 enabled_cfi_clang;
> +     u32 num_syms;
> +     u16 name_len;
> +     u16 bit_per_long;
> +     u16 module_name_len;
> +     u16 symbol_len;
> +     u64 _relative_pa;
> +     u64 _text_pa;
> +     u64 _stext_pa;
> +     u64 _etext_pa;
> +     u64 _sinittext_pa;
> +     u64 _einittext_pa;
> +     u64 _end_pa;
> +     u64 _offsets_pa;
> +     u64 _names_pa;
> +     u64 _token_table_pa;
> +     u64 _token_index_pa;
> +     u64 _markers_pa;
> +     u64 _seqs_of_names_pa;
> +
> +     /* For frame pointer */
> +     u32 thread_size;
> +
> +     /* For virt_to_phys */
> +     u64 swapper_pg_dir_pa;
> +
> +     /* For linux banner */
> +     u8 last_uts_release[__NEW_UTS_LEN];
> +
> +     /* Info of running build */
> +     u8 build_info[BUILD_INFO_LEN];
> +
> +     /* For module kallsyms */
> +     u32 enabled_modules_tree_lookup;
> +     u32 mod_mem_offset;
> +     u32 mod_kallsyms_offset;
> +} __packed;
> +
> +struct kernel_all_info {
> +     u32 magic_number;
> +     u32 combined_checksum;
> +     struct kernel_info info;
> +} __packed;
> +
> +struct debug_kinfo {
> +     struct device *dev;
> +     void *all_info_addr;
> +     size_t all_info_size;
> +     struct notifier_block nb;
> +};
> +
> +static void update_kernel_all_info(struct kernel_all_info *all_info)
> +{
> +     struct kernel_info *info;
> +     u32 *checksum_info;
> +     int index;
> +
> +     all_info->magic_number = DEBUG_KINFO_MAGIC;
> +     all_info->combined_checksum = 0;
> +
> +     info = &all_info->info;
> +     checksum_info = (u32 *)info;
> +     for (index = 0; index < sizeof(*info) / sizeof(u32); index++)
> +             all_info->combined_checksum ^= checksum_info[index];
> +}
> +
> +static u8 global_build_info[BUILD_INFO_LEN];

Don't create singletons. That's a driver so you can have multiple
instances of it.

> +
> +static int build_info_set(const char *str, const struct kernel_param *kp)
> +{
> +     size_t build_info_size = sizeof(global_build_info);
> +
> +     if (strlen(str) > build_info_size)
> +             return -ENOMEM;
> +     memcpy(global_build_info, str, min(build_info_size - 1, strlen(str)));
> +     return 0;
> +}
> +
> +static const struct kernel_param_ops build_info_op = {
> +     .set = build_info_set,
> +};
> +
> +module_param_cb(build_info, &build_info_op, NULL, 0200);
> +MODULE_PARM_DESC(build_info, "Write build info to field 'build_info' of 
> debug kinfo.");

Drop. Build info is a static, fixed information, there is no need to write it
from user-space.


...

> +     memset(all_info, 0, sizeof(struct kernel_all_info));
> +     info = &all_info->info;
> +     info->enabled_all = IS_ENABLED(CONFIG_KALLSYMS_ALL);
> +     info->enabled_absolute_percpu = 
> IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU);
> +     info->enabled_base_relative = IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE);
> +     info->enabled_cfi_clang = IS_ENABLED(CONFIG_CFI_CLANG);
> +     info->name_len = KSYM_NAME_LEN;
> +     info->bit_per_long = BITS_PER_LONG;
> +     info->module_name_len = MODULE_NAME_LEN;
> +     info->symbol_len = KSYM_SYMBOL_LEN;
> +     info->thread_size = THREAD_SIZE;
> +     info->enabled_modules_tree_lookup = 
> IS_ENABLED(CONFIG_MODULES_TREE_LOOKUP);
> +     info->mod_mem_offset = offsetof(struct module, mem);
> +     info->mod_kallsyms_offset = offsetof(struct module, kallsyms);
> +
> +     memcpy(info->build_info, global_build_info, strlen(global_build_info));
> +
> +     kinfo->nb.notifier_call = kinfo_notifier_cb;
> +
> +     meminspect_notifier_register(&kinfo->nb);
> +     meminspect_lock_traverse(kinfo, register_kinfo_region);
> +
> +     return 0;
> +}
> +
> +static void debug_kinfo_remove(struct platform_device *pdev)
> +{
> +     struct debug_kinfo *kinfo = platform_get_drvdata(pdev);
> +
> +     meminspect_notifier_unregister(&kinfo->nb);
> +}
> +
> +static const struct of_device_id debug_kinfo_of_match[] = {
> +     { .compatible   = "google,debug-kinfo" },
> +     {},
> +};
> +MODULE_DEVICE_TABLE(of, debug_kinfo_of_match);
> +
> +static struct platform_driver debug_kinfo_driver = {
> +     .probe = debug_kinfo_probe,
> +     .remove = debug_kinfo_remove,
> +     .driver = {
> +             .name = "debug-kinfo",
> +             .of_match_table = of_match_ptr(debug_kinfo_of_match),

Drop of_match_ptr, you have warning here.

> +     },
> +};
> +module_platform_driver(debug_kinfo_driver);
> +
> +MODULE_AUTHOR("Eugen Hristev <[email protected]>");
> +MODULE_AUTHOR("Jone Chou <[email protected]>");
> +MODULE_DESCRIPTION("meminspect Kinfo Driver");
> +MODULE_LICENSE("GPL");
> 
> -- 
> 2.50.1
> 

Reply via email to