Commit 815e7a88 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc64: rework PPC64 cpu map setup

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: default avatarNathan Lynch <nathanl@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ce26f197
......@@ -939,20 +939,11 @@ static void __init prom_hold_cpus(unsigned long mem)
prom_getprop(node, "reg", &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(unsigned long mem)
* 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 @@ static void __init prom_hold_cpus(unsigned long mem)
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 @@ static void __init prom_hold_cpus(unsigned long mem)
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");
}
......
......@@ -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, unsigned long r4, unsigned long r5,
}
#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, unsigned long r4, unsigned long r5,
__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");
......
......@@ -401,56 +401,11 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
}
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 int max_cpus)
*/
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 int max_cpus)
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment