x86: Move MP initialization codes into a common place
Most of the MP initialization codes in arch/x86/cpu/baytrail/cpu.c is common to all x86 processors, except detect_num_cpus() which varies from cpu to cpu. Move these to arch/x86/cpu/cpu.c and implement the new 'get_count' method for baytrail and cpu_x86 drivers. Now we call cpu_get_count() in mp_init() to get the number of CPUs. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org>utp
parent
946c2b5259
commit
6e6f4ce4f8
|
@ -12,78 +12,9 @@
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
#include <asm/cpu_x86.h>
|
#include <asm/cpu_x86.h>
|
||||||
#include <asm/lapic.h>
|
#include <asm/lapic.h>
|
||||||
#include <asm/mp.h>
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/turbo.h>
|
#include <asm/turbo.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
static int enable_smis(struct udevice *cpu, void *unused)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mp_flight_record mp_steps[] = {
|
|
||||||
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
|
|
||||||
/* Wait for APs to finish initialization before proceeding. */
|
|
||||||
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
|
|
||||||
};
|
|
||||||
|
|
||||||
static int detect_num_cpus(void)
|
|
||||||
{
|
|
||||||
int ecx = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use the algorithm described in Intel 64 and IA-32 Architectures
|
|
||||||
* Software Developer's Manual Volume 3 (3A, 3B & 3C): System
|
|
||||||
* Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
|
|
||||||
* of CPUID Extended Topology Leaf.
|
|
||||||
*/
|
|
||||||
while (1) {
|
|
||||||
struct cpuid_result leaf_b;
|
|
||||||
|
|
||||||
leaf_b = cpuid_ext(0xb, ecx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bay Trail doesn't have hyperthreading so just determine the
|
|
||||||
* number of cores by from level type (ecx[15:8] == * 2)
|
|
||||||
*/
|
|
||||||
if ((leaf_b.ecx & 0xff00) == 0x0200)
|
|
||||||
return leaf_b.ebx & 0xffff;
|
|
||||||
ecx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int baytrail_init_cpus(void)
|
|
||||||
{
|
|
||||||
struct mp_params mp_params;
|
|
||||||
|
|
||||||
lapic_setup();
|
|
||||||
|
|
||||||
mp_params.num_cpus = detect_num_cpus();
|
|
||||||
mp_params.parallel_microcode_load = 0,
|
|
||||||
mp_params.flight_plan = &mp_steps[0];
|
|
||||||
mp_params.num_records = ARRAY_SIZE(mp_steps);
|
|
||||||
mp_params.microcode_pointer = 0;
|
|
||||||
|
|
||||||
if (mp_init(&mp_params)) {
|
|
||||||
printf("Warning: MP init failure\n");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int x86_init_cpus(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
debug("Init additional CPUs\n");
|
|
||||||
baytrail_init_cpus();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_max_freq(void)
|
static void set_max_freq(void)
|
||||||
{
|
{
|
||||||
msr_t perf_ctl;
|
msr_t perf_ctl;
|
||||||
|
@ -176,9 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int baytrail_get_count(struct udevice *dev)
|
||||||
|
{
|
||||||
|
int ecx = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the algorithm described in Intel 64 and IA-32 Architectures
|
||||||
|
* Software Developer's Manual Volume 3 (3A, 3B & 3C): System
|
||||||
|
* Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
|
||||||
|
* of CPUID Extended Topology Leaf.
|
||||||
|
*/
|
||||||
|
while (1) {
|
||||||
|
struct cpuid_result leaf_b;
|
||||||
|
|
||||||
|
leaf_b = cpuid_ext(0xb, ecx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bay Trail doesn't have hyperthreading so just determine the
|
||||||
|
* number of cores by from level type (ecx[15:8] == * 2)
|
||||||
|
*/
|
||||||
|
if ((leaf_b.ecx & 0xff00) == 0x0200)
|
||||||
|
return leaf_b.ebx & 0xffff;
|
||||||
|
|
||||||
|
ecx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct cpu_ops cpu_x86_baytrail_ops = {
|
static const struct cpu_ops cpu_x86_baytrail_ops = {
|
||||||
.get_desc = cpu_x86_get_desc,
|
.get_desc = cpu_x86_get_desc,
|
||||||
.get_info = baytrail_get_info,
|
.get_info = baytrail_get_info,
|
||||||
|
.get_count = baytrail_get_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id cpu_x86_baytrail_ids[] = {
|
static const struct udevice_id cpu_x86_baytrail_ids[] = {
|
||||||
|
|
|
@ -21,10 +21,13 @@
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
|
#include <dm.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <asm/control_regs.h>
|
#include <asm/control_regs.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/lapic.h>
|
||||||
|
#include <asm/mp.h>
|
||||||
#include <asm/post.h>
|
#include <asm/post.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/processor-flags.h>
|
#include <asm/processor-flags.h>
|
||||||
|
@ -621,8 +624,45 @@ int last_stage_init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static int enable_smis(struct udevice *cpu, void *unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mp_flight_record mp_steps[] = {
|
||||||
|
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
|
||||||
|
/* Wait for APs to finish initialization before proceeding */
|
||||||
|
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int x86_mp_init(void)
|
||||||
|
{
|
||||||
|
struct mp_params mp_params;
|
||||||
|
|
||||||
|
lapic_setup();
|
||||||
|
|
||||||
|
mp_params.parallel_microcode_load = 0,
|
||||||
|
mp_params.flight_plan = &mp_steps[0];
|
||||||
|
mp_params.num_records = ARRAY_SIZE(mp_steps);
|
||||||
|
mp_params.microcode_pointer = 0;
|
||||||
|
|
||||||
|
if (mp_init(&mp_params)) {
|
||||||
|
printf("Warning: MP init failure\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__weak int x86_init_cpus(void)
|
__weak int x86_init_cpus(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
debug("Init additional CPUs\n");
|
||||||
|
x86_mp_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
int cpu_x86_bind(struct udevice *dev)
|
int cpu_x86_bind(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||||
|
@ -30,8 +32,34 @@ int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cpu_x86_get_count(struct udevice *dev)
|
||||||
|
{
|
||||||
|
int node, cpu;
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
node = fdt_path_offset(gd->fdt_blob, "/cpus");
|
||||||
|
if (node < 0)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
for (cpu = fdt_first_subnode(gd->fdt_blob, node);
|
||||||
|
cpu >= 0;
|
||||||
|
cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
|
||||||
|
const char *device_type;
|
||||||
|
|
||||||
|
device_type = fdt_getprop(gd->fdt_blob, cpu,
|
||||||
|
"device_type", NULL);
|
||||||
|
if (!device_type)
|
||||||
|
continue;
|
||||||
|
if (strcmp(device_type, "cpu") == 0)
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct cpu_ops cpu_x86_ops = {
|
static const struct cpu_ops cpu_x86_ops = {
|
||||||
.get_desc = cpu_x86_get_desc,
|
.get_desc = cpu_x86_get_desc,
|
||||||
|
.get_count = cpu_x86_get_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id cpu_x86_ids[] = {
|
static const struct udevice_id cpu_x86_ids[] = {
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include <dm/uclass-internal.h>
|
#include <dm/uclass-internal.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/* Total CPUs include BSP */
|
||||||
|
static int num_cpus;
|
||||||
|
|
||||||
/* This also needs to match the sipi.S assembly code for saved MSR encoding */
|
/* This also needs to match the sipi.S assembly code for saved MSR encoding */
|
||||||
struct saved_msr {
|
struct saved_msr {
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
|
@ -383,7 +386,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const int timeout_us = 100000;
|
const int timeout_us = 100000;
|
||||||
const int step_us = 100;
|
const int step_us = 100;
|
||||||
int num_aps = mp_params->num_cpus - 1;
|
int num_aps = num_cpus - 1;
|
||||||
|
|
||||||
for (i = 0; i < mp_params->num_records; i++) {
|
for (i = 0; i < mp_params->num_records; i++) {
|
||||||
struct mp_flight_record *rec = &mp_params->flight_plan[i];
|
struct mp_flight_record *rec = &mp_params->flight_plan[i];
|
||||||
|
@ -451,7 +454,16 @@ int mp_init(struct mp_params *p)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_cpu_devices(p->num_cpus);
|
num_cpus = cpu_get_count(cpu);
|
||||||
|
if (num_cpus < 0) {
|
||||||
|
debug("Cannot get number of CPUs: err=%d\n", num_cpus);
|
||||||
|
return num_cpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_cpus < 2)
|
||||||
|
debug("Warning: Only 1 CPU is detected\n");
|
||||||
|
|
||||||
|
ret = check_cpu_devices(num_cpus);
|
||||||
if (ret)
|
if (ret)
|
||||||
debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
|
debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
|
||||||
|
|
||||||
|
@ -471,7 +483,7 @@ int mp_init(struct mp_params *p)
|
||||||
wbinvd();
|
wbinvd();
|
||||||
|
|
||||||
/* Start the APs providing number of APs and the cpus_entered field */
|
/* Start the APs providing number of APs and the cpus_entered field */
|
||||||
num_aps = p->num_cpus - 1;
|
num_aps = num_cpus - 1;
|
||||||
ret = start_aps(num_aps, ap_count);
|
ret = start_aps(num_aps, ap_count);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mdelay(1000);
|
mdelay(1000);
|
||||||
|
|
|
@ -59,7 +59,6 @@ struct mp_flight_record {
|
||||||
* SMM support.
|
* SMM support.
|
||||||
*/
|
*/
|
||||||
struct mp_params {
|
struct mp_params {
|
||||||
int num_cpus; /* Total cpus include BSP */
|
|
||||||
int parallel_microcode_load;
|
int parallel_microcode_load;
|
||||||
const void *microcode_pointer;
|
const void *microcode_pointer;
|
||||||
/* Flight plan for APs and BSP */
|
/* Flight plan for APs and BSP */
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <dm/lists.h>
|
#include <dm/lists.h>
|
||||||
#include <dm/root.h>
|
#include <dm/root.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
int cpu_get_desc(struct udevice *dev, char *buf, int size)
|
int cpu_get_desc(struct udevice *dev, char *buf, int size)
|
||||||
{
|
{
|
||||||
struct cpu_ops *ops = cpu_get_ops(dev);
|
struct cpu_ops *ops = cpu_get_ops(dev);
|
||||||
|
|
Loading…
Reference in New Issue