From 012d1f4af1b07e5ccfcd23b7c1dcdcc30a068257 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Sep 2008 10:57:03 +0100 Subject: [ARM] move initrd code from kernel/setup.c to mm/init.c This quietens some sparse warnings about phys_initrd_start and phys_initrd_size. Signed-off-by: Russell King --- arch/arm/mm/init.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm/init.c') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 30a69d67d673..c70fb1d18903 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -27,8 +27,43 @@ #include "mm.h" extern void _text, _etext, __data_start, _end, __init_begin, __init_end; -extern unsigned long phys_initrd_start; -extern unsigned long phys_initrd_size; + +static unsigned long phys_initrd_start __initdata = 0; +static unsigned long phys_initrd_size __initdata = 0; + +static void __init early_initrd(char **p) +{ + unsigned long start, size; + + start = memparse(*p, p); + if (**p == ',') { + size = memparse((*p) + 1, p); + + phys_initrd_start = start; + phys_initrd_size = size; + } +} +__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); /* * This is used to pass memory configuration data from paging_init -- cgit v1.2.3 From 5ed5fdf50cbe8195522e2176d6356b357c0c963f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Sep 2008 11:23:30 +0100 Subject: [ARM] clean up a load of old declarations ... some of which are now in linux/*.h headers. Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 3 +-- arch/arm/mm/init.c | 2 -- arch/arm/mm/mm.h | 2 ++ arch/arm/mm/mmu.c | 3 --- arch/arm/mm/nommu.c | 2 -- 5 files changed, 3 insertions(+), 9 deletions(-) (limited to 'arch/arm/mm/init.c') diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f972fc3e979b..61a2242b18b8 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -61,8 +61,7 @@ __setup("fpe=", fpe_setup); extern void paging_init(struct meminfo *, struct machine_desc *desc); extern void reboot_setup(char *str); -extern int root_mountflags; -extern void _stext, _text, _etext, __data_start, _edata, _end; +extern void _text, _etext, __data_start, _edata, _end; unsigned int processor_id; EXPORT_SYMBOL(processor_id); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index c70fb1d18903..80584bd7f03e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -26,8 +26,6 @@ #include "mm.h" -extern void _text, _etext, __data_start, _end, __init_begin, __init_end; - static unsigned long phys_initrd_start __initdata = 0; static unsigned long phys_initrd_size __initdata = 0; diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 7647c597fc59..96590104ba0f 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -35,3 +35,5 @@ struct pglist_data; void __init create_mapping(struct map_desc *md); void __init bootmem_init(struct meminfo *mi); void reserve_node_zero(struct pglist_data *pgdat); + +extern void _text, _stext, _etext, __data_start, _end, __init_begin, __init_end; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index c2bbe3f311f0..94d81a2ba008 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -28,9 +28,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -extern void _stext, _etext, __data_start, _end; -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; - /* * empty_zero_page is a special page that is used for * zero-initialized data and COW. diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 63c62fdea521..4bc767d1cedf 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -15,8 +15,6 @@ #include "mm.h" -extern void _stext, __data_start, _end; - /* * Reserve the various regions of node 0 */ -- cgit v1.2.3 From eca73214c9c50e290b8dc823b41730b01788872d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 30 Sep 2008 19:29:25 +0100 Subject: [ARM] mm: move validation of membanks to one place The newly introduced sanity_check_meminfo() function should be used to collect all validation of the meminfo array, which we have in bootmem_init(). Move it there. Signed-off-by: Russell King --- arch/arm/mm/init.c | 9 +-------- arch/arm/mm/mmu.c | 8 ++++---- arch/arm/mm/nommu.c | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'arch/arm/mm/init.c') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 80584bd7f03e..ffff901cf627 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -333,14 +333,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) void __init bootmem_init(struct meminfo *mi) { unsigned long memend_pfn = 0; - int node, initrd_node, i; - - /* - * Invalidate the node number for empty or invalid memory banks - */ - for (i = 0; i < mi->nr_banks; i++) - if (mi->bank[i].size == 0 || mi->bank[i].node >= MAX_NUMNODES) - mi->bank[i].node = -1; + int node, initrd_node; memcpy(&meminfo, mi, sizeof(meminfo)); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 94d81a2ba008..f03ad87f6baa 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -569,9 +569,10 @@ void __init iotable_init(struct map_desc *io_desc, int nr) static int __init check_membank_valid(struct membank *mb) { /* - * Check whether this memory region has non-zero size. + * Check whether this memory region has non-zero size or + * invalid node number. */ - if (mb->size == 0) + if (mb->size == 0 || mb->node >= MAX_NUMNODES) return 0; /* @@ -605,8 +606,7 @@ static int __init check_membank_valid(struct membank *mb) static void __init sanity_check_meminfo(struct meminfo *mi) { - int i; - int j; + int i, j; for (i = 0, j = 0; i < mi->nr_banks; i++) { if (check_membank_valid(&mi->bank[i])) diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 81a3000973b4..07b62b238979 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -41,12 +41,26 @@ void __init reserve_node_zero(pg_data_t *pgdat) BOOTMEM_DEFAULT); } +static void __init sanity_check_meminfo(struct meminfo *mi) +{ + int i, j; + + for (i = 0, j = 0; i < mi->nr_banks; i++) { + struct membank *mb = &mi->bank[i]; + + if (mb->size != 0 && mb->node < MAX_NUMNODES) + mi->bank[j++] = mi->bank[i]; + } + mi->nr_banks = j; +} + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. */ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) { + sanity_check_meminfo(mi); bootmem_init(mi); } -- cgit v1.2.3 From d2a38ef9c1585b47462c7be5501228ac57fbd3b1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 1 Oct 2008 16:56:15 +0100 Subject: [ARM] mm: provide helpers for accessing membanks Provide helpers for getting physical addresses or pfns from the meminfo array, and use them. Move for_each_nodebank() to asm/setup.h alongside the meminfo structure definition. Signed-off-by: Russell King --- arch/arm/include/asm/setup.h | 11 +++++++++ arch/arm/mm/init.c | 59 +++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 31 deletions(-) (limited to 'arch/arm/mm/init.c') diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 7bbf105463f1..a65413ba121d 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -209,6 +209,17 @@ struct meminfo { struct membank bank[NR_BANKS]; }; +#define for_each_nodebank(iter,mi,no) \ + for (iter = 0; iter < mi->nr_banks; iter++) \ + if (mi->bank[iter].node == no) + +#define bank_pfn_start(bank) __phys_to_pfn((bank)->start) +#define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size) +#define bank_pfn_size(bank) ((bank)->size >> PAGE_SHIFT) +#define bank_phys_start(bank) (bank)->start +#define bank_phys_end(bank) ((bank)->start + (bank)->size) +#define bank_phys_size(bank) (bank)->size + /* * Early command line parameters. */ diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ffff901cf627..9b7f0bf26f57 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -69,10 +69,6 @@ __tagtable(ATAG_INITRD2, parse_tag_initrd2); */ static struct meminfo meminfo = { 0, }; -#define for_each_nodebank(iter,mi,no) \ - for (iter = 0; iter < mi->nr_banks; iter++) \ - if (mi->bank[iter].node == no) - void show_mem(void) { int free = 0, total = 0, reserved = 0; @@ -86,11 +82,12 @@ void show_mem(void) struct page *map = n->node_mem_map - n->node_start_pfn; for_each_nodebank (i,mi,node) { + struct membank *bank = &mi->bank[i]; unsigned int pfn1, pfn2; struct page *page, *end; - pfn1 = __phys_to_pfn(mi->bank[i].start); - pfn2 = __phys_to_pfn(mi->bank[i].size + mi->bank[i].start); + pfn1 = bank_pfn_start(bank); + pfn2 = bank_pfn_end(bank); page = map + pfn1; end = map + pfn2; @@ -129,17 +126,17 @@ void show_mem(void) static unsigned int __init find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) { - unsigned int start_pfn, bank, bootmap_pfn; + unsigned int start_pfn, i, bootmap_pfn; start_pfn = PAGE_ALIGN(__pa(&_end)) >> PAGE_SHIFT; bootmap_pfn = 0; - for_each_nodebank(bank, mi, node) { + for_each_nodebank(i, mi, node) { + struct membank *bank = &mi->bank[i]; unsigned int start, end; - start = mi->bank[bank].start >> PAGE_SHIFT; - end = (mi->bank[bank].size + - mi->bank[bank].start) >> PAGE_SHIFT; + start = bank_pfn_start(bank); + end = bank_pfn_end(bank); if (end < start_pfn) continue; @@ -178,13 +175,10 @@ static int __init check_initrd(struct meminfo *mi) initrd_node = -1; for (i = 0; i < mi->nr_banks; i++) { - unsigned long bank_end; - - bank_end = mi->bank[i].start + mi->bank[i].size; - - if (mi->bank[i].start <= phys_initrd_start && - end <= bank_end) - initrd_node = mi->bank[i].node; + struct membank *bank = &mi->bank[i]; + if (bank_phys_start(bank) <= phys_initrd_start && + end <= bank_phys_end(bank)) + initrd_node = bank->node; } } @@ -204,9 +198,9 @@ static inline void map_memory_bank(struct membank *bank) #ifdef CONFIG_MMU struct map_desc map; - map.pfn = __phys_to_pfn(bank->start); - map.virtual = __phys_to_virt(bank->start); - map.length = bank->size; + map.pfn = bank_pfn_start(bank); + map.virtual = __phys_to_virt(bank_phys_start(bank)); + map.length = bank_phys_size(bank); map.type = MT_MEMORY; create_mapping(&map); @@ -232,8 +226,8 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) struct membank *bank = &mi->bank[i]; unsigned long start, end; - start = bank->start >> PAGE_SHIFT; - end = (bank->start + bank->size) >> PAGE_SHIFT; + start = bank_pfn_start(bank); + end = bank_pfn_end(bank); if (start_pfn > start) start_pfn = start; @@ -263,8 +257,10 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) pgdat = NODE_DATA(node); init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn); - for_each_nodebank(i, mi, node) - free_bootmem_node(pgdat, mi->bank[i].start, mi->bank[i].size); + for_each_nodebank(i, mi, node) { + struct membank *bank = &mi->bank[i]; + free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); + } /* * Reserve the bootmem bitmap for this node. @@ -317,7 +313,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) */ zhole_size[0] = zone_size[0]; for_each_nodebank(i, mi, node) - zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT; + zhole_size[0] -= bank_pfn_size(&mi->bank[i]); /* * Adjust the sizes according to any special requirements for @@ -427,7 +423,9 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi) * information on the command line. */ for_each_nodebank(i, mi, node) { - bank_start = mi->bank[i].start >> PAGE_SHIFT; + struct membank *bank = &mi->bank[i]; + + bank_start = bank_pfn_start(bank); if (bank_start < prev_bank_end) { printk(KERN_ERR "MEM: unordered memory banks. " "Not freeing memmap.\n"); @@ -441,8 +439,7 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi) if (prev_bank_end && prev_bank_end != bank_start) free_memmap(node, prev_bank_end, bank_start); - prev_bank_end = (mi->bank[i].start + - mi->bank[i].size) >> PAGE_SHIFT; + prev_bank_end = bank_pfn_end(bank); } } @@ -487,8 +484,8 @@ void __init mem_init(void) num_physpages = 0; for (i = 0; i < meminfo.nr_banks; i++) { - num_physpages += meminfo.bank[i].size >> PAGE_SHIFT; - printk(" %ldMB", meminfo.bank[i].size >> 20); + num_physpages += bank_pfn_size(&meminfo.bank[i]); + printk(" %ldMB", bank_phys_size(&meminfo.bank[i]) >> 20); } printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); -- cgit v1.2.3 From b7a69ac303cbfc8d6fa8e91d10e8049244ba6847 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 1 Oct 2008 16:58:32 +0100 Subject: [ARM] mm: finish ARM sparsemem support ... including some comments about the ordering required to bring sparsemem up. You have to repeatedly guess, test, reguess, try again and again to work out what the right ordering is. Many hours later... Signed-off-by: Russell King --- arch/arm/mm/init.c | 86 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 29 deletions(-) (limited to 'arch/arm/mm/init.c') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9b7f0bf26f57..82c4b4217989 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -79,7 +79,7 @@ void show_mem(void) show_free_areas(); for_each_online_node(node) { pg_data_t *n = NODE_DATA(node); - struct page *map = n->node_mem_map - n->node_start_pfn; + struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn; for_each_nodebank (i,mi,node) { struct membank *bank = &mi->bank[i]; @@ -207,10 +207,8 @@ static inline void map_memory_bank(struct membank *bank) #endif } -static unsigned long __init -bootmem_init_node(int node, int initrd_node, struct meminfo *mi) +static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) { - unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; unsigned long start_pfn, end_pfn, boot_pfn; unsigned int boot_pages; pg_data_t *pgdat; @@ -260,6 +258,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) for_each_nodebank(i, mi, node) { struct membank *bank = &mi->bank[i]; free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); + memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank)); } /* @@ -268,31 +267,39 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); - /* - * Reserve any special node zero regions. - */ - if (node == 0) - reserve_node_zero(pgdat); + return end_pfn; +} +static void __init bootmem_reserve_initrd(int node) +{ #ifdef CONFIG_BLK_DEV_INITRD - /* - * If the initrd is in this node, reserve its memory. - */ - if (node == initrd_node) { - int res = reserve_bootmem_node(pgdat, phys_initrd_start, - phys_initrd_size, BOOTMEM_EXCLUSIVE); - - if (res == 0) { - initrd_start = __phys_to_virt(phys_initrd_start); - initrd_end = initrd_start + phys_initrd_size; - } else { - printk(KERN_ERR - "INITRD: 0x%08lx+0x%08lx overlaps in-use " - "memory region - disabling initrd\n", - phys_initrd_start, phys_initrd_size); - } + pg_data_t *pgdat = NODE_DATA(node); + int res; + + res = reserve_bootmem_node(pgdat, phys_initrd_start, + phys_initrd_size, BOOTMEM_EXCLUSIVE); + + if (res == 0) { + initrd_start = __phys_to_virt(phys_initrd_start); + initrd_end = initrd_start + phys_initrd_size; + } else { + printk(KERN_ERR + "INITRD: 0x%08lx+0x%08lx overlaps in-use " + "memory region - disabling initrd\n", + phys_initrd_start, phys_initrd_size); } #endif +} + +static void __init bootmem_free_node(int node, struct meminfo *mi) +{ + unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; + unsigned long start_pfn, end_pfn; + pg_data_t *pgdat = NODE_DATA(node); + int i; + + start_pfn = pgdat->bdata->node_min_pfn; + end_pfn = pgdat->bdata->node_low_pfn; /* * initialise the zones within this node. @@ -322,8 +329,6 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) arch_adjust_zones(node, zone_size, zhole_size); free_area_init_node(node, zone_size, start_pfn, zhole_size); - - return end_pfn; } void __init bootmem_init(struct meminfo *mi) @@ -342,9 +347,19 @@ void __init bootmem_init(struct meminfo *mi) * Run through each node initialising the bootmem allocator. */ for_each_node(node) { - unsigned long end_pfn; + unsigned long end_pfn = bootmem_init_node(node, mi); - end_pfn = bootmem_init_node(node, initrd_node, mi); + /* + * Reserve any special node zero regions. + */ + if (node == 0) + reserve_node_zero(NODE_DATA(node)); + + /* + * If the initrd is in this node, reserve its memory. + */ + if (node == initrd_node) + bootmem_reserve_initrd(node); /* * Remember the highest memory PFN. @@ -353,6 +368,19 @@ void __init bootmem_init(struct meminfo *mi) memend_pfn = end_pfn; } + /* + * sparse_init() needs the bootmem allocator up and running. + */ + sparse_init(); + + /* + * Now free memory in each node - free_area_init_node needs + * the sparse mem_map arrays initialized by sparse_init() + * for memmap_init_zone(), otherwise all PFNs are invalid. + */ + for_each_node(node) + bootmem_free_node(node, mi); + high_memory = __va(memend_pfn << PAGE_SHIFT); /* -- cgit v1.2.3