Commit 4ad8d383 authored by Zwane Mwaikambo's avatar Zwane Mwaikambo Committed by Linus Torvalds

[PATCH] i386 boottime for_each_cpu broken

for_each_cpu walks through all processors in cpu_possible_map, which is
defined as cpu_callout_map on i386 and isn't initialised until all
processors have been booted. This breaks things which do for_each_cpu
iterations early during boot. So, define cpu_possible_map as a bitmap with
NR_CPUS bits populated. This was triggered by a patch i'm working on which
does alloc_percpu before bringing up secondary processors.

From: Alexander Nyberg <alexn@telia.com>

i386-boottime-for_each_cpu-broken.patch
i386-boottime-for_each_cpu-broken-fix.patch

The SMP version of __alloc_percpu checks the cpu_possible_map before
allocating memory for a certain cpu.  With the above patches the BSP cpuid
is never set in cpu_possible_map which breaks CONFIG_SMP on uniprocessor
machines (as soon as someone tries to dereference something allocated via
__alloc_percpu, which in fact is never allocated since the cpu is not set
in cpu_possible_map).
Signed-off-by: default avatarZwane Mwaikambo <zwane@arm.linux.org.uk>
Signed-off-by: default avatarAlexander Nyberg <alexn@telia.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d7271b14
...@@ -122,7 +122,7 @@ static int MP_valid_apicid(int apicid, int version) ...@@ -122,7 +122,7 @@ static int MP_valid_apicid(int apicid, int version)
static void __init MP_processor_info (struct mpc_config_processor *m) static void __init MP_processor_info (struct mpc_config_processor *m)
{ {
int ver, apicid; int ver, apicid, cpu, found_bsp = 0;
physid_mask_t tmp; physid_mask_t tmp;
if (!(m->mpc_cpuflag & CPU_ENABLED)) if (!(m->mpc_cpuflag & CPU_ENABLED))
...@@ -181,6 +181,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m) ...@@ -181,6 +181,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
Dprintk(" Bootup CPU\n"); Dprintk(" Bootup CPU\n");
boot_cpu_physical_apicid = m->mpc_apicid; boot_cpu_physical_apicid = m->mpc_apicid;
found_bsp = 1;
} }
if (num_processors >= NR_CPUS) { if (num_processors >= NR_CPUS) {
...@@ -204,6 +205,11 @@ static void __init MP_processor_info (struct mpc_config_processor *m) ...@@ -204,6 +205,11 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
return; return;
} }
if (found_bsp)
cpu = 0;
else
cpu = num_processors - 1;
cpu_set(cpu, cpu_possible_map);
tmp = apicid_to_cpu_present(apicid); tmp = apicid_to_cpu_present(apicid);
physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp); physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
......
...@@ -88,6 +88,8 @@ EXPORT_SYMBOL(cpu_online_map); ...@@ -88,6 +88,8 @@ EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_callin_map; cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map; cpumask_t cpu_callout_map;
EXPORT_SYMBOL(cpu_callout_map); EXPORT_SYMBOL(cpu_callout_map);
cpumask_t cpu_possible_map;
EXPORT_SYMBOL(cpu_possible_map);
static cpumask_t smp_commenced_mask; static cpumask_t smp_commenced_mask;
/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there /* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
...@@ -1265,6 +1267,7 @@ void __devinit smp_prepare_boot_cpu(void) ...@@ -1265,6 +1267,7 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callout_map); cpu_set(smp_processor_id(), cpu_callout_map);
cpu_set(smp_processor_id(), cpu_present_map); cpu_set(smp_processor_id(), cpu_present_map);
cpu_set(smp_processor_id(), cpu_possible_map);
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
} }
......
...@@ -242,6 +242,8 @@ static cpumask_t smp_commenced_mask = CPU_MASK_NONE; ...@@ -242,6 +242,8 @@ static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
cpumask_t cpu_callin_map = CPU_MASK_NONE; cpumask_t cpu_callin_map = CPU_MASK_NONE;
cpumask_t cpu_callout_map = CPU_MASK_NONE; cpumask_t cpu_callout_map = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_callout_map); EXPORT_SYMBOL(cpu_callout_map);
cpumask_t cpu_possible_map = CPU_MASK_ALL;
EXPORT_SYMBOL(cpu_possible_map);
/* The per processor IRQ masks (these are usually kept in sync) */ /* The per processor IRQ masks (these are usually kept in sync) */
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned; static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
...@@ -1910,6 +1912,7 @@ void __devinit smp_prepare_boot_cpu(void) ...@@ -1910,6 +1912,7 @@ void __devinit smp_prepare_boot_cpu(void)
{ {
cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callout_map); cpu_set(smp_processor_id(), cpu_callout_map);
cpu_set(smp_processor_id(), cpu_possible_map);
} }
int __devinit int __devinit
......
...@@ -59,7 +59,7 @@ extern void cpu_uninit(void); ...@@ -59,7 +59,7 @@ extern void cpu_uninit(void);
extern cpumask_t cpu_callout_map; extern cpumask_t cpu_callout_map;
extern cpumask_t cpu_callin_map; extern cpumask_t cpu_callin_map;
#define cpu_possible_map cpu_callout_map extern cpumask_t cpu_possible_map;
/* We don't mark CPUs online until __cpu_up(), so we need another measure */ /* We don't mark CPUs online until __cpu_up(), so we need another measure */
static inline int num_booting_cpus(void) static inline int num_booting_cpus(void)
......
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