aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/setup_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/setup_64.c')
-rw-r--r--arch/powerpc/kernel/setup_64.c168
1 files changed, 31 insertions, 137 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 40c48100bf1b..6b52cce872be 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -56,7 +56,7 @@
56#include <asm/page.h> 56#include <asm/page.h>
57#include <asm/mmu.h> 57#include <asm/mmu.h>
58#include <asm/lmb.h> 58#include <asm/lmb.h>
59#include <asm/iSeries/ItLpNaca.h> 59#include <asm/iseries/it_lp_naca.h>
60#include <asm/firmware.h> 60#include <asm/firmware.h>
61#include <asm/systemcfg.h> 61#include <asm/systemcfg.h>
62#include <asm/xmon.h> 62#include <asm/xmon.h>
@@ -103,8 +103,6 @@ extern void htab_initialize(void);
103extern void early_init_devtree(void *flat_dt); 103extern void early_init_devtree(void *flat_dt);
104extern void unflatten_device_tree(void); 104extern void unflatten_device_tree(void);
105 105
106extern void smp_release_cpus(void);
107
108int have_of = 1; 106int have_of = 1;
109int boot_cpuid = 0; 107int boot_cpuid = 0;
110int boot_cpuid_phys = 0; 108int boot_cpuid_phys = 0;
@@ -183,120 +181,14 @@ static int __init early_smt_enabled(char *p)
183} 181}
184early_param("smt-enabled", early_smt_enabled); 182early_param("smt-enabled", early_smt_enabled);
185 183
186/** 184#else
187 * setup_cpu_maps - initialize the following cpu maps: 185#define check_smt_enabled()
188 * cpu_possible_map
189 * cpu_present_map
190 * cpu_sibling_map
191 *
192 * Having the possible map set up early allows us to restrict allocations
193 * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
194 *
195 * We do not initialize the online map here; cpus set their own bits in
196 * cpu_online_map as they come up.
197 *
198 * This function is valid only for Open Firmware systems. finish_device_tree
199 * must be called before using this.
200 *
201 * While we're here, we may as well set the "physical" cpu ids in the paca.
202 */
203static void __init setup_cpu_maps(void)
204{
205 struct device_node *dn = NULL;
206 int cpu = 0;
207 int swap_cpuid = 0;
208
209 check_smt_enabled();
210
211 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
212 u32 *intserv;
213 int j, len = sizeof(u32), nthreads;
214
215 intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
216 &len);
217 if (!intserv)
218 intserv = (u32 *)get_property(dn, "reg", NULL);
219
220 nthreads = len / sizeof(u32);
221
222 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
223 cpu_set(cpu, cpu_present_map);
224 set_hard_smp_processor_id(cpu, intserv[j]);
225
226 if (intserv[j] == boot_cpuid_phys)
227 swap_cpuid = cpu;
228 cpu_set(cpu, cpu_possible_map);
229 cpu++;
230 }
231 }
232
233 /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
234 * boot cpu is logical 0.
235 */
236 if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
237 u32 tmp;
238 tmp = get_hard_smp_processor_id(0);
239 set_hard_smp_processor_id(0, boot_cpuid_phys);
240 set_hard_smp_processor_id(swap_cpuid, tmp);
241 }
242
243 /*
244 * On pSeries LPAR, we need to know how many cpus
245 * could possibly be added to this partition.
246 */
247 if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
248 (dn = of_find_node_by_path("/rtas"))) {
249 int num_addr_cell, num_size_cell, maxcpus;
250 unsigned int *ireg;
251
252 num_addr_cell = prom_n_addr_cells(dn);
253 num_size_cell = prom_n_size_cells(dn);
254
255 ireg = (unsigned int *)
256 get_property(dn, "ibm,lrdr-capacity", NULL);
257
258 if (!ireg)
259 goto out;
260
261 maxcpus = ireg[num_addr_cell + num_size_cell];
262
263 /* Double maxcpus for processors which have SMT capability */
264 if (cpu_has_feature(CPU_FTR_SMT))
265 maxcpus *= 2;
266
267 if (maxcpus > NR_CPUS) {
268 printk(KERN_WARNING
269 "Partition configured for %d cpus, "
270 "operating system maximum is %d.\n",
271 maxcpus, NR_CPUS);
272 maxcpus = NR_CPUS;
273 } else
274 printk(KERN_INFO "Partition configured for %d cpus.\n",
275 maxcpus);
276
277 for (cpu = 0; cpu < maxcpus; cpu++)
278 cpu_set(cpu, cpu_possible_map);
279 out:
280 of_node_put(dn);
281 }
282
283 /*
284 * Do the sibling map; assume only two threads per processor.
285 */
286 for_each_cpu(cpu) {
287 cpu_set(cpu, cpu_sibling_map[cpu]);
288 if (cpu_has_feature(CPU_FTR_SMT))
289 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
290 }
291
292 systemcfg->processorCount = num_present_cpus();
293}
294#endif /* CONFIG_SMP */ 186#endif /* CONFIG_SMP */
295 187
296extern struct machdep_calls pSeries_md; 188extern struct machdep_calls pSeries_md;
297extern struct machdep_calls pmac_md; 189extern struct machdep_calls pmac_md;
298extern struct machdep_calls maple_md; 190extern struct machdep_calls maple_md;
299extern struct machdep_calls bpa_md; 191extern struct machdep_calls cell_md;
300extern struct machdep_calls iseries_md; 192extern struct machdep_calls iseries_md;
301 193
302/* Ultimately, stuff them in an elf section like initcalls... */ 194/* Ultimately, stuff them in an elf section like initcalls... */
@@ -310,8 +202,8 @@ static struct machdep_calls __initdata *machines[] = {
310#ifdef CONFIG_PPC_MAPLE 202#ifdef CONFIG_PPC_MAPLE
311 &maple_md, 203 &maple_md,
312#endif /* CONFIG_PPC_MAPLE */ 204#endif /* CONFIG_PPC_MAPLE */
313#ifdef CONFIG_PPC_BPA 205#ifdef CONFIG_PPC_CELL
314 &bpa_md, 206 &cell_md,
315#endif 207#endif
316#ifdef CONFIG_PPC_ISERIES 208#ifdef CONFIG_PPC_ISERIES
317 &iseries_md, 209 &iseries_md,
@@ -400,6 +292,29 @@ void __init early_setup(unsigned long dt_ptr)
400} 292}
401 293
402 294
295#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
296void smp_release_cpus(void)
297{
298 extern unsigned long __secondary_hold_spinloop;
299
300 DBG(" -> smp_release_cpus()\n");
301
302 /* All secondary cpus are spinning on a common spinloop, release them
303 * all now so they can start to spin on their individual paca
304 * spinloops. For non SMP kernels, the secondary cpus never get out
305 * of the common spinloop.
306 * This is useless but harmless on iSeries, secondaries are already
307 * waiting on their paca spinloops. */
308
309 __secondary_hold_spinloop = 1;
310 mb();
311
312 DBG(" <- smp_release_cpus()\n");
313}
314#else
315#define smp_release_cpus()
316#endif /* CONFIG_SMP || CONFIG_KEXEC */
317
403/* 318/*
404 * Initialize some remaining members of the ppc64_caches and systemcfg structures 319 * Initialize some remaining members of the ppc64_caches and systemcfg structures
405 * (at least until we get rid of them completely). This is mostly some 320 * (at least until we get rid of them completely). This is mostly some
@@ -589,17 +504,13 @@ void __init setup_system(void)
589 504
590 parse_early_param(); 505 parse_early_param();
591 506
592#ifdef CONFIG_SMP 507 check_smt_enabled();
593 /* 508 smp_setup_cpu_maps();
594 * iSeries has already initialized the cpu maps at this point.
595 */
596 setup_cpu_maps();
597 509
598 /* Release secondary cpus out of their spinloops at 0x60 now that 510 /* Release secondary cpus out of their spinloops at 0x60 now that
599 * we can map physical -> logical CPU ids 511 * we can map physical -> logical CPU ids
600 */ 512 */
601 smp_release_cpus(); 513 smp_release_cpus();
602#endif
603 514
604 printk("Starting Linux PPC64 %s\n", system_utsname.version); 515 printk("Starting Linux PPC64 %s\n", system_utsname.version);
605 516
@@ -631,23 +542,6 @@ static int ppc64_panic_event(struct notifier_block *this,
631 return NOTIFY_DONE; 542 return NOTIFY_DONE;
632} 543}
633 544
634#ifdef CONFIG_PPC_ISERIES
635/*
636 * On iSeries we just parse the mem=X option from the command line.
637 * On pSeries it's a bit more complicated, see prom_init_mem()
638 */
639static int __init early_parsemem(char *p)
640{
641 if (!p)
642 return 0;
643
644 memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
645
646 return 0;
647}
648early_param("mem", early_parsemem);
649#endif /* CONFIG_PPC_ISERIES */
650
651#ifdef CONFIG_IRQSTACKS 545#ifdef CONFIG_IRQSTACKS
652static void __init irqstack_early_init(void) 546static void __init irqstack_early_init(void)
653{ 547{