diff options
Diffstat (limited to 'src/cpu/x86/lapic')
-rw-r--r-- | src/cpu/x86/lapic/lapic_cpu_init.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c index ef150a50d7..bf63517384 100644 --- a/src/cpu/x86/lapic/lapic_cpu_init.c +++ b/src/cpu/x86/lapic/lapic_cpu_init.c @@ -458,6 +458,39 @@ static void start_other_cpus(struct bus *cpu_bus, struct device *bsp_cpu) } +static void smm_other_cpus(struct bus *cpu_bus, device_t bsp_cpu) +{ + device_t cpu; + int pre_count = atomic_read(&active_cpus); + + /* Loop through the cpus once to let them run through SMM relocator */ + + for(cpu = cpu_bus->children; cpu ; cpu = cpu->sibling) { + if (cpu->path.type != DEVICE_PATH_APIC) { + continue; + } + + printk(BIOS_ERR, "considering CPU 0x%02x for SMM init\n", + cpu->path.apic.apic_id); + + if (cpu == bsp_cpu) + continue; + + if (!cpu->enabled) { + continue; + } + + if (!start_cpu(cpu)) { + /* Record the error in cpu? */ + printk(BIOS_ERR, "CPU 0x%02x would not start!\n", + cpu->path.apic.apic_id); + } + + /* FIXME: endless loop */ + while (atomic_read(&active_cpus) != pre_count) ; + } +} + static void wait_other_cpus_stop(struct bus *cpu_bus) { struct device *cpu; @@ -528,7 +561,8 @@ void initialize_cpus(struct bus *cpu_bus) #endif #if CONFIG_HAVE_SMI_HANDLER - smm_init(); + if (!IS_ENABLED(CONFIG_SERIALIZED_SMM_INITIALIZATION)) + smm_init(); #endif #if CONFIG_SMP && CONFIG_MAX_CPUS > 1 @@ -547,4 +581,15 @@ void initialize_cpus(struct bus *cpu_bus) /* Now wait the rest of the cpus stop*/ wait_other_cpus_stop(cpu_bus); #endif + + if (IS_ENABLED(CONFIG_SERIALIZED_SMM_INITIALIZATION)) { + /* At this point, all APs are sleeping: + * smm_init() will queue a pending SMI on all cpus + * and smm_other_cpus() will start them one by one */ + smm_init(); +#if CONFIG_SMP && CONFIG_MAX_CPUS > 1 + last_cpu_index = 0; + smm_other_cpus(cpu_bus, info->cpu); +#endif + } } |