diff options
author | Sven Schnelle <svens@stackframe.org> | 2012-06-17 10:32:55 +0200 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2012-07-02 19:39:08 +0200 |
commit | 042c1461fb777e583e5de48edf9326e47ee5595f (patch) | |
tree | 489bf29958a39f8a0169e451c7f080e99d25eadd /src/arch/x86/lib/cpu.c | |
parent | 9ed1456eff73d1a268eabb84176dd2a2107bf2d7 (diff) |
Use broadcast SIPI to startup siblings
The current code for initializing AP cpus has several shortcomings:
- it assumes APIC IDs are sequential
- it uses only the BSP for determining the AP count, which is bad if
there's more than one physical CPU, and CPUs are of different type
Note that the new code call cpu->ops->init() in parallel, and therefore
some CPU code needs to be changed to address that. One example are old
Intel HT enabled CPUs which can't do microcode update in parallel.
Change-Id: Ic48a1ebab6a7c52aa76765f497268af09fa38c25
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Reviewed-on: http://review.coreboot.org/1139
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/arch/x86/lib/cpu.c')
-rw-r--r-- | src/arch/x86/lib/cpu.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/src/arch/x86/lib/cpu.c b/src/arch/x86/lib/cpu.c index 98ede068ef..2d64be95ba 100644 --- a/src/arch/x86/lib/cpu.c +++ b/src/arch/x86/lib/cpu.c @@ -9,6 +9,7 @@ #include <device/path.h> #include <device/device.h> #include <smp/spinlock.h> +#include <cpu/x86/lapic.h> /* Standard macro to see if a specific flag is changeable */ static inline int flag_is_changeable_p(uint32_t flag) @@ -234,7 +235,11 @@ static void set_cpu_ops(struct device *cpu) cpu->ops = driver ? driver->ops : NULL; } -void cpu_initialize(void) +#if CONFIG_SMP +static spinlock_t start_cpu_lock = SPIN_LOCK_UNLOCKED; +#endif + +void cpu_initialize(struct bus *cpu_bus, int index) { /* Because we busy wait at the printk spinlock. * It is important to keep the number of printed messages @@ -242,17 +247,22 @@ void cpu_initialize(void) * disabled. */ struct device *cpu; - struct cpu_info *info; struct cpuinfo_x86 c; - - info = cpu_info(); - - printk(BIOS_INFO, "Initializing CPU #%ld\n", info->index); - - cpu = info->cpu; - if (!cpu) { - die("CPU: missing cpu device structure"); - } + struct device_path cpu_path; + unsigned char id = lapicid(); + + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.apic.apic_id = id; + cpu_path.apic.index = index; + +#if CONFIG_SMP + spin_lock(&start_cpu_lock); +#endif + cpu = alloc_find_dev(cpu_bus, &cpu_path); +#if CONFIG_SMP + spin_unlock(&start_cpu_lock); +#endif + printk(BIOS_DEBUG, "Initializing CPU #%d\n", id); /* Find what type of cpu we are dealing with */ identify_cpu(cpu); @@ -276,7 +286,6 @@ void cpu_initialize(void) printk(BIOS_DEBUG, "Using generic cpu ops (good)\n"); } - /* Initialize the cpu */ if (cpu->ops && cpu->ops->init) { cpu->enabled = 1; @@ -284,7 +293,7 @@ void cpu_initialize(void) cpu->ops->init(cpu); } - printk(BIOS_INFO, "CPU #%ld initialized\n", info->index); + printk(BIOS_INFO, "CPU #%d initialized\n", id); return; } |