From: Paul Mackerras Move all cpu map initializations to one place (except for the online map -- cpus mark themselves online as they come up). This sets up cpu_possible_map early enough that we can use num_possible_cpus for allocating irqstacks instead of NR_CPUS. Hopefully this should also help set the stage for kexec. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc64/kernel/prom.c | 28 ------- 25-akpm/arch/ppc64/kernel/setup.c | 136 ++++++++++++++++++++++++++++++++------ 25-akpm/arch/ppc64/kernel/smp.c | 54 --------------- 3 files changed, 117 insertions(+), 101 deletions(-) diff -puN arch/ppc64/kernel/prom.c~ppc64-1-3-rework-ppc64-cpu-map-setup arch/ppc64/kernel/prom.c --- 25/arch/ppc64/kernel/prom.c~ppc64-1-3-rework-ppc64-cpu-map-setup 2004-08-30 00:50:17.694074496 -0700 +++ 25-akpm/arch/ppc64/kernel/prom.c 2004-08-30 00:50:17.704072976 -0700 @@ -939,20 +939,11 @@ static void __init prom_hold_cpus(unsign prom_getprop(node, "reg", ®, sizeof(reg)); lpaca[cpuid].hw_cpu_id = reg; -#ifdef CONFIG_SMP - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_present_map)); - if (reg == 0) - cpu_set(cpuid, RELOC(cpu_online_map)); -#endif /* CONFIG_SMP */ cpuid++; } return; } - /* Initially, we must have one active CPU. */ - _systemcfg->processorCount = 1; - prom_debug("prom_hold_cpus: start...\n"); prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); @@ -1038,23 +1029,13 @@ static void __init prom_hold_cpus(unsign * even if we never start it. */ if (cpuid >= NR_CPUS) goto next; -#ifdef CONFIG_SMP - /* Set the number of active processors. */ - _systemcfg->processorCount++; - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_present_map)); -#endif } else { prom_printf("... failed: %x\n", *acknowledge); } } #ifdef CONFIG_SMP - else { + else prom_printf("%x : booting cpu %s\n", cpuid, path); - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_online_map)); - cpu_set(cpuid, RELOC(cpu_present_map)); - } #endif next: #ifdef CONFIG_SMP @@ -1067,9 +1048,6 @@ next: prom_printf("%x : preparing thread ... ", interrupt_server[i]); if (_naca->smt_state) { - cpu_set(cpuid, RELOC(cpu_present_map)); - cpu_set(cpuid, RELOC(cpu_possible_map)); - _systemcfg->processorCount++; prom_printf("available\n"); } else { prom_printf("not available\n"); @@ -1099,11 +1077,7 @@ next: pir & 0x3ff; } } -/* cpu_set(i+1, cpu_online_map); */ - cpu_set(i+1, RELOC(cpu_possible_map)); - cpu_set(i+1, RELOC(cpu_present_map)); } - _systemcfg->processorCount *= 2; } else { prom_printf("Processor is not HMT capable\n"); } diff -puN arch/ppc64/kernel/setup.c~ppc64-1-3-rework-ppc64-cpu-map-setup arch/ppc64/kernel/setup.c --- 25/arch/ppc64/kernel/setup.c~ppc64-1-3-rework-ppc64-cpu-map-setup 2004-08-30 00:50:17.696074192 -0700 +++ 25-akpm/arch/ppc64/kernel/setup.c 2004-08-30 00:50:17.706072672 -0700 @@ -155,6 +155,94 @@ void __init disable_early_printk(void) early_console_initialized = 0; } +#if !defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) +/** + * setup_cpu_maps - initialize the following cpu maps: + * cpu_possible_map + * cpu_present_map + * cpu_sibling_map + * + * Having the possible map set up early allows us to restrict allocations + * of things like irqstacks to num_possible_cpus() rather than NR_CPUS. + * + * We do not initialize the online map here; cpus set their own bits in + * cpu_online_map as they come up. + * + * This function is valid only for Open Firmware systems. finish_device_tree + * must be called before using this. + */ +static void __init setup_cpu_maps(void) +{ + struct device_node *dn = NULL; + int cpu = 0; + + while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { + u32 *intserv; + int j, len = sizeof(u32), nthreads; + + intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s", + &len); + nthreads = len / sizeof(u32); + + for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { + cpu_set(cpu, cpu_possible_map); + cpu_set(cpu, cpu_present_map); + cpu++; + } + } + + /* + * On pSeries LPAR, we need to know how many cpus + * could possibly be added to this partition. + */ + if (systemcfg->platform == PLATFORM_PSERIES_LPAR && + (dn = of_find_node_by_path("/rtas"))) { + int num_addr_cell, num_size_cell, maxcpus; + unsigned int *ireg; + + num_addr_cell = prom_n_addr_cells(dn); + num_size_cell = prom_n_size_cells(dn); + + ireg = (unsigned int *) + get_property(dn, "ibm,lrdr-capacity", NULL); + + if (!ireg) + goto out; + + maxcpus = ireg[num_addr_cell + num_size_cell]; + + /* Double maxcpus for processors which have SMT capability */ + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + maxcpus *= 2; + + if (maxcpus > NR_CPUS) { + printk(KERN_WARNING + "Partition configured for %d cpus, " + "operating system maximum is %d.\n", + maxcpus, NR_CPUS); + maxcpus = NR_CPUS; + } else + printk(KERN_INFO "Partition configured for %d cpus.\n", + maxcpus); + + for (cpu = 0; cpu < maxcpus; cpu++) + cpu_set(cpu, cpu_possible_map); + out: + of_node_put(dn); + } + + /* + * Do the sibling map; assume only two threads per processor. + */ + for_each_cpu(cpu) { + cpu_set(cpu, cpu_sibling_map[cpu]); + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); + } + + systemcfg->processorCount = num_present_cpus(); +} +#endif /* !defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) */ /* * Do some initial setup of the system. The parameters are those which * were passed in from the bootloader. @@ -220,6 +308,13 @@ void setup_system(unsigned long r3, unsi } #endif /* CONFIG_BOOTX_TEXT */ +#ifdef CONFIG_PPC_PMAC + if (systemcfg->platform == PLATFORM_POWERMAC) { + finish_device_tree(); + pmac_init(r3, r4, r5, r6, r7); + } +#endif /* CONFIG_PPC_PMAC */ + #ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; @@ -227,31 +322,32 @@ void setup_system(unsigned long r3, unsi __irq_offset_value = NUM_ISA_INTERRUPTS; finish_device_tree(); chrp_init(r3, r4, r5, r6, r7); + } +#endif /* CONFIG_PPC_PSERIES */ #ifdef CONFIG_SMP - /* Start secondary threads on SMT systems; primary threads - * are already in the running state. - */ - for_each_present_cpu(i) { - if (query_cpu_stopped - (get_hard_smp_processor_id(i)) == 0) { - printk("%16.16x : starting thread\n", i); - rtas_call(rtas_token("start-cpu"), 3, 1, &ret, - get_hard_smp_processor_id(i), - (u32)*((unsigned long *)pseries_secondary_smp_init), - i); - } +#ifndef CONFIG_PPC_ISERIES + /* + * iSeries has already initialized the cpu maps at this point. + */ + setup_cpu_maps(); +#endif /* CONFIG_PPC_ISERIES */ + +#ifdef CONFIG_PPC_PSERIES + /* Start secondary threads on SMT systems; primary threads + * are already in the running state. + */ + for_each_present_cpu(i) { + if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) { + printk("%16.16x : starting thread\n", i); + rtas_call(rtas_token("start-cpu"), 3, 1, &ret, + get_hard_smp_processor_id(i), + (u32)*((unsigned long *)pseries_secondary_smp_init), + i); } -#endif /* CONFIG_SMP */ } #endif /* CONFIG_PPC_PSERIES */ - -#ifdef CONFIG_PPC_PMAC - if (systemcfg->platform == PLATFORM_POWERMAC) { - finish_device_tree(); - pmac_init(r3, r4, r5, r6, r7); - } -#endif /* CONFIG_PPC_PMAC */ +#endif /* CONFIG_SMP */ #if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_PPC_PMAC) rtas_stop_self_args.token = rtas_token("stop-self"); diff -puN arch/ppc64/kernel/smp.c~ppc64-1-3-rework-ppc64-cpu-map-setup arch/ppc64/kernel/smp.c --- 25/arch/ppc64/kernel/smp.c~ppc64-1-3-rework-ppc64-cpu-map-setup 2004-08-30 00:50:17.698073888 -0700 +++ 25-akpm/arch/ppc64/kernel/smp.c 2004-08-30 00:50:17.707072520 -0700 @@ -401,56 +401,11 @@ static inline int __devinit smp_startup_ } return 1; } - -static inline void look_for_more_cpus(void) -{ - int num_addr_cell, num_size_cell, len, i, maxcpus; - struct device_node *np; - unsigned int *ireg; - - /* Find the property which will tell us about how many CPUs - * we're allowed to have. */ - if ((np = find_path_device("/rtas")) == NULL) { - printk(KERN_ERR "Could not find /rtas in device tree!"); - return; - } - num_addr_cell = prom_n_addr_cells(np); - num_size_cell = prom_n_size_cells(np); - - ireg = (unsigned int *)get_property(np, "ibm,lrdr-capacity", &len); - if (ireg == NULL) { - /* FIXME: make sure not marked as lrdr_capable() */ - return; - } - - maxcpus = ireg[num_addr_cell + num_size_cell]; - - /* Double maxcpus for processors which have SMT capability */ - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - maxcpus *= 2; - - - if (maxcpus > NR_CPUS) { - printk(KERN_WARNING - "Partition configured for %d cpus, " - "operating system maximum is %d.\n", maxcpus, NR_CPUS); - maxcpus = NR_CPUS; - } else - printk(KERN_INFO "Partition configured for %d cpus.\n", - maxcpus); - - /* Make those cpus (which might appear later) possible too. */ - for (i = 0; i < maxcpus; i++) - cpu_set(i, cpu_possible_map); -} #else /* ... CONFIG_HOTPLUG_CPU */ static inline int __devinit smp_startup_cpu(unsigned int lcpu) { return 1; } -static inline void look_for_more_cpus(void) -{ -} #endif /* CONFIG_HOTPLUG_CPU */ static void smp_pSeries_kick_cpu(int nr) @@ -832,8 +787,6 @@ void __init smp_prepare_cpus(unsigned in */ do_gtod.tb_orig_stamp = tb_last_stamp; systemcfg->tb_orig_stamp = tb_last_stamp; - - look_for_more_cpus(); #endif max_cpus = smp_ops->probe(); @@ -846,19 +799,12 @@ void __init smp_prepare_cpus(unsigned in for_each_cpu(cpu) if (cpu != boot_cpuid) smp_create_idle(cpu); - - for_each_cpu(cpu) { - cpu_set(cpu, cpu_sibling_map[cpu]); - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); - } } void __devinit smp_prepare_boot_cpu(void) { BUG_ON(smp_processor_id() != boot_cpuid); - /* cpu_possible is set up in prom.c */ cpu_set(boot_cpuid, cpu_online_map); paca[boot_cpuid].__current = current; _