lkml.org 
[lkml]   [1999]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch] bootmem-2.3.30-C4

On Fri, 26 Nov 1999, NIIBE Yutaka wrote:

> In the patch, I added a argument for init_bootmem so that bootmem can work
> with machine with physical memory offset.

yep - thanks for the patch. I've ported it to 2.3.30-pre2, plus did some
more bootmem cleanups (patch attached). Changes:

- physical memory offset works just fine on x86, but obviously i cannot
test it with a real physical memory offset part.

- i've also changed the bootmem.h API to always deal with pfn numbers.
Unfortunately this breaks other architectures but should be the last
such case. It was getting unmaintainable that some functions wanted to
have a byte offset argument, some others used pfns. This also
simplified things.

- x86 now too first searches for a valid memory area to put the bootmem
map into, no more magic assumptions.

Does this have all the components you needed?

-- mingo
--- linux/mm/bootmem.c.orig Fri Nov 26 06:11:29 1999
+++ linux/mm/bootmem.c Fri Nov 26 06:12:06 1999
@@ -27,15 +27,17 @@
unsigned long max_low_pfn;

static void * bootmem_map = NULL;
+static unsigned long phys_mem_start;

-/* return the number of _pages_ that will be allocated for the boot bitmap */
+/*
+ * Return the number of pages that will be allocated for the boot bitmap
+ */
unsigned long __init bootmem_bootmap_pages (unsigned long pages)
{
unsigned long mapsize;

mapsize = (pages+7)/8;
- mapsize = (mapsize + ~PAGE_MASK) & PAGE_MASK;
- mapsize >>= PAGE_SHIFT;
+ mapsize = (mapsize + PAGE_SIZE-1) >> PAGE_SHIFT;

return mapsize;
}
@@ -43,20 +45,20 @@
/*
* Called once to set up the allocator itself.
*/
-unsigned long __init init_bootmem (unsigned long start, unsigned long pages)
+void __init init_bootmem (unsigned long bootmap_pfn,
+ unsigned long mempages, unsigned long memstart_pfn)
{
- unsigned long mapsize = (pages+7)/8;
+ unsigned long mapsize = bootmem_bootmap_pages(mempages) << PAGE_SHIFT;

- bootmem_map = phys_to_virt(start << PAGE_SHIFT);
- max_low_pfn = pages;
+ phys_mem_start = memstart_pfn;
+ bootmem_map = phys_to_virt((bootmap_pfn * PAGE_SIZE) + phys_mem_start);
+ max_low_pfn = mempages;

/*
* Initially all pages are reserved - setup_arch() has to
* register free RAM areas explicitly.
*/
memset(bootmem_map, 0xff, mapsize);
-
- return mapsize;
}

/*
@@ -64,44 +66,35 @@
* might be used for boot-time allocations - or it might get added
* to the free page pool later on.
*/
-void __init reserve_bootmem (unsigned long addr, unsigned long size)
+void __init reserve_bootmem (unsigned long start_pfn, unsigned long pages)
{
unsigned long i;
/*
* round up, partially reserved pages are considered
* fully reserved.
*/
- unsigned long end = (addr + size + PAGE_SIZE-1)/PAGE_SIZE;
+ unsigned long end_pfn = start_pfn + pages;

- if (!size) BUG();
+ if (!pages) BUG();

- if (end > max_low_pfn)
+ if (end_pfn > max_low_pfn)
BUG();
- for (i = addr/PAGE_SIZE; i < end; i++)
+ for (i = start_pfn; i < end_pfn; i++)
if (test_and_set_bit(i, bootmem_map))
BUG();
}

-void __init free_bootmem (unsigned long addr, unsigned long size)
+void __init free_bootmem (unsigned long start_pfn, unsigned long pages)
{
- unsigned long i;
- unsigned long start;
- /*
- * round down end of usable mem, partially free pages are
- * considered reserved.
- */
- unsigned long end = (addr + size)/PAGE_SIZE;
+ unsigned long i, end_pfn;

- if (!size) BUG();
- if (end > max_low_pfn)
- BUG();
+ end_pfn = start_pfn + pages;

- /*
- * Round up the beginning of the address.
- */
- start = (addr + PAGE_SIZE-1) / PAGE_SIZE;
+ if (!pages) BUG();
+ if (end_pfn > max_low_pfn)
+ BUG();

- for (i = start; i < end; i++) {
+ for (i = start_pfn; i < end_pfn; i++) {
if (!test_and_clear_bit(i, bootmem_map))
BUG();
}
@@ -188,11 +181,11 @@
areasize = 0;
// last_pos unchanged
last_offset = offset+size;
- ret = phys_to_virt(last_pos*PAGE_SIZE + offset);
+ ret = phys_to_virt(last_pos*PAGE_SIZE + offset + phys_mem_start);
} else {
remaining_size = size - remaining_size;
areasize = (remaining_size+PAGE_SIZE-1)/PAGE_SIZE;
- ret = phys_to_virt(last_pos*PAGE_SIZE + offset);
+ ret = phys_to_virt(last_pos*PAGE_SIZE + offset + phys_mem_start);
last_pos = start+areasize-1;
last_offset = remaining_size;
}
@@ -200,7 +193,7 @@
} else {
last_pos = start + areasize - 1;
last_offset = size & ~PAGE_MASK;
- ret = phys_to_virt(start * PAGE_SIZE);
+ ret = phys_to_virt(start*PAGE_SIZE + phys_mem_start);
}
/*
* Reserve the area now:
@@ -226,7 +219,7 @@
count++;
ClearPageReserved(page);
set_page_count(page, 1);
- if (i >= (virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT))
+ if (i >= ((virt_to_phys((char *)MAX_DMA_ADDRESS) - phys_mem_start) >> PAGE_SHIFT))
clear_bit(PG_DMA, &page->flags);
__free_page(page);
}
--- linux/include/linux/bootmem.h.orig Fri Nov 26 06:11:29 1999
+++ linux/include/linux/bootmem.h Fri Nov 26 06:12:24 1999
@@ -7,16 +7,22 @@
#include <linux/init.h>

/*
- * simple boot-time physical memory area allocator.
+ * Simple boot-time physical memory area allocator.
+ *
+ * All units are 'page frame numbers', except the alloc_bootmem() variants
+ * where we allow byte granularity allocations.
*/

extern unsigned long max_low_pfn;

-extern unsigned long __init bootmem_bootmap_pages (unsigned long);
-extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
-extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
-extern void __init free_bootmem (unsigned long addr, unsigned long size);
-extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+extern unsigned long __init bootmem_bootmap_pages (unsigned long mempages);
+extern void __init init_bootmem (unsigned long bootmap_pfn,
+ unsigned long mempages, unsigned long memstart_pfn);
+extern void __init reserve_bootmem (unsigned long start_pfn,
+ unsigned long pages);
+extern void __init free_bootmem (unsigned long start_pfn, unsigned long pages);
+extern void * __init __alloc_bootmem (unsigned long size, unsigned long align,
+ unsigned long goal);
#define alloc_bootmem(x) \
__alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low(x) \
--- linux/arch/i386/kernel/setup.c.orig Fri Nov 26 06:11:29 1999
+++ linux/arch/i386/kernel/setup.c Fri Nov 26 06:12:06 1999
@@ -380,8 +380,7 @@
} /* memparse */


-void __init add_memory_region(unsigned long start,
- unsigned long size, int type)
+void __init add_memory_region(unsigned long start, unsigned long size, int type)
{
int x = e820.nr_map;

@@ -528,7 +527,7 @@

void __init setup_arch(char **cmdline_p)
{
- unsigned long bootmap_size;
+ unsigned long bootmap_pages, bootmap_pfn;
unsigned long start_pfn, max_pfn, max_low_pfn;
int i;

@@ -582,12 +581,6 @@
#define MAX_NONPAE_PFN (1 << 20)

/*
- * partially used pages are not usable - thus
- * we are rounding upwards:
- */
- start_pfn = PFN_UP(__pa(&_end));
-
- /*
* Find the highest page frame number we have available
*/
max_pfn = 0;
@@ -635,15 +628,43 @@
}
#endif
/*
- * Initialize the boot-time allocator (with low memory only):
+ * Partially used pages are not usable - thus
+ * we are rounding upwards:
*/
- bootmap_size = init_bootmem(start_pfn, max_low_pfn);
-
+ start_pfn = PFN_UP(__pa(&_end));
+ bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
+ /*
+ * Find a proper area for the bootmem bitmap. After this
+ * bootstrap step all allocations (until the page allocator
+ * is intact) must be done via bootmem_alloc().
+ */
+ bootmap_pfn = 0;
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long start, end;
+ /* RAM? */
+ if (e820.map[i].type != E820_RAM)
+ continue;
+ start = PFN_UP(e820.map[i].addr);
+ end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+ if (end < start_pfn)
+ continue;
+ if (start < start_pfn)
+ start = start_pfn;
+ if (end <= start)
+ continue;
+ if (end - start >= bootmap_pages) {
+ bootmap_pfn = start;
+ break;
+ }
+ }
+ if (!bootmap_pfn)
+ BUG();
+ init_bootmem(bootmap_pfn, max_low_pfn, 0);
/*
* Register fully available low RAM pages with the bootmem allocator.
*/
for (i = 0; i < e820.nr_map; i++) {
- unsigned long curr_pfn, last_pfn, size;
+ unsigned long curr_pfn, last_pfn, pages;
/*
* Reserve usable low memory
*/
@@ -670,23 +691,28 @@
if (last_pfn <= curr_pfn)
continue;

- size = last_pfn - curr_pfn;
- free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ pages = last_pfn - curr_pfn;
+ free_bootmem(curr_pfn, pages);
}
+
/*
- * Reserve the bootmem bitmap itself as well. We do this in two
- * steps (first step was init_bootmem()) because this catches
- * the (very unlikely) case of us accidentally initializing the
- * bootmem allocator with an invalid RAM area.
+ * Reserve the bootmem bitmap. We do this in two steps (first step
+ * was init_bootmem()), because this catches the (definitely buggy)
+ * case of us accidentally initializing the bootmem allocator with
+ * an invalid RAM area.
*/
- reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
- bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+ reserve_bootmem(bootmap_pfn, bootmap_pages);
+
+ /*
+ * Reserve the kernel image starting at 1MB.
+ */
+ reserve_bootmem(PFN_DOWN(HIGH_MEMORY), start_pfn-PFN_DOWN(HIGH_MEMORY));

/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
* enabling clean reboots, SMP operation, laptop functions.
*/
- reserve_bootmem(0, PAGE_SIZE);
+ reserve_bootmem(0, 1);

#ifdef __SMP__
/*
@@ -694,7 +720,7 @@
* FIXME: Don't need the extra page at 4K, but need to fix
* trampoline before removing it. (see the GDT stuff)
*/
- reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
+ reserve_bootmem(1, 1);
smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
#endif

@@ -707,17 +733,21 @@

#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE) {
- if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
+ unsigned long start, end, pages;
+
+ start = PFN_DOWN(INITRD_START);
+ end = PFN_UP(INITRD_START+INITRD_SIZE);
+ pages = end - start;
+ if (end < max_low_pfn) {
+ reserve_bootmem(start, pages);
initrd_start =
INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
- initrd_end = initrd_start+INITRD_SIZE;
- }
- else {
+ initrd_end = initrd_start + INITRD_SIZE;
+ } else {
printk("initrd extends beyond end of memory "
"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- INITRD_START + INITRD_SIZE,
- max_low_pfn << PAGE_SHIFT);
+ INITRD_START + INITRD_SIZE,
+ max_low_pfn << PAGE_SHIFT);
initrd_start = 0;
}
}
@@ -730,6 +760,7 @@
probe_roms();
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
+
if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
continue;
res = alloc_bootmem_low(sizeof(struct resource));
@@ -745,9 +776,9 @@
request_resource(&iomem_resource, res);
if (e820.map[i].type == E820_RAM) {
/*
- * We dont't know which RAM region contains kernel data,
- * so we try it repeatedly and let the resource manager
- * test it.
+ * We dont't know which RAM region contains kernel
+ * data, so we try it repeatedly and let the
+ * resource manager test it.
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.084 / U:0.124 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site