@@ -114,12 +114,10 @@ static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS
114114
115115struct memblock memblock __initdata_memblock = {
116116 .memory .regions = memblock_memory_init_regions ,
117- .memory .cnt = 1 , /* empty dummy entry */
118117 .memory .max = INIT_MEMBLOCK_MEMORY_REGIONS ,
119118 .memory .name = "memory" ,
120119
121120 .reserved .regions = memblock_reserved_init_regions ,
122- .reserved .cnt = 1 , /* empty dummy entry */
123121 .reserved .max = INIT_MEMBLOCK_RESERVED_REGIONS ,
124122 .reserved .name = "reserved" ,
125123
@@ -130,7 +128,6 @@ struct memblock memblock __initdata_memblock = {
130128#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
131129struct memblock_type physmem = {
132130 .regions = memblock_physmem_init_regions ,
133- .cnt = 1 , /* empty dummy entry */
134131 .max = INIT_PHYSMEM_REGIONS ,
135132 .name = "physmem" ,
136133};
@@ -197,8 +194,8 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
197194 for (i = 0 ; i < type -> cnt ; i ++ )
198195 if (memblock_addrs_overlap (base , size , type -> regions [i ].base ,
199196 type -> regions [i ].size ))
200- break ;
201- return i < type -> cnt ;
197+ return true ;
198+ return false ;
202199}
203200
204201/**
@@ -356,7 +353,6 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
356353 /* Special case for empty arrays */
357354 if (type -> cnt == 0 ) {
358355 WARN_ON (type -> total_size != 0 );
359- type -> cnt = 1 ;
360356 type -> regions [0 ].base = 0 ;
361357 type -> regions [0 ].size = 0 ;
362358 type -> regions [0 ].flags = 0 ;
@@ -600,12 +596,13 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
600596
601597 /* special case for empty array */
602598 if (type -> regions [0 ].size == 0 ) {
603- WARN_ON (type -> cnt != 1 || type -> total_size );
599+ WARN_ON (type -> cnt != 0 || type -> total_size );
604600 type -> regions [0 ].base = base ;
605601 type -> regions [0 ].size = size ;
606602 type -> regions [0 ].flags = flags ;
607603 memblock_set_region_node (& type -> regions [0 ], nid );
608604 type -> total_size = size ;
605+ type -> cnt = 1 ;
609606 return 0 ;
610607 }
611608
@@ -780,7 +777,8 @@ bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_byt
780777 * Walk @type and ensure that regions don't cross the boundaries defined by
781778 * [@base, @base + @size). Crossing regions are split at the boundaries,
782779 * which may create at most two more regions. The index of the first
783- * region inside the range is returned in *@start_rgn and end in *@end_rgn.
780+ * region inside the range is returned in *@start_rgn and the index of the
781+ * first region after the range is returned in *@end_rgn.
784782 *
785783 * Return:
786784 * 0 on success, -errno on failure.
@@ -1441,6 +1439,17 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
14411439 enum memblock_flags flags = choose_memblock_flags ();
14421440 phys_addr_t found ;
14431441
1442+ /*
1443+ * Detect any accidental use of these APIs after slab is ready, as at
1444+ * this moment memblock may be deinitialized already and its
1445+ * internal data may be destroyed (after execution of memblock_free_all)
1446+ */
1447+ if (WARN_ON_ONCE (slab_is_available ())) {
1448+ void * vaddr = kzalloc_node (size , GFP_NOWAIT , nid );
1449+
1450+ return vaddr ? virt_to_phys (vaddr ) : 0 ;
1451+ }
1452+
14441453 if (!align ) {
14451454 /* Can't use WARNs this early in boot on powerpc */
14461455 dump_stack ();
@@ -1566,13 +1575,6 @@ static void * __init memblock_alloc_internal(
15661575{
15671576 phys_addr_t alloc ;
15681577
1569- /*
1570- * Detect any accidental use of these APIs after slab is ready, as at
1571- * this moment memblock may be deinitialized already and its
1572- * internal data may be destroyed (after execution of memblock_free_all)
1573- */
1574- if (WARN_ON_ONCE (slab_is_available ()))
1575- return kzalloc_node (size , GFP_NOWAIT , nid );
15761578
15771579 if (max_addr > memblock .current_limit )
15781580 max_addr = memblock .current_limit ;
@@ -2031,7 +2033,7 @@ static void __init free_memmap(unsigned long start_pfn, unsigned long end_pfn)
20312033 * downwards.
20322034 */
20332035 pg = PAGE_ALIGN (__pa (start_pg ));
2034- pgend = __pa (end_pg ) & PAGE_MASK ;
2036+ pgend = PAGE_ALIGN_DOWN ( __pa (end_pg )) ;
20352037
20362038 /*
20372039 * If there are free pages between these, free the section of the
@@ -2234,6 +2236,123 @@ void __init memblock_free_all(void)
22342236 totalram_pages_add (pages );
22352237}
22362238
2239+ /* Keep a table to reserve named memory */
2240+ #define RESERVE_MEM_MAX_ENTRIES 8
2241+ #define RESERVE_MEM_NAME_SIZE 16
2242+ struct reserve_mem_table {
2243+ char name [RESERVE_MEM_NAME_SIZE ];
2244+ phys_addr_t start ;
2245+ phys_addr_t size ;
2246+ };
2247+ static struct reserve_mem_table reserved_mem_table [RESERVE_MEM_MAX_ENTRIES ];
2248+ static int reserved_mem_count ;
2249+
2250+ /* Add wildcard region with a lookup name */
2251+ static void __init reserved_mem_add (phys_addr_t start , phys_addr_t size ,
2252+ const char * name )
2253+ {
2254+ struct reserve_mem_table * map ;
2255+
2256+ map = & reserved_mem_table [reserved_mem_count ++ ];
2257+ map -> start = start ;
2258+ map -> size = size ;
2259+ strscpy (map -> name , name );
2260+ }
2261+
2262+ /**
2263+ * reserve_mem_find_by_name - Find reserved memory region with a given name
2264+ * @name: The name that is attached to a reserved memory region
2265+ * @start: If found, holds the start address
2266+ * @size: If found, holds the size of the address.
2267+ *
2268+ * @start and @size are only updated if @name is found.
2269+ *
2270+ * Returns: 1 if found or 0 if not found.
2271+ */
2272+ int reserve_mem_find_by_name (const char * name , phys_addr_t * start , phys_addr_t * size )
2273+ {
2274+ struct reserve_mem_table * map ;
2275+ int i ;
2276+
2277+ for (i = 0 ; i < reserved_mem_count ; i ++ ) {
2278+ map = & reserved_mem_table [i ];
2279+ if (!map -> size )
2280+ continue ;
2281+ if (strcmp (name , map -> name ) == 0 ) {
2282+ * start = map -> start ;
2283+ * size = map -> size ;
2284+ return 1 ;
2285+ }
2286+ }
2287+ return 0 ;
2288+ }
2289+ EXPORT_SYMBOL_GPL (reserve_mem_find_by_name );
2290+
2291+ /*
2292+ * Parse reserve_mem=nn:align:name
2293+ */
2294+ static int __init reserve_mem (char * p )
2295+ {
2296+ phys_addr_t start , size , align , tmp ;
2297+ char * name ;
2298+ char * oldp ;
2299+ int len ;
2300+
2301+ if (!p )
2302+ return - EINVAL ;
2303+
2304+ /* Check if there's room for more reserved memory */
2305+ if (reserved_mem_count >= RESERVE_MEM_MAX_ENTRIES )
2306+ return - EBUSY ;
2307+
2308+ oldp = p ;
2309+ size = memparse (p , & p );
2310+ if (!size || p == oldp )
2311+ return - EINVAL ;
2312+
2313+ if (* p != ':' )
2314+ return - EINVAL ;
2315+
2316+ align = memparse (p + 1 , & p );
2317+ if (* p != ':' )
2318+ return - EINVAL ;
2319+
2320+ /*
2321+ * memblock_phys_alloc() doesn't like a zero size align,
2322+ * but it is OK for this command to have it.
2323+ */
2324+ if (align < SMP_CACHE_BYTES )
2325+ align = SMP_CACHE_BYTES ;
2326+
2327+ name = p + 1 ;
2328+ len = strlen (name );
2329+
2330+ /* name needs to have length but not too big */
2331+ if (!len || len >= RESERVE_MEM_NAME_SIZE )
2332+ return - EINVAL ;
2333+
2334+ /* Make sure that name has text */
2335+ for (p = name ; * p ; p ++ ) {
2336+ if (!isspace (* p ))
2337+ break ;
2338+ }
2339+ if (!* p )
2340+ return - EINVAL ;
2341+
2342+ /* Make sure the name is not already used */
2343+ if (reserve_mem_find_by_name (name , & start , & tmp ))
2344+ return - EBUSY ;
2345+
2346+ start = memblock_phys_alloc (size , align );
2347+ if (!start )
2348+ return - ENOMEM ;
2349+
2350+ reserved_mem_add (start , size , name );
2351+
2352+ return 1 ;
2353+ }
2354+ __setup ("reserve_mem=" , reserve_mem );
2355+
22372356#if defined(CONFIG_DEBUG_FS ) && defined(CONFIG_ARCH_KEEP_MEMBLOCK )
22382357static const char * const flagname [] = {
22392358 [ilog2 (MEMBLOCK_HOTPLUG )] = "HOTPLUG" ,
0 commit comments