diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/kernel/setup.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/kernel/setup.c')
-rw-r--r-- | arch/arm/kernel/setup.c | 275 |
1 files changed, 180 insertions, 95 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d5231ae7355a..acbb447ac6b5 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/screen_info.h> | 20 | #include <linux/screen_info.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kexec.h> | 22 | #include <linux/kexec.h> |
23 | #include <linux/of_fdt.h> | ||
23 | #include <linux/crash_dump.h> | 24 | #include <linux/crash_dump.h> |
24 | #include <linux/root_dev.h> | 25 | #include <linux/root_dev.h> |
25 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
@@ -36,11 +37,13 @@ | |||
36 | #include <asm/procinfo.h> | 37 | #include <asm/procinfo.h> |
37 | #include <asm/sections.h> | 38 | #include <asm/sections.h> |
38 | #include <asm/setup.h> | 39 | #include <asm/setup.h> |
40 | #include <asm/smp_plat.h> | ||
39 | #include <asm/mach-types.h> | 41 | #include <asm/mach-types.h> |
40 | #include <asm/cacheflush.h> | 42 | #include <asm/cacheflush.h> |
41 | #include <asm/cachetype.h> | 43 | #include <asm/cachetype.h> |
42 | #include <asm/tlbflush.h> | 44 | #include <asm/tlbflush.h> |
43 | 45 | ||
46 | #include <asm/prom.h> | ||
44 | #include <asm/mach/arch.h> | 47 | #include <asm/mach/arch.h> |
45 | #include <asm/mach/irq.h> | 48 | #include <asm/mach/irq.h> |
46 | #include <asm/mach/time.h> | 49 | #include <asm/mach/time.h> |
@@ -70,13 +73,14 @@ __setup("fpe=", fpe_setup); | |||
70 | #endif | 73 | #endif |
71 | 74 | ||
72 | extern void paging_init(struct machine_desc *desc); | 75 | extern void paging_init(struct machine_desc *desc); |
76 | extern void sanity_check_meminfo(void); | ||
73 | extern void reboot_setup(char *str); | 77 | extern void reboot_setup(char *str); |
74 | 78 | ||
75 | unsigned int processor_id; | 79 | unsigned int processor_id; |
76 | EXPORT_SYMBOL(processor_id); | 80 | EXPORT_SYMBOL(processor_id); |
77 | unsigned int __machine_arch_type; | 81 | unsigned int __machine_arch_type __read_mostly; |
78 | EXPORT_SYMBOL(__machine_arch_type); | 82 | EXPORT_SYMBOL(__machine_arch_type); |
79 | unsigned int cacheid; | 83 | unsigned int cacheid __read_mostly; |
80 | EXPORT_SYMBOL(cacheid); | 84 | EXPORT_SYMBOL(cacheid); |
81 | 85 | ||
82 | unsigned int __atags_pointer __initdata; | 86 | unsigned int __atags_pointer __initdata; |
@@ -90,24 +94,24 @@ EXPORT_SYMBOL(system_serial_low); | |||
90 | unsigned int system_serial_high; | 94 | unsigned int system_serial_high; |
91 | EXPORT_SYMBOL(system_serial_high); | 95 | EXPORT_SYMBOL(system_serial_high); |
92 | 96 | ||
93 | unsigned int elf_hwcap; | 97 | unsigned int elf_hwcap __read_mostly; |
94 | EXPORT_SYMBOL(elf_hwcap); | 98 | EXPORT_SYMBOL(elf_hwcap); |
95 | 99 | ||
96 | 100 | ||
97 | #ifdef MULTI_CPU | 101 | #ifdef MULTI_CPU |
98 | struct processor processor; | 102 | struct processor processor __read_mostly; |
99 | #endif | 103 | #endif |
100 | #ifdef MULTI_TLB | 104 | #ifdef MULTI_TLB |
101 | struct cpu_tlb_fns cpu_tlb; | 105 | struct cpu_tlb_fns cpu_tlb __read_mostly; |
102 | #endif | 106 | #endif |
103 | #ifdef MULTI_USER | 107 | #ifdef MULTI_USER |
104 | struct cpu_user_fns cpu_user; | 108 | struct cpu_user_fns cpu_user __read_mostly; |
105 | #endif | 109 | #endif |
106 | #ifdef MULTI_CACHE | 110 | #ifdef MULTI_CACHE |
107 | struct cpu_cache_fns cpu_cache; | 111 | struct cpu_cache_fns cpu_cache __read_mostly; |
108 | #endif | 112 | #endif |
109 | #ifdef CONFIG_OUTER_CACHE | 113 | #ifdef CONFIG_OUTER_CACHE |
110 | struct outer_cache_fns outer_cache; | 114 | struct outer_cache_fns outer_cache __read_mostly; |
111 | EXPORT_SYMBOL(outer_cache); | 115 | EXPORT_SYMBOL(outer_cache); |
112 | #endif | 116 | #endif |
113 | 117 | ||
@@ -125,6 +129,7 @@ EXPORT_SYMBOL(elf_platform); | |||
125 | static const char *cpu_name; | 129 | static const char *cpu_name; |
126 | static const char *machine_name; | 130 | static const char *machine_name; |
127 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; | 131 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; |
132 | struct machine_desc *machine_desc __initdata; | ||
128 | 133 | ||
129 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 134 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
130 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; | 135 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; |
@@ -224,8 +229,8 @@ int cpu_architecture(void) | |||
224 | * Register 0 and check for VMSAv7 or PMSAv7 */ | 229 | * Register 0 and check for VMSAv7 or PMSAv7 */ |
225 | asm("mrc p15, 0, %0, c0, c1, 4" | 230 | asm("mrc p15, 0, %0, c0, c1, 4" |
226 | : "=r" (mmfr0)); | 231 | : "=r" (mmfr0)); |
227 | if ((mmfr0 & 0x0000000f) == 0x00000003 || | 232 | if ((mmfr0 & 0x0000000f) >= 0x00000003 || |
228 | (mmfr0 & 0x000000f0) == 0x00000030) | 233 | (mmfr0 & 0x000000f0) >= 0x00000030) |
229 | cpu_arch = CPU_ARCH_ARMv7; | 234 | cpu_arch = CPU_ARCH_ARMv7; |
230 | else if ((mmfr0 & 0x0000000f) == 0x00000002 || | 235 | else if ((mmfr0 & 0x0000000f) == 0x00000002 || |
231 | (mmfr0 & 0x000000f0) == 0x00000020) | 236 | (mmfr0 & 0x000000f0) == 0x00000020) |
@@ -238,6 +243,35 @@ int cpu_architecture(void) | |||
238 | return cpu_arch; | 243 | return cpu_arch; |
239 | } | 244 | } |
240 | 245 | ||
246 | static int cpu_has_aliasing_icache(unsigned int arch) | ||
247 | { | ||
248 | int aliasing_icache; | ||
249 | unsigned int id_reg, num_sets, line_size; | ||
250 | |||
251 | /* arch specifies the register format */ | ||
252 | switch (arch) { | ||
253 | case CPU_ARCH_ARMv7: | ||
254 | asm("mcr p15, 2, %0, c0, c0, 0 @ set CSSELR" | ||
255 | : /* No output operands */ | ||
256 | : "r" (1)); | ||
257 | isb(); | ||
258 | asm("mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" | ||
259 | : "=r" (id_reg)); | ||
260 | line_size = 4 << ((id_reg & 0x7) + 2); | ||
261 | num_sets = ((id_reg >> 13) & 0x7fff) + 1; | ||
262 | aliasing_icache = (line_size * num_sets) > PAGE_SIZE; | ||
263 | break; | ||
264 | case CPU_ARCH_ARMv6: | ||
265 | aliasing_icache = read_cpuid_cachetype() & (1 << 11); | ||
266 | break; | ||
267 | default: | ||
268 | /* I-cache aliases will be handled by D-cache aliasing code */ | ||
269 | aliasing_icache = 0; | ||
270 | } | ||
271 | |||
272 | return aliasing_icache; | ||
273 | } | ||
274 | |||
241 | static void __init cacheid_init(void) | 275 | static void __init cacheid_init(void) |
242 | { | 276 | { |
243 | unsigned int cachetype = read_cpuid_cachetype(); | 277 | unsigned int cachetype = read_cpuid_cachetype(); |
@@ -249,10 +283,15 @@ static void __init cacheid_init(void) | |||
249 | cacheid = CACHEID_VIPT_NONALIASING; | 283 | cacheid = CACHEID_VIPT_NONALIASING; |
250 | if ((cachetype & (3 << 14)) == 1 << 14) | 284 | if ((cachetype & (3 << 14)) == 1 << 14) |
251 | cacheid |= CACHEID_ASID_TAGGED; | 285 | cacheid |= CACHEID_ASID_TAGGED; |
252 | } else if (cachetype & (1 << 23)) | 286 | else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7)) |
287 | cacheid |= CACHEID_VIPT_I_ALIASING; | ||
288 | } else if (cachetype & (1 << 23)) { | ||
253 | cacheid = CACHEID_VIPT_ALIASING; | 289 | cacheid = CACHEID_VIPT_ALIASING; |
254 | else | 290 | } else { |
255 | cacheid = CACHEID_VIPT_NONALIASING; | 291 | cacheid = CACHEID_VIPT_NONALIASING; |
292 | if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6)) | ||
293 | cacheid |= CACHEID_VIPT_I_ALIASING; | ||
294 | } | ||
256 | } else { | 295 | } else { |
257 | cacheid = CACHEID_VIVT; | 296 | cacheid = CACHEID_VIVT; |
258 | } | 297 | } |
@@ -263,7 +302,7 @@ static void __init cacheid_init(void) | |||
263 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", | 302 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", |
264 | cache_is_vivt() ? "VIVT" : | 303 | cache_is_vivt() ? "VIVT" : |
265 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : | 304 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : |
266 | cache_is_vipt_aliasing() ? "VIPT aliasing" : | 305 | icache_is_vipt_aliasing() ? "VIPT aliasing" : |
267 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); | 306 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); |
268 | } | 307 | } |
269 | 308 | ||
@@ -272,7 +311,22 @@ static void __init cacheid_init(void) | |||
272 | * already provide the required functionality. | 311 | * already provide the required functionality. |
273 | */ | 312 | */ |
274 | extern struct proc_info_list *lookup_processor_type(unsigned int); | 313 | extern struct proc_info_list *lookup_processor_type(unsigned int); |
275 | extern struct machine_desc *lookup_machine_type(unsigned int); | 314 | |
315 | void __init early_print(const char *str, ...) | ||
316 | { | ||
317 | extern void printascii(const char *); | ||
318 | char buf[256]; | ||
319 | va_list ap; | ||
320 | |||
321 | va_start(ap, str); | ||
322 | vsnprintf(buf, sizeof(buf), str, ap); | ||
323 | va_end(ap); | ||
324 | |||
325 | #ifdef CONFIG_DEBUG_LL | ||
326 | printascii(buf); | ||
327 | #endif | ||
328 | printk("%s", buf); | ||
329 | } | ||
276 | 330 | ||
277 | static void __init feat_v6_fixup(void) | 331 | static void __init feat_v6_fixup(void) |
278 | { | 332 | { |
@@ -388,32 +442,27 @@ void cpu_init(void) | |||
388 | : "r14"); | 442 | : "r14"); |
389 | } | 443 | } |
390 | 444 | ||
391 | static struct machine_desc * __init setup_machine(unsigned int nr) | 445 | void __init dump_machine_table(void) |
392 | { | 446 | { |
393 | struct machine_desc *list; | 447 | struct machine_desc *p; |
394 | 448 | ||
395 | /* | 449 | early_print("Available machine support:\n\nID (hex)\tNAME\n"); |
396 | * locate machine in the list of supported machines. | 450 | for_each_machine_desc(p) |
397 | */ | 451 | early_print("%08x\t%s\n", p->nr, p->name); |
398 | list = lookup_machine_type(nr); | ||
399 | if (!list) { | ||
400 | printk("Machine configuration botched (nr %d), unable " | ||
401 | "to continue.\n", nr); | ||
402 | while (1); | ||
403 | } | ||
404 | 452 | ||
405 | printk("Machine: %s\n", list->name); | 453 | early_print("\nPlease check your kernel config and/or bootloader.\n"); |
406 | 454 | ||
407 | return list; | 455 | while (true) |
456 | /* can't use cpu_relax() here as it may require MMU setup */; | ||
408 | } | 457 | } |
409 | 458 | ||
410 | static int __init arm_add_memory(unsigned long start, unsigned long size) | 459 | int __init arm_add_memory(phys_addr_t start, unsigned long size) |
411 | { | 460 | { |
412 | struct membank *bank = &meminfo.bank[meminfo.nr_banks]; | 461 | struct membank *bank = &meminfo.bank[meminfo.nr_banks]; |
413 | 462 | ||
414 | if (meminfo.nr_banks >= NR_BANKS) { | 463 | if (meminfo.nr_banks >= NR_BANKS) { |
415 | printk(KERN_CRIT "NR_BANKS too low, " | 464 | printk(KERN_CRIT "NR_BANKS too low, " |
416 | "ignoring memory at %#lx\n", start); | 465 | "ignoring memory at 0x%08llx\n", (long long)start); |
417 | return -EINVAL; | 466 | return -EINVAL; |
418 | } | 467 | } |
419 | 468 | ||
@@ -443,7 +492,8 @@ static int __init arm_add_memory(unsigned long start, unsigned long size) | |||
443 | static int __init early_mem(char *p) | 492 | static int __init early_mem(char *p) |
444 | { | 493 | { |
445 | static int usermem __initdata = 0; | 494 | static int usermem __initdata = 0; |
446 | unsigned long size, start; | 495 | unsigned long size; |
496 | phys_addr_t start; | ||
447 | char *endp; | 497 | char *endp; |
448 | 498 | ||
449 | /* | 499 | /* |
@@ -482,25 +532,21 @@ setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) | |||
482 | #endif | 532 | #endif |
483 | } | 533 | } |
484 | 534 | ||
485 | static void __init | 535 | static void __init request_standard_resources(struct machine_desc *mdesc) |
486 | request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) | ||
487 | { | 536 | { |
537 | struct memblock_region *region; | ||
488 | struct resource *res; | 538 | struct resource *res; |
489 | int i; | ||
490 | 539 | ||
491 | kernel_code.start = virt_to_phys(_text); | 540 | kernel_code.start = virt_to_phys(_text); |
492 | kernel_code.end = virt_to_phys(_etext - 1); | 541 | kernel_code.end = virt_to_phys(_etext - 1); |
493 | kernel_data.start = virt_to_phys(_data); | 542 | kernel_data.start = virt_to_phys(_sdata); |
494 | kernel_data.end = virt_to_phys(_end - 1); | 543 | kernel_data.end = virt_to_phys(_end - 1); |
495 | 544 | ||
496 | for (i = 0; i < mi->nr_banks; i++) { | 545 | for_each_memblock(memory, region) { |
497 | if (mi->bank[i].size == 0) | ||
498 | continue; | ||
499 | |||
500 | res = alloc_bootmem_low(sizeof(*res)); | 546 | res = alloc_bootmem_low(sizeof(*res)); |
501 | res->name = "System RAM"; | 547 | res->name = "System RAM"; |
502 | res->start = mi->bank[i].start; | 548 | res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); |
503 | res->end = mi->bank[i].start + mi->bank[i].size - 1; | 549 | res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; |
504 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 550 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
505 | 551 | ||
506 | request_resource(&iomem_resource, res); | 552 | request_resource(&iomem_resource, res); |
@@ -614,15 +660,22 @@ static int __init parse_tag_revision(const struct tag *tag) | |||
614 | 660 | ||
615 | __tagtable(ATAG_REVISION, parse_tag_revision); | 661 | __tagtable(ATAG_REVISION, parse_tag_revision); |
616 | 662 | ||
617 | #ifndef CONFIG_CMDLINE_FORCE | ||
618 | static int __init parse_tag_cmdline(const struct tag *tag) | 663 | static int __init parse_tag_cmdline(const struct tag *tag) |
619 | { | 664 | { |
620 | strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE); | 665 | #if defined(CONFIG_CMDLINE_EXTEND) |
666 | strlcat(default_command_line, " ", COMMAND_LINE_SIZE); | ||
667 | strlcat(default_command_line, tag->u.cmdline.cmdline, | ||
668 | COMMAND_LINE_SIZE); | ||
669 | #elif defined(CONFIG_CMDLINE_FORCE) | ||
670 | pr_warning("Ignoring tag cmdline (using the default kernel command line)\n"); | ||
671 | #else | ||
672 | strlcpy(default_command_line, tag->u.cmdline.cmdline, | ||
673 | COMMAND_LINE_SIZE); | ||
674 | #endif | ||
621 | return 0; | 675 | return 0; |
622 | } | 676 | } |
623 | 677 | ||
624 | __tagtable(ATAG_CMDLINE, parse_tag_cmdline); | 678 | __tagtable(ATAG_CMDLINE, parse_tag_cmdline); |
625 | #endif /* CONFIG_CMDLINE_FORCE */ | ||
626 | 679 | ||
627 | /* | 680 | /* |
628 | * Scan the tag table for this tag, and call its parse function. | 681 | * Scan the tag table for this tag, and call its parse function. |
@@ -669,17 +722,15 @@ static struct init_tags { | |||
669 | { tag_size(tag_core), ATAG_CORE }, | 722 | { tag_size(tag_core), ATAG_CORE }, |
670 | { 1, PAGE_SIZE, 0xff }, | 723 | { 1, PAGE_SIZE, 0xff }, |
671 | { tag_size(tag_mem32), ATAG_MEM }, | 724 | { tag_size(tag_mem32), ATAG_MEM }, |
672 | { MEM_SIZE, PHYS_OFFSET }, | 725 | { MEM_SIZE }, |
673 | { 0, ATAG_NONE } | 726 | { 0, ATAG_NONE } |
674 | }; | 727 | }; |
675 | 728 | ||
676 | static void (*init_machine)(void) __initdata; | ||
677 | |||
678 | static int __init customize_machine(void) | 729 | static int __init customize_machine(void) |
679 | { | 730 | { |
680 | /* customizes platform devices, or adds new ones */ | 731 | /* customizes platform devices, or adds new ones */ |
681 | if (init_machine) | 732 | if (machine_desc->init_machine) |
682 | init_machine(); | 733 | machine_desc->init_machine(); |
683 | return 0; | 734 | return 0; |
684 | } | 735 | } |
685 | arch_initcall(customize_machine); | 736 | arch_initcall(customize_machine); |
@@ -733,30 +784,6 @@ static void __init reserve_crashkernel(void) | |||
733 | static inline void reserve_crashkernel(void) {} | 784 | static inline void reserve_crashkernel(void) {} |
734 | #endif /* CONFIG_KEXEC */ | 785 | #endif /* CONFIG_KEXEC */ |
735 | 786 | ||
736 | /* | ||
737 | * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by | ||
738 | * is_kdump_kernel() to determine if we are booting after a panic. Hence | ||
739 | * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. | ||
740 | */ | ||
741 | |||
742 | #ifdef CONFIG_CRASH_DUMP | ||
743 | /* | ||
744 | * elfcorehdr= specifies the location of elf core header stored by the crashed | ||
745 | * kernel. This option will be passed by kexec loader to the capture kernel. | ||
746 | */ | ||
747 | static int __init setup_elfcorehdr(char *arg) | ||
748 | { | ||
749 | char *end; | ||
750 | |||
751 | if (!arg) | ||
752 | return -EINVAL; | ||
753 | |||
754 | elfcorehdr_addr = memparse(arg, &end); | ||
755 | return end > arg ? 0 : -EINVAL; | ||
756 | } | ||
757 | early_param("elfcorehdr", setup_elfcorehdr); | ||
758 | #endif /* CONFIG_CRASH_DUMP */ | ||
759 | |||
760 | static void __init squash_mem_tags(struct tag *tag) | 787 | static void __init squash_mem_tags(struct tag *tag) |
761 | { | 788 | { |
762 | for (; tag->hdr.size; tag = tag_next(tag)) | 789 | for (; tag->hdr.size; tag = tag_next(tag)) |
@@ -764,25 +791,51 @@ static void __init squash_mem_tags(struct tag *tag) | |||
764 | tag->hdr.tag = ATAG_NONE; | 791 | tag->hdr.tag = ATAG_NONE; |
765 | } | 792 | } |
766 | 793 | ||
767 | void __init setup_arch(char **cmdline_p) | 794 | static struct machine_desc * __init setup_machine_tags(unsigned int nr) |
768 | { | 795 | { |
769 | struct tag *tags = (struct tag *)&init_tags; | 796 | struct tag *tags = (struct tag *)&init_tags; |
770 | struct machine_desc *mdesc; | 797 | struct machine_desc *mdesc = NULL, *p; |
771 | char *from = default_command_line; | 798 | char *from = default_command_line; |
772 | 799 | ||
773 | unwind_init(); | 800 | init_tags.mem.start = PHYS_OFFSET; |
774 | 801 | ||
775 | setup_processor(); | 802 | /* |
776 | mdesc = setup_machine(machine_arch_type); | 803 | * locate machine in the list of supported machines. |
777 | machine_name = mdesc->name; | 804 | */ |
805 | for_each_machine_desc(p) | ||
806 | if (nr == p->nr) { | ||
807 | printk("Machine: %s\n", p->name); | ||
808 | mdesc = p; | ||
809 | break; | ||
810 | } | ||
778 | 811 | ||
779 | if (mdesc->soft_reboot) | 812 | if (!mdesc) { |
780 | reboot_setup("s"); | 813 | early_print("\nError: unrecognized/unsupported machine ID" |
814 | " (r1 = 0x%08x).\n\n", nr); | ||
815 | dump_machine_table(); /* does not return */ | ||
816 | } | ||
781 | 817 | ||
782 | if (__atags_pointer) | 818 | if (__atags_pointer) |
783 | tags = phys_to_virt(__atags_pointer); | 819 | tags = phys_to_virt(__atags_pointer); |
784 | else if (mdesc->boot_params) | 820 | else if (mdesc->boot_params) { |
785 | tags = phys_to_virt(mdesc->boot_params); | 821 | #ifdef CONFIG_MMU |
822 | /* | ||
823 | * We still are executing with a minimal MMU mapping created | ||
824 | * with the presumption that the machine default for this | ||
825 | * is located in the first MB of RAM. Anything else will | ||
826 | * fault and silently hang the kernel at this point. | ||
827 | */ | ||
828 | if (mdesc->boot_params < PHYS_OFFSET || | ||
829 | mdesc->boot_params >= PHYS_OFFSET + SZ_1M) { | ||
830 | printk(KERN_WARNING | ||
831 | "Default boot params at physical 0x%08lx out of reach\n", | ||
832 | mdesc->boot_params); | ||
833 | } else | ||
834 | #endif | ||
835 | { | ||
836 | tags = phys_to_virt(mdesc->boot_params); | ||
837 | } | ||
838 | } | ||
786 | 839 | ||
787 | #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) | 840 | #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) |
788 | /* | 841 | /* |
@@ -792,8 +845,17 @@ void __init setup_arch(char **cmdline_p) | |||
792 | if (tags->hdr.tag != ATAG_CORE) | 845 | if (tags->hdr.tag != ATAG_CORE) |
793 | convert_to_tag_list(tags); | 846 | convert_to_tag_list(tags); |
794 | #endif | 847 | #endif |
795 | if (tags->hdr.tag != ATAG_CORE) | 848 | |
849 | if (tags->hdr.tag != ATAG_CORE) { | ||
850 | #if defined(CONFIG_OF) | ||
851 | /* | ||
852 | * If CONFIG_OF is set, then assume this is a reasonably | ||
853 | * modern system that should pass boot parameters | ||
854 | */ | ||
855 | early_print("Warning: Neither atags nor dtb found\n"); | ||
856 | #endif | ||
796 | tags = (struct tag *)&init_tags; | 857 | tags = (struct tag *)&init_tags; |
858 | } | ||
797 | 859 | ||
798 | if (mdesc->fixup) | 860 | if (mdesc->fixup) |
799 | mdesc->fixup(mdesc, tags, &from, &meminfo); | 861 | mdesc->fixup(mdesc, tags, &from, &meminfo); |
@@ -805,40 +867,60 @@ void __init setup_arch(char **cmdline_p) | |||
805 | parse_tags(tags); | 867 | parse_tags(tags); |
806 | } | 868 | } |
807 | 869 | ||
870 | /* parse_early_param needs a boot_command_line */ | ||
871 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
872 | |||
873 | return mdesc; | ||
874 | } | ||
875 | |||
876 | |||
877 | void __init setup_arch(char **cmdline_p) | ||
878 | { | ||
879 | struct machine_desc *mdesc; | ||
880 | |||
881 | unwind_init(); | ||
882 | |||
883 | setup_processor(); | ||
884 | mdesc = setup_machine_fdt(__atags_pointer); | ||
885 | if (!mdesc) | ||
886 | mdesc = setup_machine_tags(machine_arch_type); | ||
887 | machine_desc = mdesc; | ||
888 | machine_name = mdesc->name; | ||
889 | |||
890 | if (mdesc->soft_reboot) | ||
891 | reboot_setup("s"); | ||
892 | |||
808 | init_mm.start_code = (unsigned long) _text; | 893 | init_mm.start_code = (unsigned long) _text; |
809 | init_mm.end_code = (unsigned long) _etext; | 894 | init_mm.end_code = (unsigned long) _etext; |
810 | init_mm.end_data = (unsigned long) _edata; | 895 | init_mm.end_data = (unsigned long) _edata; |
811 | init_mm.brk = (unsigned long) _end; | 896 | init_mm.brk = (unsigned long) _end; |
812 | 897 | ||
813 | /* parse_early_param needs a boot_command_line */ | ||
814 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
815 | |||
816 | /* populate cmd_line too for later use, preserving boot_command_line */ | 898 | /* populate cmd_line too for later use, preserving boot_command_line */ |
817 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); | 899 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); |
818 | *cmdline_p = cmd_line; | 900 | *cmdline_p = cmd_line; |
819 | 901 | ||
820 | parse_early_param(); | 902 | parse_early_param(); |
821 | 903 | ||
904 | sanity_check_meminfo(); | ||
822 | arm_memblock_init(&meminfo, mdesc); | 905 | arm_memblock_init(&meminfo, mdesc); |
823 | 906 | ||
824 | paging_init(mdesc); | 907 | paging_init(mdesc); |
825 | request_standard_resources(&meminfo, mdesc); | 908 | request_standard_resources(mdesc); |
909 | |||
910 | unflatten_device_tree(); | ||
826 | 911 | ||
827 | #ifdef CONFIG_SMP | 912 | #ifdef CONFIG_SMP |
828 | smp_init_cpus(); | 913 | if (is_smp()) |
914 | smp_init_cpus(); | ||
829 | #endif | 915 | #endif |
830 | reserve_crashkernel(); | 916 | reserve_crashkernel(); |
831 | 917 | ||
832 | cpu_init(); | 918 | cpu_init(); |
833 | tcm_init(); | 919 | tcm_init(); |
834 | 920 | ||
835 | /* | 921 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
836 | * Set up various architecture-specific pointers | 922 | handle_arch_irq = mdesc->handle_irq; |
837 | */ | 923 | #endif |
838 | arch_nr_irqs = mdesc->nr_irqs; | ||
839 | init_arch_irq = mdesc->init_irq; | ||
840 | system_timer = mdesc->timer; | ||
841 | init_machine = mdesc->init_machine; | ||
842 | 924 | ||
843 | #ifdef CONFIG_VT | 925 | #ifdef CONFIG_VT |
844 | #if defined(CONFIG_VGA_CONSOLE) | 926 | #if defined(CONFIG_VGA_CONSOLE) |
@@ -848,6 +930,9 @@ void __init setup_arch(char **cmdline_p) | |||
848 | #endif | 930 | #endif |
849 | #endif | 931 | #endif |
850 | early_trap_init(); | 932 | early_trap_init(); |
933 | |||
934 | if (mdesc->init_early) | ||
935 | mdesc->init_early(); | ||
851 | } | 936 | } |
852 | 937 | ||
853 | 938 | ||