diff options
author | Nicolas Pitre <nico@cam.org> | 2008-10-06 13:24:40 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-11-28 10:36:44 -0500 |
commit | 4b5f32cee0cce7b9783ced5cbeabd17aa53c51fb (patch) | |
tree | 95d3f2af07733cf70419ea5c3ae1100be2533197 | |
parent | 43ae286b7d4d8c4983bc263ef2e3cccc10dedb2b (diff) |
[ARM] rationalize memory configuration code some more
Currently there are two instances of struct meminfo: one in
kernel/setup.c marked __initdata, and another in mm/init.c with
permanent storage. Let's keep only the later to directly populate
the permanent version from arm_add_memory().
Also move common validation tests between the MMU and non-MMU cases
into arm_add_memory() to remove some duplication. Protection against
overflowing the membank array is also moved in there in order to cover
the kernel cmdline parsing path as well.
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/include/asm/setup.h | 6 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 37 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 12 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 29 | ||||
-rw-r--r-- | arch/arm/mm/nommu.c | 18 |
6 files changed, 45 insertions, 59 deletions
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index a65413ba121d..f2cd18a0932b 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h | |||
@@ -209,9 +209,11 @@ struct meminfo { | |||
209 | struct membank bank[NR_BANKS]; | 209 | struct membank bank[NR_BANKS]; |
210 | }; | 210 | }; |
211 | 211 | ||
212 | extern struct meminfo meminfo; | ||
213 | |||
212 | #define for_each_nodebank(iter,mi,no) \ | 214 | #define for_each_nodebank(iter,mi,no) \ |
213 | for (iter = 0; iter < mi->nr_banks; iter++) \ | 215 | for (iter = 0; iter < (mi)->nr_banks; iter++) \ |
214 | if (mi->bank[iter].node == no) | 216 | if ((mi)->bank[iter].node == no) |
215 | 217 | ||
216 | #define bank_pfn_start(bank) __phys_to_pfn((bank)->start) | 218 | #define bank_pfn_start(bank) __phys_to_pfn((bank)->start) |
217 | #define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size) | 219 | #define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size) |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1f1eecca7f55..d21786712c88 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -59,7 +59,7 @@ static int __init fpe_setup(char *line) | |||
59 | __setup("fpe=", fpe_setup); | 59 | __setup("fpe=", fpe_setup); |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | extern void paging_init(struct meminfo *, struct machine_desc *desc); | 62 | extern void paging_init(struct machine_desc *desc); |
63 | extern void reboot_setup(char *str); | 63 | extern void reboot_setup(char *str); |
64 | extern void _text, _etext, __data_start, _edata, _end; | 64 | extern void _text, _etext, __data_start, _edata, _end; |
65 | 65 | ||
@@ -112,7 +112,6 @@ static struct stack stacks[NR_CPUS]; | |||
112 | char elf_platform[ELF_PLATFORM_SIZE]; | 112 | char elf_platform[ELF_PLATFORM_SIZE]; |
113 | EXPORT_SYMBOL(elf_platform); | 113 | EXPORT_SYMBOL(elf_platform); |
114 | 114 | ||
115 | static struct meminfo meminfo __initdata = { 0, }; | ||
116 | static const char *cpu_name; | 115 | static const char *cpu_name; |
117 | static const char *machine_name; | 116 | static const char *machine_name; |
118 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 117 | static char __initdata command_line[COMMAND_LINE_SIZE]; |
@@ -367,21 +366,34 @@ static struct machine_desc * __init setup_machine(unsigned int nr) | |||
367 | return list; | 366 | return list; |
368 | } | 367 | } |
369 | 368 | ||
370 | static void __init arm_add_memory(unsigned long start, unsigned long size) | 369 | static int __init arm_add_memory(unsigned long start, unsigned long size) |
371 | { | 370 | { |
372 | struct membank *bank; | 371 | struct membank *bank = &meminfo.bank[meminfo.nr_banks]; |
372 | |||
373 | if (meminfo.nr_banks >= NR_BANKS) { | ||
374 | printk(KERN_CRIT "NR_BANKS too low, " | ||
375 | "ignoring memory at %#lx\n", start); | ||
376 | return -EINVAL; | ||
377 | } | ||
373 | 378 | ||
374 | /* | 379 | /* |
375 | * Ensure that start/size are aligned to a page boundary. | 380 | * Ensure that start/size are aligned to a page boundary. |
376 | * Size is appropriately rounded down, start is rounded up. | 381 | * Size is appropriately rounded down, start is rounded up. |
377 | */ | 382 | */ |
378 | size -= start & ~PAGE_MASK; | 383 | size -= start & ~PAGE_MASK; |
379 | |||
380 | bank = &meminfo.bank[meminfo.nr_banks++]; | ||
381 | |||
382 | bank->start = PAGE_ALIGN(start); | 384 | bank->start = PAGE_ALIGN(start); |
383 | bank->size = size & PAGE_MASK; | 385 | bank->size = size & PAGE_MASK; |
384 | bank->node = PHYS_TO_NID(start); | 386 | bank->node = PHYS_TO_NID(start); |
387 | |||
388 | /* | ||
389 | * Check whether this memory region has non-zero size or | ||
390 | * invalid node number. | ||
391 | */ | ||
392 | if (bank->size == 0 || bank->node >= MAX_NUMNODES) | ||
393 | return -EINVAL; | ||
394 | |||
395 | meminfo.nr_banks++; | ||
396 | return 0; | ||
385 | } | 397 | } |
386 | 398 | ||
387 | /* | 399 | /* |
@@ -539,14 +551,7 @@ __tagtable(ATAG_CORE, parse_tag_core); | |||
539 | 551 | ||
540 | static int __init parse_tag_mem32(const struct tag *tag) | 552 | static int __init parse_tag_mem32(const struct tag *tag) |
541 | { | 553 | { |
542 | if (meminfo.nr_banks >= NR_BANKS) { | 554 | return arm_add_memory(tag->u.mem.start, tag->u.mem.size); |
543 | printk(KERN_WARNING | ||
544 | "Ignoring memory bank 0x%08x size %dKB\n", | ||
545 | tag->u.mem.start, tag->u.mem.size / 1024); | ||
546 | return -EINVAL; | ||
547 | } | ||
548 | arm_add_memory(tag->u.mem.start, tag->u.mem.size); | ||
549 | return 0; | ||
550 | } | 555 | } |
551 | 556 | ||
552 | __tagtable(ATAG_MEM, parse_tag_mem32); | 557 | __tagtable(ATAG_MEM, parse_tag_mem32); |
@@ -718,7 +723,7 @@ void __init setup_arch(char **cmdline_p) | |||
718 | memcpy(boot_command_line, from, COMMAND_LINE_SIZE); | 723 | memcpy(boot_command_line, from, COMMAND_LINE_SIZE); |
719 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | 724 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; |
720 | parse_cmdline(cmdline_p, from); | 725 | parse_cmdline(cmdline_p, from); |
721 | paging_init(&meminfo, mdesc); | 726 | paging_init(mdesc); |
722 | request_standard_resources(&meminfo, mdesc); | 727 | request_standard_resources(&meminfo, mdesc); |
723 | 728 | ||
724 | #ifdef CONFIG_SMP | 729 | #ifdef CONFIG_SMP |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 82c4b4217989..b43da2479fa0 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -64,10 +64,11 @@ static int __init parse_tag_initrd2(const struct tag *tag) | |||
64 | __tagtable(ATAG_INITRD2, parse_tag_initrd2); | 64 | __tagtable(ATAG_INITRD2, parse_tag_initrd2); |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * This is used to pass memory configuration data from paging_init | 67 | * This keeps memory configuration data used by a couple memory |
68 | * to mem_init, and by show_mem() to skip holes in the memory map. | 68 | * initialization functions, as well as show_mem() for the skipping |
69 | * of holes in the memory map. It is populated by arm_add_memory(). | ||
69 | */ | 70 | */ |
70 | static struct meminfo meminfo = { 0, }; | 71 | struct meminfo meminfo; |
71 | 72 | ||
72 | void show_mem(void) | 73 | void show_mem(void) |
73 | { | 74 | { |
@@ -331,13 +332,12 @@ static void __init bootmem_free_node(int node, struct meminfo *mi) | |||
331 | free_area_init_node(node, zone_size, start_pfn, zhole_size); | 332 | free_area_init_node(node, zone_size, start_pfn, zhole_size); |
332 | } | 333 | } |
333 | 334 | ||
334 | void __init bootmem_init(struct meminfo *mi) | 335 | void __init bootmem_init(void) |
335 | { | 336 | { |
337 | struct meminfo *mi = &meminfo; | ||
336 | unsigned long memend_pfn = 0; | 338 | unsigned long memend_pfn = 0; |
337 | int node, initrd_node; | 339 | int node, initrd_node; |
338 | 340 | ||
339 | memcpy(&meminfo, mi, sizeof(meminfo)); | ||
340 | |||
341 | /* | 341 | /* |
342 | * Locate which node contains the ramdisk image, if any. | 342 | * Locate which node contains the ramdisk image, if any. |
343 | */ | 343 | */ |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 5d9f53907b4e..94367bdbb5a8 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -32,7 +32,7 @@ struct meminfo; | |||
32 | struct pglist_data; | 32 | struct pglist_data; |
33 | 33 | ||
34 | void __init create_mapping(struct map_desc *md); | 34 | void __init create_mapping(struct map_desc *md); |
35 | void __init bootmem_init(struct meminfo *mi); | 35 | void __init bootmem_init(void); |
36 | void reserve_node_zero(struct pglist_data *pgdat); | 36 | void reserve_node_zero(struct pglist_data *pgdat); |
37 | 37 | ||
38 | extern void _text, _stext, _etext, __data_start, _end, __init_begin, __init_end; | 38 | 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 7f36c825718d..6870805c31dd 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -654,13 +654,6 @@ __early_param("vmalloc=", early_vmalloc); | |||
654 | static int __init check_membank_valid(struct membank *mb) | 654 | static int __init check_membank_valid(struct membank *mb) |
655 | { | 655 | { |
656 | /* | 656 | /* |
657 | * Check whether this memory region has non-zero size or | ||
658 | * invalid node number. | ||
659 | */ | ||
660 | if (mb->size == 0 || mb->node >= MAX_NUMNODES) | ||
661 | return 0; | ||
662 | |||
663 | /* | ||
664 | * Check whether this memory region would entirely overlap | 657 | * Check whether this memory region would entirely overlap |
665 | * the vmalloc area. | 658 | * the vmalloc area. |
666 | */ | 659 | */ |
@@ -689,18 +682,18 @@ static int __init check_membank_valid(struct membank *mb) | |||
689 | return 1; | 682 | return 1; |
690 | } | 683 | } |
691 | 684 | ||
692 | static void __init sanity_check_meminfo(struct meminfo *mi) | 685 | static void __init sanity_check_meminfo(void) |
693 | { | 686 | { |
694 | int i, j; | 687 | int i, j; |
695 | 688 | ||
696 | for (i = 0, j = 0; i < mi->nr_banks; i++) { | 689 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { |
697 | if (check_membank_valid(&mi->bank[i])) | 690 | if (check_membank_valid(&meminfo.bank[i])) |
698 | mi->bank[j++] = mi->bank[i]; | 691 | meminfo.bank[j++] = meminfo.bank[i]; |
699 | } | 692 | } |
700 | mi->nr_banks = j; | 693 | meminfo.nr_banks = j; |
701 | } | 694 | } |
702 | 695 | ||
703 | static inline void prepare_page_table(struct meminfo *mi) | 696 | static inline void prepare_page_table(void) |
704 | { | 697 | { |
705 | unsigned long addr; | 698 | unsigned long addr; |
706 | 699 | ||
@@ -721,7 +714,7 @@ static inline void prepare_page_table(struct meminfo *mi) | |||
721 | * Clear out all the kernel space mappings, except for the first | 714 | * Clear out all the kernel space mappings, except for the first |
722 | * memory bank, up to the end of the vmalloc region. | 715 | * memory bank, up to the end of the vmalloc region. |
723 | */ | 716 | */ |
724 | for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size); | 717 | for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); |
725 | addr < VMALLOC_END; addr += PGDIR_SIZE) | 718 | addr < VMALLOC_END; addr += PGDIR_SIZE) |
726 | pmd_clear(pmd_off_k(addr)); | 719 | pmd_clear(pmd_off_k(addr)); |
727 | } | 720 | } |
@@ -880,14 +873,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
880 | * paging_init() sets up the page tables, initialises the zone memory | 873 | * paging_init() sets up the page tables, initialises the zone memory |
881 | * maps, and sets up the zero page, bad page and bad page tables. | 874 | * maps, and sets up the zero page, bad page and bad page tables. |
882 | */ | 875 | */ |
883 | void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) | 876 | void __init paging_init(struct machine_desc *mdesc) |
884 | { | 877 | { |
885 | void *zero_page; | 878 | void *zero_page; |
886 | 879 | ||
887 | build_mem_type_table(); | 880 | build_mem_type_table(); |
888 | sanity_check_meminfo(mi); | 881 | sanity_check_meminfo(); |
889 | prepare_page_table(mi); | 882 | prepare_page_table(); |
890 | bootmem_init(mi); | 883 | bootmem_init(); |
891 | devicemaps_init(mdesc); | 884 | devicemaps_init(mdesc); |
892 | 885 | ||
893 | top_pmd = pmd_off_k(0xffff0000); | 886 | top_pmd = pmd_off_k(0xffff0000); |
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 07b62b238979..c085f4e8248b 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c | |||
@@ -41,27 +41,13 @@ void __init reserve_node_zero(pg_data_t *pgdat) | |||
41 | BOOTMEM_DEFAULT); | 41 | BOOTMEM_DEFAULT); |
42 | } | 42 | } |
43 | 43 | ||
44 | static void __init sanity_check_meminfo(struct meminfo *mi) | ||
45 | { | ||
46 | int i, j; | ||
47 | |||
48 | for (i = 0, j = 0; i < mi->nr_banks; i++) { | ||
49 | struct membank *mb = &mi->bank[i]; | ||
50 | |||
51 | if (mb->size != 0 && mb->node < MAX_NUMNODES) | ||
52 | mi->bank[j++] = mi->bank[i]; | ||
53 | } | ||
54 | mi->nr_banks = j; | ||
55 | } | ||
56 | |||
57 | /* | 44 | /* |
58 | * paging_init() sets up the page tables, initialises the zone memory | 45 | * paging_init() sets up the page tables, initialises the zone memory |
59 | * maps, and sets up the zero page, bad page and bad page tables. | 46 | * maps, and sets up the zero page, bad page and bad page tables. |
60 | */ | 47 | */ |
61 | void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) | 48 | void __init paging_init(struct machine_desc *mdesc) |
62 | { | 49 | { |
63 | sanity_check_meminfo(mi); | 50 | bootmem_init(); |
64 | bootmem_init(mi); | ||
65 | } | 51 | } |
66 | 52 | ||
67 | /* | 53 | /* |