diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-03-08 15:57:03 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 01:14:23 -0800 |
commit | 17b0e199a10184d8c5bbbd79a4cee993bb1fb257 (patch) | |
tree | c5cf39d072cf908e5b03216e1e1698bf85e86877 /arch/sparc64 | |
parent | d1112018b4bc82adf5c8a9c15a08954328f023ae (diff) | |
download | linux-17b0e199a10184d8c5bbbd79a4cee993bb1fb257.tar.bz2 |
[SPARC64]: Fix 32-bit truncation which broke sparsemem.
The page->flags manipulations done by the D-cache dirty
state tracking was broken because the constants were not
marked with "UL" to make them 64-bit, which means we were
clobbering the upper 32-bits of page->flags all the time.
This doesn't jive well with sparsemem which stores the
section and indexing information in the top 32-bits of
page->flags.
This is yet another sparc64 bug which has been with us
forever.
While we're here, tidy up some things in bootmem_init()
and paginig_init():
1) Pass min_low_pfn to init_bootmem_node(), it's identical
to (phys_base >> PAGE_SHIFT) but we should use consistent
with the variable names we print in CONFIG_BOOTMEM_DEBUG
2) max_mapnr, although no longer used, was being set
inaccurately, we shouldn't subtract pfn_base any more.
3) All the games with phys_base in the zones_*[] arrays
we pass to free_area_init_node() are no longer necessary.
Thanks to Josh Grebe and Fabbione for the bug reports
and testing. Fix also verified locally on an SB2500
which had a memory layout that triggered the same problem.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/mm/init.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 5f67b53b3a5b..b40f6477dea0 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -205,8 +205,8 @@ inline void flush_dcache_page_impl(struct page *page) } #define PG_dcache_dirty PG_arch_1 -#define PG_dcache_cpu_shift 24 -#define PG_dcache_cpu_mask (256 - 1) +#define PG_dcache_cpu_shift 24UL +#define PG_dcache_cpu_mask (256UL - 1UL) #if NR_CPUS > 256 #error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus @@ -901,8 +901,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, min_low_pfn, bootmap_pfn, max_low_pfn); #endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, - (phys_base >> PAGE_SHIFT), - end_pfn); + min_low_pfn, end_pfn); /* Now register the available physical memory with the * allocator. @@ -1311,25 +1310,24 @@ void __init paging_init(void) pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base); - max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); + max_mapnr = last_valid_pfn; kernel_physical_mapping_init(); { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; - unsigned long npages; int znum; for (znum = 0; znum < MAX_NR_ZONES; znum++) zones_size[znum] = zholes_size[znum] = 0; - npages = end_pfn - (phys_base >> PAGE_SHIFT); - zones_size[ZONE_DMA] = npages; - zholes_size[ZONE_DMA] = npages - pages_avail; + zones_size[ZONE_DMA] = end_pfn; + zholes_size[ZONE_DMA] = end_pfn - pages_avail; free_area_init_node(0, &contig_page_data, zones_size, - phys_base >> PAGE_SHIFT, zholes_size); + __pa(PAGE_OFFSET) >> PAGE_SHIFT, + zholes_size); } device_scan(); |