On June 3, 2024 4:33:31 PM PDT, Steven Rostedt <rostedt@xxxxxxxxxxx> wrote: >From: "Steven Rostedt (Google)" <rostedt@xxxxxxxxxxx> > >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 How does this interact with KASLR? It has chosen its physical location before this parsing happens, so I'd expect this to fail once in a while, unless the size/alignment is lucky enough that KASLR never uses that portion of the physical memory... -Kees > >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 > >Link: https://lore.kernel.org/all/ZjJVnZUX3NZiGW6q@xxxxxxxxxx/ > >Suggested-by: Mike Rapoport <rppt@xxxxxxxxxx> >Signed-off-by: Steven Rostedt (Google) <rostedt@xxxxxxxxxxx> >--- > include/linux/mm.h | 2 + > mm/memblock.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+) > >diff --git a/include/linux/mm.h b/include/linux/mm.h >index 9849dfda44d4..b4455cc02f2c 100644 >--- a/include/linux/mm.h >+++ b/include/linux/mm.h >@@ -4263,4 +4263,6 @@ static inline bool pfn_is_unaccepted_memory(unsigned long pfn) > void vma_pgtable_walk_begin(struct vm_area_struct *vma); > void vma_pgtable_walk_end(struct vm_area_struct *vma); > >+int reserve_mem_find_by_name(const char *name, unsigned long *start, unsigned long *size); >+ > #endif /* _LINUX_MM_H */ >diff --git a/mm/memblock.c b/mm/memblock.c >index d09136e040d3..a8bf0ee9e2b4 100644 >--- a/mm/memblock.c >+++ b/mm/memblock.c >@@ -2244,6 +2244,103 @@ void __init memblock_free_all(void) > totalram_pages_add(pages); > } > >+/* Keep a table to reserve named memory */ >+#define RESERVE_MEM_MAX_ENTRIES 8 >+#define RESERVE_MEM_NAME_SIZE 16 >+struct reserve_mem_table { >+ char name[RESERVE_MEM_NAME_SIZE]; >+ unsigned long start; >+ unsigned long size; >+}; >+static struct reserve_mem_table reserved_mem_table[RESERVE_MEM_MAX_ENTRIES]; >+static int reserved_mem_count; >+ >+/* Add wildcard region with a lookup name */ >+static int __init reserved_mem_add(unsigned long start, unsigned long size, >+ const char *name) >+{ >+ struct reserve_mem_table *map; >+ >+ if (!name || !name[0] || strlen(name) >= RESERVE_MEM_NAME_SIZE) >+ return -EINVAL; >+ >+ if (reserved_mem_count >= RESERVE_MEM_MAX_ENTRIES) >+ return -1; >+ >+ map = &reserved_mem_table[reserved_mem_count++]; >+ map->start = start; >+ map->size = size; >+ strscpy(map->name, name); >+ return 0; >+} >+ >+/** >+ * reserve_mem_find_by_name - Find reserved memory region with a given name >+ * @name: The name that is attached to a reserved memory region >+ * @start: If found, holds the start address >+ * @size: If found, holds the size of the address. >+ * >+ * Returns: 1 if found or 0 if not found. >+ */ >+int reserve_mem_find_by_name(const char *name, unsigned long *start, unsigned long *size) >+{ >+ struct reserve_mem_table *map; >+ int i; >+ >+ for (i = 0; i < reserved_mem_count; i++) { >+ map = &reserved_mem_table[i]; >+ if (!map->size) >+ continue; >+ if (strcmp(name, map->name) == 0) { >+ *start = map->start; >+ *size = map->size; >+ return 1; >+ } >+ } >+ return 0; >+} >+ >+/* >+ * Parse early_reserve_mem=nn:align:name >+ */ >+static int __init reserve_mem(char *p) >+{ >+ phys_addr_t start, size, align; >+ char *oldp; >+ int err; >+ >+ if (!p) >+ return -EINVAL; >+ >+ oldp = p; >+ size = memparse(p, &p); >+ if (p == oldp) >+ return -EINVAL; >+ >+ if (*p != ':') >+ return -EINVAL; >+ >+ align = memparse(p+1, &p); >+ if (*p != ':') >+ return -EINVAL; >+ >+ start = memblock_phys_alloc(size, align); >+ if (!start) >+ return -ENOMEM; >+ >+ p++; >+ err = reserved_mem_add(start, size, p); >+ if (err) { >+ memblock_phys_free(start, size); >+ return err; >+ } >+ >+ p += strlen(p); >+ >+ return *p == '\0' ? 0: -EINVAL; >+} >+__setup("reserve_mem=", reserve_mem); >+ > #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK) > static const char * const flagname[] = { > [ilog2(MEMBLOCK_HOTPLUG)] = "HOTPLUG", -- Kees Cook