[PATCH v3 RESEND 08/17] ARM: LPAE: use phys_addr_t in free_memmap()

Russell King - ARM Linux linux at arm.linux.org.uk
Mon Sep 24 13:14:25 EDT 2012


On Mon, Sep 24, 2012 at 05:51:46PM +0100, Catalin Marinas wrote:
> 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.



More information about the linux-arm-kernel mailing list