On Wed, Jun 12, 2024 at 08:34:36PM -0400, Steven Rostedt wrote:
> From: "Steven Rostedt (Google)" <rost...@goodmis.org>
> 
> In order to allow for requesting a memory region that can be used for
> things like pstore on multiple machines where the memory layout is not the
> same, add a new option to the kernel command line called "reserve_mem".
> 
> The format is:  reserve_mem=nn:align:name
> 
> Where it will find nn amount of memory at the given alignment of align.
> The name field is to allow another subsystem to retrieve where the memory
> was found. For example:
> 
>   reserve_mem=12M:4096:oops ramoops.mem_name=oops
> 
> Where ramoops.mem_name will tell ramoops that memory was reserved for it
> via the reserve_mem option and it can find it by calling:
> 
>   if (reserve_mem_find_by_name("oops", &start, &size)) {
>       // start holds the start address and size holds the size given
> 
> This is typically used for systems that do not wipe the RAM, and this
> command line will try to reserve the same physical memory on soft reboots.
> Note, it is not guaranteed to be the same location. For example, if KASLR
> places the kernel at the location of where the RAM reservation was from a
> previous boot, the new reservation will be at a different location.  Any
> subsystem using this feature must add a way to verify that the contents of
> the physical memory is from a previous boot, as there may be cases where
> the memory will not be located at the same location.
> 
> Not all systems may work either. There could be bit flips if the reboot
> goes through the BIOS. Using kexec to reboot the machine is likely to
> have better results in such cases.
> 
> Link: https://lore.kernel.org/all/zjjvnzux3nzig...@kernel.org/
> 
> Suggested-by: Mike Rapoport <r...@kernel.org>
> Tested-by: Guilherme G. Piccoli <gpicc...@igalia.com>
> Signed-off-by: Steven Rostedt (Google) <rost...@goodmis.org>
> ---
> Changes since v4: 
> https://lore.kernel.org/linux-trace-kernel/20240611215801.443593...@goodmis.org
> 
> - Add all checks about reserve_mem before allocation.
>   This means reserved_mem_add() is now a void function.
> 
> - Check for name duplications.
> 
> - Fix compare of align to SMP_CACHE_BYTES ("<" instead of "<=")
> 
>  .../admin-guide/kernel-parameters.txt         |  20 +++
>  include/linux/mm.h                            |   2 +
>  mm/memblock.c                                 | 117 ++++++++++++++++++
>  3 files changed, 139 insertions(+)
> 
> diff --git a/mm/memblock.c b/mm/memblock.c
> index d09136e040d3..739d106a9165 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c

...

> +/*
> + * Parse reserve_mem=nn:align:name
> + */
> +static int __init reserve_mem(char *p)
> +{
> +     phys_addr_t start, size, align;
> +     char *name;
> +     char *oldp;
> +     int len;
> +
> +     if (!p)
> +             return -EINVAL;
> +
> +     /* Check if there's room for more reserved memory */
> +     if (reserved_mem_count >= RESERVE_MEM_MAX_ENTRIES)
> +             return -EBUSY;
> +
> +     oldp = p;
> +     size = memparse(p, &p);
> +     if (!size || p == oldp)
> +             return -EINVAL;
> +
> +     if (*p != ':')
> +             return -EINVAL;
> +
> +     align = memparse(p+1, &p);
> +     if (*p != ':')
> +             return -EINVAL;
> +
> +     /*
> +      * memblock_phys_alloc() doesn't like a zero size align,
> +      * but it is OK for this command to have it.
> +      */
> +     if (align < SMP_CACHE_BYTES)
> +             align = SMP_CACHE_BYTES;
> +
> +     name = p + 1;
> +     len = strlen(name);
> +
> +     /* name needs to have length but not too big */
> +     if (!len || len >= RESERVE_MEM_NAME_SIZE)
> +             return -EINVAL;
> +
> +     /* Make sure that name has text */
> +     for (p = name; *p; p++) {
> +             if (!isspace(*p))
> +                     break;
> +     }
> +     if (!*p)
> +             return -EINVAL;
> +
> +     /* Make sure the name is not already used (size is only updated if 
> found) */
> +     if (reserve_mem_find_by_name(name, &start, &size))
> +             return -EBUSY;

I'd prefer another variable here rather than size. Will be more robust IMO.

> +
> +     start = memblock_phys_alloc(size, align);
> +     if (!start)
> +             return -ENOMEM;
> +
> +     reserved_mem_add(start, size, name);
> +
> +     return 0;
> +}
> +__setup("reserve_mem=", reserve_mem);
> +
>  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK)
>  static const char * const flagname[] = {
>       [ilog2(MEMBLOCK_HOTPLUG)] = "HOTPLUG",
> -- 
> 2.43.0
> 
> 

-- 
Sincerely yours,
Mike.

Reply via email to