@@ -152,6 +152,35 @@ void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_add
152152 add_memory_region (start , size , BOOT_MEM_RAM );
153153}
154154
155+ bool __init memory_region_available (phys_addr_t start , phys_addr_t size )
156+ {
157+ int i ;
158+ bool in_ram = false, free = true;
159+
160+ for (i = 0 ; i < boot_mem_map .nr_map ; i ++ ) {
161+ phys_addr_t start_ , end_ ;
162+
163+ start_ = boot_mem_map .map [i ].addr ;
164+ end_ = boot_mem_map .map [i ].addr + boot_mem_map .map [i ].size ;
165+
166+ switch (boot_mem_map .map [i ].type ) {
167+ case BOOT_MEM_RAM :
168+ if (start >= start_ && start + size <= end_ )
169+ in_ram = true;
170+ break ;
171+ case BOOT_MEM_RESERVED :
172+ if ((start >= start_ && start < end_ ) ||
173+ (start < start_ && start + size >= start_ ))
174+ free = false;
175+ break ;
176+ default :
177+ continue ;
178+ }
179+ }
180+
181+ return in_ram && free ;
182+ }
183+
155184static void __init print_memory_map (void )
156185{
157186 int i ;
@@ -300,11 +329,19 @@ static void __init bootmem_init(void)
300329
301330#else /* !CONFIG_SGI_IP27 */
302331
332+ static unsigned long __init bootmap_bytes (unsigned long pages )
333+ {
334+ unsigned long bytes = DIV_ROUND_UP (pages , 8 );
335+
336+ return ALIGN (bytes , sizeof (long ));
337+ }
338+
303339static void __init bootmem_init (void )
304340{
305341 unsigned long reserved_end ;
306342 unsigned long mapstart = ~0UL ;
307343 unsigned long bootmap_size ;
344+ bool bootmap_valid = false;
308345 int i ;
309346
310347 /*
@@ -385,11 +422,42 @@ static void __init bootmem_init(void)
385422#endif
386423
387424 /*
388- * Initialize the boot-time allocator with low memory only.
425+ * check that mapstart doesn't overlap with any of
426+ * memory regions that have been reserved through eg. DTB
389427 */
390- bootmap_size = init_bootmem_node (NODE_DATA (0 ), mapstart ,
391- min_low_pfn , max_low_pfn );
428+ bootmap_size = bootmap_bytes (max_low_pfn - min_low_pfn );
429+
430+ bootmap_valid = memory_region_available (PFN_PHYS (mapstart ),
431+ bootmap_size );
432+ for (i = 0 ; i < boot_mem_map .nr_map && !bootmap_valid ; i ++ ) {
433+ unsigned long mapstart_addr ;
434+
435+ switch (boot_mem_map .map [i ].type ) {
436+ case BOOT_MEM_RESERVED :
437+ mapstart_addr = PFN_ALIGN (boot_mem_map .map [i ].addr +
438+ boot_mem_map .map [i ].size );
439+ if (PHYS_PFN (mapstart_addr ) < mapstart )
440+ break ;
441+
442+ bootmap_valid = memory_region_available (mapstart_addr ,
443+ bootmap_size );
444+ if (bootmap_valid )
445+ mapstart = PHYS_PFN (mapstart_addr );
446+ break ;
447+ default :
448+ break ;
449+ }
450+ }
392451
452+ if (!bootmap_valid )
453+ panic ("No memory area to place a bootmap bitmap" );
454+
455+ /*
456+ * Initialize the boot-time allocator with low memory only.
457+ */
458+ if (bootmap_size != init_bootmem_node (NODE_DATA (0 ), mapstart ,
459+ min_low_pfn , max_low_pfn ))
460+ panic ("Unexpected memory size required for bootmap" );
393461
394462 for (i = 0 ; i < boot_mem_map .nr_map ; i ++ ) {
395463 unsigned long start , end ;
@@ -438,6 +506,10 @@ static void __init bootmem_init(void)
438506 continue ;
439507 default :
440508 /* Not usable memory */
509+ if (start > min_low_pfn && end < max_low_pfn )
510+ reserve_bootmem (boot_mem_map .map [i ].addr ,
511+ boot_mem_map .map [i ].size ,
512+ BOOTMEM_DEFAULT );
441513 continue ;
442514 }
443515
0 commit comments