aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c118
1 files changed, 78 insertions, 40 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index fed9bf6187d1..8c3112a57cf2 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -66,7 +66,9 @@
66int __initdata iommu_is_off; 66int __initdata iommu_is_off;
67int __initdata iommu_force_on; 67int __initdata iommu_force_on;
68unsigned long tce_alloc_start, tce_alloc_end; 68unsigned long tce_alloc_start, tce_alloc_end;
69u64 ppc64_rma_size;
69#endif 70#endif
71static phys_addr_t first_memblock_size;
70 72
71static int __init early_parse_mem(char *p) 73static int __init early_parse_mem(char *p)
72{ 74{
@@ -80,11 +82,29 @@ static int __init early_parse_mem(char *p)
80} 82}
81early_param("mem", early_parse_mem); 83early_param("mem", early_parse_mem);
82 84
85/*
86 * overlaps_initrd - check for overlap with page aligned extension of
87 * initrd.
88 */
89static inline int overlaps_initrd(unsigned long start, unsigned long size)
90{
91#ifdef CONFIG_BLK_DEV_INITRD
92 if (!initrd_start)
93 return 0;
94
95 return (start + size) > _ALIGN_DOWN(initrd_start, PAGE_SIZE) &&
96 start <= _ALIGN_UP(initrd_end, PAGE_SIZE);
97#else
98 return 0;
99#endif
100}
101
83/** 102/**
84 * move_device_tree - move tree to an unused area, if needed. 103 * move_device_tree - move tree to an unused area, if needed.
85 * 104 *
86 * The device tree may be allocated beyond our memory limit, or inside the 105 * The device tree may be allocated beyond our memory limit, or inside the
87 * crash kernel region for kdump. If so, move it out of the way. 106 * crash kernel region for kdump, or within the page aligned range of initrd.
107 * If so, move it out of the way.
88 */ 108 */
89static void __init move_device_tree(void) 109static void __init move_device_tree(void)
90{ 110{
@@ -96,9 +116,10 @@ static void __init move_device_tree(void)
96 start = __pa(initial_boot_params); 116 start = __pa(initial_boot_params);
97 size = be32_to_cpu(initial_boot_params->totalsize); 117 size = be32_to_cpu(initial_boot_params->totalsize);
98 118
99 if ((memory_limit && (start + size) > memory_limit) || 119 if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
100 overlaps_crashkernel(start, size)) { 120 overlaps_crashkernel(start, size) ||
101 p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size)); 121 overlaps_initrd(start, size)) {
122 p = __va(memblock_alloc(size, PAGE_SIZE));
102 memcpy(p, initial_boot_params, size); 123 memcpy(p, initial_boot_params, size);
103 initial_boot_params = (struct boot_param_header *)p; 124 initial_boot_params = (struct boot_param_header *)p;
104 DBG("Moved device tree to 0x%p\n", p); 125 DBG("Moved device tree to 0x%p\n", p);
@@ -122,18 +143,19 @@ static void __init move_device_tree(void)
122 */ 143 */
123static struct ibm_pa_feature { 144static struct ibm_pa_feature {
124 unsigned long cpu_features; /* CPU_FTR_xxx bit */ 145 unsigned long cpu_features; /* CPU_FTR_xxx bit */
146 unsigned long mmu_features; /* MMU_FTR_xxx bit */
125 unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */ 147 unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */
126 unsigned char pabyte; /* byte number in ibm,pa-features */ 148 unsigned char pabyte; /* byte number in ibm,pa-features */
127 unsigned char pabit; /* bit number (big-endian) */ 149 unsigned char pabit; /* bit number (big-endian) */
128 unsigned char invert; /* if 1, pa bit set => clear feature */ 150 unsigned char invert; /* if 1, pa bit set => clear feature */
129} ibm_pa_features[] __initdata = { 151} ibm_pa_features[] __initdata = {
130 {0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, 152 {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0},
131 {0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, 153 {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0},
132 {CPU_FTR_SLB, 0, 0, 2, 0}, 154 {0, MMU_FTR_SLB, 0, 0, 2, 0},
133 {CPU_FTR_CTRL, 0, 0, 3, 0}, 155 {CPU_FTR_CTRL, 0, 0, 0, 3, 0},
134 {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, 156 {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0},
135 {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, 157 {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1},
136 {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, 158 {0, MMU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
137 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, 159 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
138}; 160};
139 161
@@ -165,9 +187,11 @@ static void __init scan_features(unsigned long node, unsigned char *ftrs,
165 if (bit ^ fp->invert) { 187 if (bit ^ fp->invert) {
166 cur_cpu_spec->cpu_features |= fp->cpu_features; 188 cur_cpu_spec->cpu_features |= fp->cpu_features;
167 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; 189 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
190 cur_cpu_spec->mmu_features |= fp->mmu_features;
168 } else { 191 } else {
169 cur_cpu_spec->cpu_features &= ~fp->cpu_features; 192 cur_cpu_spec->cpu_features &= ~fp->cpu_features;
170 cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs; 193 cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;
194 cur_cpu_spec->mmu_features &= ~fp->mmu_features;
171 } 195 }
172 } 196 }
173} 197}
@@ -267,13 +291,13 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
267 const char *uname, int depth, 291 const char *uname, int depth,
268 void *data) 292 void *data)
269{ 293{
270 static int logical_cpuid = 0;
271 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 294 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
272 const u32 *prop; 295 const u32 *prop;
273 const u32 *intserv; 296 const u32 *intserv;
274 int i, nthreads; 297 int i, nthreads;
275 unsigned long len; 298 unsigned long len;
276 int found = 0; 299 int found = -1;
300 int found_thread = 0;
277 301
278 /* We are scanning "cpu" nodes only */ 302 /* We are scanning "cpu" nodes only */
279 if (type == NULL || strcmp(type, "cpu") != 0) 303 if (type == NULL || strcmp(type, "cpu") != 0)
@@ -297,11 +321,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
297 * version 2 of the kexec param format adds the phys cpuid of 321 * version 2 of the kexec param format adds the phys cpuid of
298 * booted proc. 322 * booted proc.
299 */ 323 */
300 if (initial_boot_params && initial_boot_params->version >= 2) { 324 if (initial_boot_params->version >= 2) {
301 if (intserv[i] == 325 if (intserv[i] == initial_boot_params->boot_cpuid_phys) {
302 initial_boot_params->boot_cpuid_phys) { 326 found = boot_cpu_count;
303 found = 1; 327 found_thread = i;
304 break;
305 } 328 }
306 } else { 329 } else {
307 /* 330 /*
@@ -310,23 +333,20 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
310 * off secondary threads. 333 * off secondary threads.
311 */ 334 */
312 if (of_get_flat_dt_prop(node, 335 if (of_get_flat_dt_prop(node,
313 "linux,boot-cpu", NULL) != NULL) { 336 "linux,boot-cpu", NULL) != NULL)
314 found = 1; 337 found = boot_cpu_count;
315 break;
316 }
317 } 338 }
318
319#ifdef CONFIG_SMP 339#ifdef CONFIG_SMP
320 /* logical cpu id is always 0 on UP kernels */ 340 /* logical cpu id is always 0 on UP kernels */
321 logical_cpuid++; 341 boot_cpu_count++;
322#endif 342#endif
323 } 343 }
324 344
325 if (found) { 345 if (found >= 0) {
326 DBG("boot cpu: logical %d physical %d\n", logical_cpuid, 346 DBG("boot cpu: logical %d physical %d\n", found,
327 intserv[i]); 347 intserv[found_thread]);
328 boot_cpuid = logical_cpuid; 348 boot_cpuid = found;
329 set_hard_smp_processor_id(boot_cpuid, intserv[i]); 349 set_hard_smp_processor_id(found, intserv[found_thread]);
330 350
331 /* 351 /*
332 * PAPR defines "logical" PVR values for cpus that 352 * PAPR defines "logical" PVR values for cpus that
@@ -363,10 +383,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
363 return 0; 383 return 0;
364} 384}
365 385
366void __init early_init_dt_scan_chosen_arch(unsigned long node) 386int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
387 int depth, void *data)
367{ 388{
368 unsigned long *lprop; 389 unsigned long *lprop;
369 390
391 /* Use common scan routine to determine if this is the chosen node */
392 if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
393 return 0;
394
370#ifdef CONFIG_PPC64 395#ifdef CONFIG_PPC64
371 /* check if iommu is forced on or off */ 396 /* check if iommu is forced on or off */
372 if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) 397 if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -398,6 +423,9 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node)
398 if (lprop) 423 if (lprop)
399 crashk_res.end = crashk_res.start + *lprop - 1; 424 crashk_res.end = crashk_res.start + *lprop - 1;
400#endif 425#endif
426
427 /* break now */
428 return 1;
401} 429}
402 430
403#ifdef CONFIG_PPC_PSERIES 431#ifdef CONFIG_PPC_PSERIES
@@ -492,7 +520,7 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node,
492 520
493void __init early_init_dt_add_memory_arch(u64 base, u64 size) 521void __init early_init_dt_add_memory_arch(u64 base, u64 size)
494{ 522{
495#if defined(CONFIG_PPC64) 523#ifdef CONFIG_PPC64
496 if (iommu_is_off) { 524 if (iommu_is_off) {
497 if (base >= 0x80000000ul) 525 if (base >= 0x80000000ul)
498 return; 526 return;
@@ -500,15 +528,22 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
500 size = 0x80000000ul - base; 528 size = 0x80000000ul - base;
501 } 529 }
502#endif 530#endif
531 /* Keep track of the beginning of memory -and- the size of
532 * the very first block in the device-tree as it represents
533 * the RMA on ppc64 server
534 */
535 if (base < memstart_addr) {
536 memstart_addr = base;
537 first_memblock_size = size;
538 }
503 539
540 /* Add the chunk to the MEMBLOCK list */
504 memblock_add(base, size); 541 memblock_add(base, size);
505
506 memstart_addr = min((u64)memstart_addr, base);
507} 542}
508 543
509u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) 544void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
510{ 545{
511 return memblock_alloc(size, align); 546 return __va(memblock_alloc(size, align));
512} 547}
513 548
514#ifdef CONFIG_BLK_DEV_INITRD 549#ifdef CONFIG_BLK_DEV_INITRD
@@ -539,7 +574,9 @@ static void __init early_reserve_mem(void)
539#ifdef CONFIG_BLK_DEV_INITRD 574#ifdef CONFIG_BLK_DEV_INITRD
540 /* then reserve the initrd, if any */ 575 /* then reserve the initrd, if any */
541 if (initrd_start && (initrd_end > initrd_start)) 576 if (initrd_start && (initrd_end > initrd_start))
542 memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); 577 memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
578 _ALIGN_UP(initrd_end, PAGE_SIZE) -
579 _ALIGN_DOWN(initrd_start, PAGE_SIZE));
543#endif /* CONFIG_BLK_DEV_INITRD */ 580#endif /* CONFIG_BLK_DEV_INITRD */
544 581
545#ifdef CONFIG_PPC32 582#ifdef CONFIG_PPC32
@@ -655,7 +692,6 @@ static void __init phyp_dump_reserve_mem(void)
655static inline void __init phyp_dump_reserve_mem(void) {} 692static inline void __init phyp_dump_reserve_mem(void) {}
656#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ 693#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
657 694
658
659void __init early_init_devtree(void *params) 695void __init early_init_devtree(void *params)
660{ 696{
661 phys_addr_t limit; 697 phys_addr_t limit;
@@ -671,7 +707,7 @@ void __init early_init_devtree(void *params)
671#endif 707#endif
672 708
673#ifdef CONFIG_PHYP_DUMP 709#ifdef CONFIG_PHYP_DUMP
674 /* scan tree to see if dump occured during last boot */ 710 /* scan tree to see if dump occurred during last boot */
675 of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); 711 of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
676#endif 712#endif
677 713
@@ -679,12 +715,14 @@ void __init early_init_devtree(void *params)
679 * device-tree, including the platform type, initrd location and 715 * device-tree, including the platform type, initrd location and
680 * size, TCE reserve, and more ... 716 * size, TCE reserve, and more ...
681 */ 717 */
682 of_scan_flat_dt(early_init_dt_scan_chosen, NULL); 718 of_scan_flat_dt(early_init_dt_scan_chosen_ppc, cmd_line);
683 719
684 /* Scan memory nodes and rebuild MEMBLOCKs */ 720 /* Scan memory nodes and rebuild MEMBLOCKs */
685 memblock_init(); 721 memblock_init();
722
686 of_scan_flat_dt(early_init_dt_scan_root, NULL); 723 of_scan_flat_dt(early_init_dt_scan_root, NULL);
687 of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); 724 of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
725 setup_initial_memory_limit(memstart_addr, first_memblock_size);
688 726
689 /* Save command line for /proc/cmdline and then parse parameters */ 727 /* Save command line for /proc/cmdline and then parse parameters */
690 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); 728 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
@@ -726,7 +764,7 @@ void __init early_init_devtree(void *params)
726 764
727 DBG("Scanning CPUs ...\n"); 765 DBG("Scanning CPUs ...\n");
728 766
729 /* Retreive CPU related informations from the flat tree 767 /* Retrieve CPU related informations from the flat tree
730 * (altivec support, boot CPU ID, ...) 768 * (altivec support, boot CPU ID, ...)
731 */ 769 */
732 of_scan_flat_dt(early_init_dt_scan_cpus, NULL); 770 of_scan_flat_dt(early_init_dt_scan_cpus, NULL);