[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 12:55:55 EDT 2012


On Mon, Sep 24, 2012 at 12:41:33PM -0400, Cyril Chemparathy wrote:
> It appears to be not that hard actually... Or maybe I'm totally missing  
> your point.  Could it be that you last looked at this prior to the  
> nobootmem compatibility stuff being added in?

Quite possible - we converted over to memblock here:

commit 2778f62056ada442414392d7ccd41188bb631619
Author: Russell King <rmk+kernel at arm.linux.org.uk>
Date:   Fri Jul 9 16:27:52 2010 +0100

It looks like nobootmem.c was created here:

commit 0932587328d9bd5b500a640fbaff3290c8d4cabf
Author: Yinghai Lu <yinghai at kernel.org>
Date:   Thu Feb 24 14:43:05 2011 +0100

So, when I was porting ARM to memblock, we had:

commit 08677214e318297f228237be0042aac754f48f1d
Author: Yinghai Lu <yinghai at kernel.org>
Date:   Wed Feb 10 01:20:20 2010 -0800

which causes a load of bootmem functions to panic() when bootmem is
disabled.

> The following patch appears to work just fine on a faked sparsemem system:

Great.  Don't forget to also check flatmem too, just to be sure.

> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 92f598a..e94fa4c 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -49,6 +49,7 @@ config ARM
>  	select GENERIC_STRNCPY_FROM_USER
>  	select GENERIC_STRNLEN_USER
>  	select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) &&  
> !CPU_BIG_ENDIAN
> +	select NO_BOOTMEM
>  	help
>  	  The ARM series is a line of low-power-consumption RISC chip designs
>  	  licensed by ARM Ltd and targeted at embedded applications and
> diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
> index 29560d8..0ca6c00 100644
> --- a/arch/arm/mm/init.c
> +++ b/arch/arm/mm/init.c
> @@ -150,58 +150,6 @@ static void __init find_limits(unsigned long *min,  
> unsigned long *max_low,
>  	*max_high = bank_pfn_end(&mi->bank[mi->nr_banks - 1]);
>  }
>
> -static void __init arm_bootmem_init(unsigned long start_pfn,
> -	unsigned long end_pfn)
> -{
> -	struct memblock_region *reg;
> -	unsigned int boot_pages;
> -	phys_addr_t bitmap;
> -	pg_data_t *pgdat;
> -
> -	/*
> -	 * Allocate the bootmem bitmap page.  This must be in a region
> -	 * of memory which has already been mapped.
> -	 */
> -	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
> -	bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
> -				__pfn_to_phys(end_pfn));
> -
> -	/*
> -	 * Initialise the bootmem allocator, handing the
> -	 * memory banks over to bootmem.
> -	 */
> -	node_set_online(0);
> -	pgdat = NODE_DATA(0);
> -	init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
> -
> -	/* Free the lowmem regions from memblock into bootmem. */
> -	for_each_memblock(memory, reg) {
> -		unsigned long start = memblock_region_memory_base_pfn(reg);
> -		unsigned long end = memblock_region_memory_end_pfn(reg);
> -
> -		if (end >= end_pfn)
> -			end = end_pfn;
> -		if (start >= end)
> -			break;
> -
> -		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
> -	}
> -
> -	/* Reserve the lowmem memblock reserved regions in bootmem. */
> -	for_each_memblock(reserved, reg) {
> -		unsigned long start = memblock_region_reserved_base_pfn(reg);
> -		unsigned long end = memblock_region_reserved_end_pfn(reg);
> -
> -		if (end >= end_pfn)
> -			end = end_pfn;
> -		if (start >= end)
> -			break;
> -
> -		reserve_bootmem(__pfn_to_phys(start),
> -			        (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
> -	}
> -}
> -
>  #ifdef CONFIG_ZONE_DMA
>
>  unsigned long arm_dma_zone_size __read_mostly;
> @@ -393,8 +341,6 @@ void __init bootmem_init(void)
>
>  	find_limits(&min, &max_low, &max_high);
>
> -	arm_bootmem_init(min, max_low);
> -
>  	/*
>  	 * Sparsemem tries to allocate bootmem in memory_present(),
>  	 * so must be done after the fixed reservations
> @@ -443,6 +389,54 @@ static inline int free_area(unsigned long pfn,  
> unsigned long end, char *s)
>  	return pages;
>  }
>
> +static unsigned long free_all_lowmem(void)
> +{
> +	unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET;
> +	struct memblock_region *mem, *res;
> +	unsigned long total_pages = 0;
> +
> +	/* set highmem page free */
> +	for_each_memblock(memory, mem) {
> +		unsigned long start = memblock_region_memory_base_pfn(mem);
> +		unsigned long end = memblock_region_memory_end_pfn(mem);
> +
> +		/* Ignore complete lowmem entries */
> +		if (start > max_low)
> +			continue;
> +
> +		/* Truncate partial highmem entries */
> +		if (end > max_low)
> +			end = max_low;
> +
> +		/* Find and exclude any reserved regions */
> +		for_each_memblock(reserved, res) {
> +			unsigned long res_start, res_end;
> +
> +			res_start = memblock_region_reserved_base_pfn(res);
> +			res_end = memblock_region_reserved_end_pfn(res);
> +
> +			if (res_end < start)
> +				continue;
> +			if (res_start < start)
> +				res_start = start;
> +			if (res_start > end)
> +				res_start = end;
> +			if (res_end > end)
> +				res_end = end;
> +			if (res_start != start)
> +				total_pages += free_area(start, res_start, NULL);
> +			start = res_end;
> +			if (start == end)
> +				break;
> +		}
> +
> +		/* And now free anything which remains */
> +		if (start < end)
> +			total_pages += free_area(start, end, NULL);
> +	}
> +	return total_pages;
> +}
> +
>  /*
>   * Poison init memory with an undefined instruction (ARM) or a branch  
> to an
>   * undefined instruction (Thumb).
> @@ -606,7 +600,7 @@ void __init mem_init(void)
>  	/* this will put all unused low memory onto the freelists */
>  	free_unused_memmap(&meminfo);
>
> -	totalram_pages += free_all_bootmem();
> +	totalram_pages += free_all_lowmem();
>
>  #ifdef CONFIG_SA1111
>  	/* now that our DMA memory is actually so designated, we can free it */
>
> -- 
> Thanks
> - Cyril



More information about the linux-arm-kernel mailing list