Messages in this thread Patch in this message | | | Date | Wed, 3 Nov 1999 13:09:40 +0100 (CET) | From | Ingo Molnar <> | 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; }
| |