On Wed, 12 Jun 2024 07:23:40 +0000 Wei Yang <richard.weiyang@xxxxxxxxx> wrote: > >> >+struct reserve_mem_table { > >> >+ char name[RESERVE_MEM_NAME_SIZE]; > >> >+ unsigned long start; > >> >+ unsigned long size; > >> > >> phys_addr_t looks more precise? > > > >For just the start variable, correct? I'm OK with updating that. > > > > Both start and size. When you look at the definition of memblock_region, both > are defined as phys_addr_t. I ended up keeping everything phys_addr_t. > > >> > >> >+}; > >> >+static struct reserve_mem_table reserved_mem_table[RESERVE_MEM_MAX_ENTRIES]; > >> >+static int reserved_mem_count; > >> > >> Seems no matter we use this feature or not, these memory would be occupied? > > > >Yes, because allocation may screw it up as well. I could add a CONFIG > >around it, so that those that do not want this could configure it out. But > >since it's just a total of (16 + 8 + 8) * 8 = 256 bytes, I'm not sure it's > >much of a worry to add the complexities to save that much space. As the > >code to save it may likely be bigger. > > > > If Mike feel good to it, I am ok. > > >> > >> >+ > >> >+/* 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; > >> > >> return ENOSPC? Not good at it, but a raw value maybe not a good practice. > > > >This is what gets returned by the command line parser. It only cares if it > >is zero or not. > > > >> > >> Also, we'd better do this check before allocation. > > > >What allocation? > > > > You call reserved_mem_add() after memblock_phys_alloc(). > My suggestion is do those sanity check before calling memblock_phys_alloc(). Yeah, I did add more checks before the allocation happens. > > >> > >> >+ > >> >+ 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 > >> > >> early_reserve_mem or reserve_mem ? > > > >Oops, that was the original name. I'll change that. > > > >> > >> >+ */ > >> >+static int __init reserve_mem(char *p) > >> >+{ > >> >+ phys_addr_t start, size, align; > > > >Hmm, I wonder if I should change size and align to unsigned long? > > > > I grep the kernel, some use u64, some use unsigned long. > I think it is ok to use unsigned long here. For consistency, I switched them all to phys_addr_t. > > >> >+ 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; > >> >+ > >> > >> Better to check if the name is valid here. > > > >You mean that it has text and is not blank? > > > >> > >> Make sure command line parameters are valid before doing the allocation. > > > >You mean that size is non zero? > > > > I mean do those sanity check before real allocation. Yep, I hope I caught everything (of course I need to check if the name exists first). > > >I don't know if we care what the align is. Zero is valid. > > > > memblock internal would check the alignment. If it is zero, it will change to > SMP_CACHE_BYTES with dump_stack(). I saw that and added: if (align < SMP_CACHE_BYTES) align = SMP_CACHE_BYTES; so that SMP_CACHE_BYTES will be the minimum alignment. Thanks for looking at this. -- Steve