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

On Tue, 2 Nov 1999, Russell King wrote:

> > > This is just Ingo being bad. He should have used virt_to_phys() and
> > > friends, not __pa().
>
> IMHO, __pa should not be the same as virt_to_phys(). [...]

i've fixed this already in my tree (patch attached) - but i do not think
this should make any difference. bootmem.c does not deal with vmalloced or
ioremapped memory, so __pa/__va should be identical to virt_to_phys /
phys_to_virt.

The patch also adds a simple (and fast) intrusive RAM tester [saw the idea
of boot-time RAM testing in Pavel Machek's patch], this can be done in
bootmem.c in a very straightforward way. Pages are tested right before
they are freed. Only pages that are explicitly marked as usable are
tested, ie. boot-parameter-forced memory maps can be used to ignore faulty
RAM. This feature should also help us sorting out memory detection
inconsistencies. [bootmem.c still has some debugging checks, this will be
removed later.]

> However, as Roman points out, if the bootmem stuff is to use
> virt_to_phys(), unless a "start" page number is passed in, the bit
> array could be unnecessarily large, and may in certain systems cause
> major problems (systems with many small (512KB) banks of memory).

there is a single place where bootmem.c uses virt_to_phys, and thats a
constant address (MAX_DMA_ADDRESS). I'd be surprised if there was any
difference between virt_to_phys() and __pa() in this case. There were
several uses of __va() in bootmem.c - can there be any theoretical
difference between __va() and phys_to_virt()?

Niibe Yutaka (the SH maintainer) noticed this 'too big bitmap and memory
map' problem too, and he promised to send patches for this in a few days.
(it's a bit hard to test this on x86) It's not really a problem with the
bootmem.c bitmap (that one is getting freed after bootup anyway), the real
problem is mem_map[], which can get unnecesserily big if there are too
many 'holes' in the physical memory layout.

-- mingo
--- linux/mm/bootmem.c.orig Tue Nov 2 04:25:11 1999
+++ linux/mm/bootmem.c Tue Nov 2 08:13:37 1999
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/highmem.h>
#include <asm/dma.h>

/*
@@ -36,9 +37,7 @@
{
unsigned long mapsize = (pages+7)/8;

- if (bootmem_map)
- BUG();
- bootmem_map = __va(start << PAGE_SHIFT);
+ bootmem_map = phys_to_virt(start << PAGE_SHIFT);
max_low_pfn = pages;

/*
@@ -64,7 +63,6 @@
*/
unsigned long end = (addr + size + PAGE_SIZE-1)/PAGE_SIZE;

- if (!bootmem_map) BUG();
if (!size) BUG();

if (end > max_low_pfn)
@@ -83,7 +81,6 @@
*/
unsigned long end = (addr + size)/PAGE_SIZE;

- if (!bootmem_map) BUG();
if (!size) BUG();

if (end > max_low_pfn)
@@ -117,7 +114,6 @@
unsigned long offset, remaining_size;
unsigned long areasize, preferred;

- if (!bootmem_map) BUG();
if (!size) BUG();

/*
@@ -152,6 +148,9 @@
preferred = 0;
goto restart_scan;
}
+ /*
+ * Whoops, we cannot satisfy the allocation request.
+ */
BUG();
found:
if (start >= max_low_pfn)
@@ -173,11 +172,11 @@
areasize = 0;
// last_pos unchanged
last_offset = offset+size;
- ret = __va(last_pos*PAGE_SIZE + offset);
+ ret = phys_to_virt(last_pos*PAGE_SIZE + offset);
} else {
size -= remaining_size;
areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
- ret = __va(last_pos*PAGE_SIZE + offset);
+ ret = phys_to_virt(last_pos*PAGE_SIZE + offset);
last_pos = start+areasize-1;
last_offset = size;
}
@@ -185,7 +184,7 @@
} else {
last_pos = start + areasize - 1;
last_offset = size & ~PAGE_MASK;
- ret = __va(start * PAGE_SIZE);
+ ret = phys_to_virt(start * PAGE_SIZE);
}
/*
* Reserve the area now:
@@ -197,6 +196,41 @@
return ret;
}

+/*
+ * Only test every TEST_INTERVAL byte, main memory bandwith
+ * slows things down
+ */
+#define TEST_INTERVAL 69
+
+static void silly_test_page(struct page *page)
+{
+ volatile unsigned char * kaddr;
+ int i;
+
+ kaddr = (char *)kmap(page, KM_READ);
+
+ /*
+ * Simple test to see wether all bits are intact.
+ */
+ for (i = 0; i < PAGE_SIZE; i += TEST_INTERVAL) {
+ kaddr[i] |= 0x55;
+ if ((kaddr[i] & 0x55) != 0x55)
+ goto failure;
+ kaddr[i] |= 0xAA;
+ if (kaddr[i] != 0xff)
+ goto failure;
+ kaddr[i]++;
+ if (kaddr[i] != 0x00)
+ goto failure;
+ }
+
+ kunmap((unsigned long)kaddr, KM_READ);
+ return;
+
+failure:
+ panic("memory test failed!");
+}
+
unsigned long __init free_all_bootmem (void)
{
struct page * page;
@@ -204,6 +238,7 @@

if (!bootmem_map) BUG();

+ printk("simple RAM-test ...");
page = mem_map;
count = 0;
for (i = 0; i < max_low_pfn; i++, page++) {
@@ -211,8 +246,9 @@
count++;
ClearPageReserved(page);
set_page_count(page, 1);
- if (i >= (__pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT))
+ if (i >= (virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT))
clear_bit(PG_DMA, &page->flags);
+ silly_test_page(page);
__free_page(page);
}
}
@@ -227,10 +263,13 @@
count++;
ClearPageReserved(page);
set_page_count(page, 1);
+ silly_test_page(page);
__free_page(page);
}
total += count;
bootmem_map = NULL;
+
+ printk(" passed.\n");

return total;
}
\
 
 \ /
  Last update: 2005-03-22 13:54    [W:0.083 / U:0.824 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site