bootmem and mem_map allocation problem

Nicolas Pitre (nico@cam.org)
Sun, 5 Dec 1999 23:18:19 -0500 (EST)


I'm currently re-integrating the StrongARM SA1100 support into 2.3.29 but
here is the problem:

Physical RAM banks are located at 0xc0000000, 0xc8000000, 0xd0000000 and
0xd8000000. The system I have contains 4 megs for each bank, but the
SA1100 can support many other configurations as well.

The bootmem allocator keep track of all physical ram pages linearly, which
is still OK since the holes between all banks are marked reserved.
However this represents a total of
((0xd8000000 + 4MB - 0xc0000000) >> PAGE_SHIFT) = 99328 pages total.

When it is time to allocate the mem_map array which is also indexing
physical pages, we have this:

/*
* Some architectures (with lots of mem and discontinous memory
* maps) have to search for a good mem_map area:
*/
map_size = totalpages*sizeof(struct page);
mem_map = (struct page *) alloc_bootmem(map_size);

map_size is then equal to 6754304 which is larger than a single ram
bank. Then, alloc_bootmem() fails since it can't find enough
contiguous memory.

Even if the mem_map "holes" can be freed later, the valuable
entries may not fit with the available memory layout, especially if we
want to keep the virt_to_phys()/phys_to_virt() macros simple.

Maybe the mem_map array could be indexed with virtual page location since
the virtual memory space is being compressed a bit, thus reducing the
number of entries required. However this would require modifications to
the free_all_bootmem() function which isn't architecture specific.

What should be the correct fix for this?

Also I needed this patch to make things work on a machine with a non
null physical memory offset:

--- ../2.3.29/linux/mm/bootmem.c Thu Dec 2 22:08:08 1999
+++ linux/mm/bootmem.c Sat Dec 4 14:17:24 1999
@@ -38,7 +38,7 @@
unsigned long mapsize = (pages+7)/8;

mem_start = mstart;
- bootmem_map = phys_to_virt(start << PAGE_SHIFT);
+ bootmem_map = phys_to_virt((start << PAGE_SHIFT) + mem_start);
max_low_pfn = pages;

/*
@@ -217,7 +217,7 @@
count++;
ClearPageReserved(page);
set_page_count(page, 1);
- if (i >= (virt_to_phys((char *)MAX_DMA_ADDRESS) >>
PAGE_SHIFT))
+ if (i >= MAP_NR(MAX_DMA_ADDRESS) )
clear_bit(PG_DMA, &page->flags);
__free_page(page);
}

Thanks.

Nicolas

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/