[PATCH v3 RESEND 08/17] ARM: LPAE: use phys_addr_t in free_memmap()
From: Russell King - ARM Linux <hidden>
Date: 2012-09-24 17:14:25
On Mon, Sep 24, 2012 at 05:51:46PM +0100, Catalin Marinas wrote:
quoted hunk ↗ jump to hunk
I don't think that's needed. free_all_bootmem() in mm/nobootmem.c takes care of freeing lowmem but it has a different notion of max_low_pfn. So this hunk did the trick:@@ -420,8 +366,8 @@ void __init bootmem_init(void) * Note: max_low_pfn and max_pfn reflect the number of _pages_ in * the system, not the maximum PFN. */ - max_low_pfn = max_low - PHYS_PFN_OFFSET; - max_pfn = max_high - PHYS_PFN_OFFSET; + max_low_pfn = max_low; + max_pfn = max_high; }
Did you actually look to see where that's used before you made the change.
I don't think you did.
The reason we have that there is that much of the kernel assumes memory
always starts at physical zero, so the max*pfn variables can be used to
generate bitmasks to cover the range of system memory addresses - iow,
(1 << max_low_pfn) - 1.
Eg, in the block code:
blk_max_low_pfn = max_low_pfn - 1;
blk_max_pfn = max_pfn - 1;
...
unsigned long b_pfn = dma_mask >> PAGE_SHIFT;
if (b_pfn < blk_max_low_pfn)
dma = 1;
Having a DMA mask for a peripheral which only has 24 bits wired (so
0x00ffffff) with a system memory offset of 0xc0000000 results in
apparantly _all_ system memory being DMA-able according to this test
unless max_low_pfn is defined as the _number_ of bits in the RAM
address.
In dma_get_required_mask():
u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
low_totalram = (1 << (fls(low_totalram) - 1));
low_totalram += low_totalram - 1;
which results in (for a phys offset of 0xc0000000) low_totalram being
0xffffffff unconditionally no matter how much RAM you actually have.
fs/proc/kcore.c can be ignored because that's not supported on ARM.
So, for DMA masks to work correctly, max_pfn and max_low_pfn must be
defined to cover the number of signiciant address bits in the RAM
region, and not covering the number of significant bits of the last
RAM address.