| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 | /* *  linux/arch/arm/mm/init.c * *  Copyright (C) 1995-2005 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/kernel.h>#include <linux/errno.h>#include <linux/swap.h>#include <linux/init.h>#include <linux/bootmem.h>#include <linux/mman.h>#include <linux/export.h>#include <linux/nodemask.h>#include <linux/initrd.h>#include <linux/of_fdt.h>#include <linux/highmem.h>#include <linux/gfp.h>#include <linux/memblock.h>#include <linux/dma-contiguous.h>#include <linux/sizes.h>#include <asm/mach-types.h>#include <asm/memblock.h>#include <asm/prom.h>#include <asm/sections.h>#include <asm/setup.h>#include <asm/tlb.h>#include <asm/fixmap.h>#include <asm/mach/arch.h>#include <asm/mach/map.h>#include "mm.h"static unsigned long phys_initrd_start __initdata = 0;static unsigned long phys_initrd_size __initdata = 0;static int __init early_initrd(char *p){	unsigned long start, size;	char *endp;	start = memparse(p, &endp);	if (*endp == ',') {		size = memparse(endp + 1, NULL);		phys_initrd_start = start;		phys_initrd_size = size;	}	return 0;}early_param("initrd", early_initrd);static int __init parse_tag_initrd(const struct tag *tag){	printk(KERN_WARNING "ATAG_INITRD is deprecated; "		"please update your bootloader.\n");	phys_initrd_start = __virt_to_phys(tag->u.initrd.start);	phys_initrd_size = tag->u.initrd.size;	return 0;}__tagtable(ATAG_INITRD, parse_tag_initrd);static int __init parse_tag_initrd2(const struct tag *tag){	phys_initrd_start = tag->u.initrd.start;	phys_initrd_size = tag->u.initrd.size;	return 0;}__tagtable(ATAG_INITRD2, parse_tag_initrd2);#ifdef CONFIG_OF_FLATTREEvoid __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end){	phys_initrd_start = start;	phys_initrd_size = end - start;}#endif /* CONFIG_OF_FLATTREE *//* * This keeps memory configuration data used by a couple memory * initialization functions, as well as show_mem() for the skipping * of holes in the memory map.  It is populated by arm_add_memory(). */struct meminfo meminfo;void show_mem(unsigned int filter){	int free = 0, total = 0, reserved = 0;	int shared = 0, cached = 0, slab = 0, i;	struct meminfo * mi = &meminfo;	printk("Mem-info:\n");	show_free_areas(filter);	for_each_bank (i, mi) {		struct membank *bank = &mi->bank[i];		unsigned int pfn1, pfn2;		struct page *page, *end;		pfn1 = bank_pfn_start(bank);		pfn2 = bank_pfn_end(bank);		page = pfn_to_page(pfn1);		end  = pfn_to_page(pfn2 - 1) + 1;		do {			total++;			if (PageReserved(page))				reserved++;			else if (PageSwapCache(page))				cached++;			else if (PageSlab(page))				slab++;			else if (!page_count(page))				free++;			else				shared += page_count(page) - 1;			page++;		} while (page < end);	}	printk("%d pages of RAM\n", total);	printk("%d free pages\n", free);	printk("%d reserved pages\n", reserved);	printk("%d slab pages\n", slab);	printk("%d pages shared\n", shared);	printk("%d pages swap cached\n", cached);}static void __init find_limits(unsigned long *min, unsigned long *max_low,			       unsigned long *max_high){	struct meminfo *mi = &meminfo;	int i;	/* This assumes the meminfo array is properly sorted */	*min = bank_pfn_start(&mi->bank[0]);	for_each_bank (i, mi)		if (mi->bank[i].highmem)				break;	*max_low = bank_pfn_end(&mi->bank[i - 1]);	*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);
 |