soc/intel/common/block: Add common MP Init code
This patch contains State Machine callbacks init_cpus() and post_cpu_init(). Also, it has the SOC call for CPU feature programming. Change-Id: I5b20d413c85bf7ec6ed89b4cdf1770c33507236b Signed-off-by: Barnali Sarkar <barnali.sarkar@intel.com> Reviewed-on: https://review.coreboot.org/20189 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
parent
71dacacb74
commit
91d38a5b0e
|
@ -2,11 +2,22 @@ config SOC_INTEL_COMMON_BLOCK_CPU
|
|||
bool
|
||||
default n
|
||||
help
|
||||
This option helps to select Intel Common CPU Model support code
|
||||
This option selects Intel Common CPU Model support code
|
||||
which provides various CPU related APIs which are common
|
||||
between all Intel Processor families. Common CPU code is supported
|
||||
for SOCs starting from SKL,KBL,APL, and future.
|
||||
|
||||
config SOC_INTEL_COMMON_BLOCK_CPU_MPINIT
|
||||
bool
|
||||
default n
|
||||
help
|
||||
This option selects Intel Common CPU MP Init code. In
|
||||
this common MP Init mechanism, the MP Init is occurring before
|
||||
calling FSP Silicon Init. Hence, MP Init will be pulled to
|
||||
BS_DEV_INIT_CHIPS Entry. And on Exit of BS_DEV_INIT, it is
|
||||
ensured that all MTRRs are re-programmed based on the DRAM
|
||||
resource settings.
|
||||
|
||||
config SOC_INTEL_COMMON_BLOCK_CAR
|
||||
bool
|
||||
default n
|
||||
|
|
|
@ -7,3 +7,4 @@ romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU) += cpulib.c
|
|||
postcar-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CAR) += car/exit_car.S
|
||||
|
||||
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU) += cpulib.c
|
||||
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CPU_MPINIT) += mp_init.c
|
||||
|
|
|
@ -226,3 +226,17 @@ void cpu_enable_untrusted_mode(void)
|
|||
msr.lo |= ENABLE_IA_UNTRUSTED;
|
||||
wrmsr(MSR_POWER_MISC, msr);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function fills in the number of Cores(physical) and Threads(virtual)
|
||||
* of the CPU in the function arguments. It also returns if the number of cores
|
||||
* and number of threads are equal.
|
||||
*/
|
||||
int cpu_read_topology(unsigned int *num_phys, unsigned int *num_virt)
|
||||
{
|
||||
msr_t msr;
|
||||
msr = rdmsr(MSR_CORE_THREAD_COUNT);
|
||||
*num_virt = (msr.lo >> 0) & 0xffff;
|
||||
*num_phys = (msr.lo >> 16) & 0xffff;
|
||||
return (*num_virt == *num_phys);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <assert.h>
|
||||
#include <bootstate.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <cpu/x86/mp.h>
|
||||
#include <cpu/intel/microcode.h>
|
||||
#include <intelblocks/cpulib.h>
|
||||
#include <intelblocks/fast_spi.h>
|
||||
#include <intelblocks/mp_init.h>
|
||||
#include <intelblocks/msr.h>
|
||||
#include <soc/cpu.h>
|
||||
|
||||
static const void *microcode_patch;
|
||||
|
||||
/* SoC override function */
|
||||
__attribute__((weak)) void soc_core_init(device_t dev, const void *microcode)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
__attribute__((weak)) void soc_init_cpus(struct bus *cpu_bus,
|
||||
const void *microcode)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
static void init_one_cpu(device_t dev)
|
||||
{
|
||||
soc_core_init(dev, microcode_patch);
|
||||
intel_microcode_load_unlocked(microcode_patch);
|
||||
}
|
||||
|
||||
static struct device_operations cpu_dev_ops = {
|
||||
.init = init_one_cpu,
|
||||
};
|
||||
|
||||
static struct cpu_device_id cpu_table[] = {
|
||||
{ X86_VENDOR_INTEL, CPUID_SKYLAKE_C0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_SKYLAKE_D0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_SKYLAKE_HQ0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_SKYLAKE_HR0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_KABYLAKE_G0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_KABYLAKE_H0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_KABYLAKE_Y0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_KABYLAKE_HA0 },
|
||||
{ X86_VENDOR_INTEL, CPUID_KABYLAKE_HB0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct cpu_driver driver __cpu_driver = {
|
||||
.ops = &cpu_dev_ops,
|
||||
.id_table = cpu_table,
|
||||
};
|
||||
|
||||
/*
|
||||
* MP Init callback function to Find CPU Topology. This function is common
|
||||
* among all SOCs and thus its in Common CPU block.
|
||||
*/
|
||||
int get_cpu_count(void)
|
||||
{
|
||||
unsigned int num_virt_cores, num_phys_cores;
|
||||
|
||||
cpu_read_topology(&num_phys_cores, &num_virt_cores);
|
||||
|
||||
printk(BIOS_DEBUG, "Detected %u core, %u thread CPU.\n",
|
||||
num_phys_cores, num_virt_cores);
|
||||
|
||||
return num_virt_cores;
|
||||
}
|
||||
|
||||
/*
|
||||
* MP Init callback function(get_microcode_info) to find the Microcode at
|
||||
* Pre MP Init phase. This function is common among all SOCs and thus its in
|
||||
* Common CPU block.
|
||||
* This function also fills in the microcode patch (in *microcode), and also
|
||||
* sets the argument *parallel to 1, which allows microcode loading in all
|
||||
* APs to occur in parallel during MP Init.
|
||||
*/
|
||||
void get_microcode_info(const void **microcode, int *parallel)
|
||||
{
|
||||
*microcode =microcode_patch;
|
||||
*parallel = 1;
|
||||
}
|
||||
|
||||
static void init_cpus(void *unused)
|
||||
{
|
||||
device_t dev = dev_find_path(NULL, DEVICE_PATH_CPU_CLUSTER);
|
||||
assert(dev != NULL);
|
||||
|
||||
microcode_patch = intel_microcode_find();
|
||||
intel_microcode_load_unlocked(microcode_patch);
|
||||
|
||||
/*
|
||||
* TODO: This parameter "microcode_patch" should be removed
|
||||
* in this function call once the following two cases are resolved -
|
||||
*
|
||||
* 1) SGX enabling for the BSP issue gets solved, due to which
|
||||
* configure_sgx() function is kept inside soc/cpu.c soc_init_cpus().
|
||||
* 2) uCode loading after SMM relocation is deleted inside
|
||||
* per_cpu_smm_trigger() mp_ops callback function in soc/cpu.c,
|
||||
* since as per current BWG, uCode loading can be done after
|
||||
* all feature programmings are done. There is no specific
|
||||
* recommendation to do it after SMM Relocation.
|
||||
*/
|
||||
soc_init_cpus(dev->link_list, microcode_patch);
|
||||
}
|
||||
|
||||
/* Ensure to re-program all MTRRs based on DRAM resource settings */
|
||||
static void post_cpus_init(void *unused)
|
||||
{
|
||||
if (mp_run_on_all_cpus(&x86_setup_mtrrs_with_detect, 1000) < 0)
|
||||
printk(BIOS_ERR, "MTRR programming failure\n");
|
||||
|
||||
/* Temporarily cache the memory-mapped boot media. */
|
||||
if (IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED) &&
|
||||
IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH))
|
||||
fast_spi_cache_bios_region();
|
||||
|
||||
x86_mtrr_check();
|
||||
}
|
||||
|
||||
/* Do CPU MP Init before FSP Silicon Init */
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, init_cpus, NULL);
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, post_cpus_init, NULL);
|
|
@ -114,4 +114,11 @@ void cpu_disable_eist(void);
|
|||
*/
|
||||
void cpu_enable_untrusted_mode(void);
|
||||
|
||||
/*
|
||||
* This function fills in the number of Cores(physical) and Threads(virtual)
|
||||
* of the CPU in the function arguments. It also returns if the number of cores
|
||||
* and number of threads are equal.
|
||||
*/
|
||||
int cpu_read_topology(unsigned int *num_phys, unsigned int *num_virt);
|
||||
|
||||
#endif /* SOC_INTEL_COMMON_BLOCK_CPULIB_H */
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2017 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef SOC_INTEL_COMMON_BLOCK_MP_INIT_H
|
||||
#define SOC_INTEL_COMMON_BLOCK_MP_INIT_H
|
||||
|
||||
#include <device/device.h>
|
||||
|
||||
/* Supported CPUIDs for different SOCs */
|
||||
#define CPUID_SKYLAKE_C0 0x406e2
|
||||
#define CPUID_SKYLAKE_D0 0x406e3
|
||||
#define CPUID_SKYLAKE_HQ0 0x506e1
|
||||
#define CPUID_SKYLAKE_HR0 0x506e3
|
||||
#define CPUID_KABYLAKE_G0 0x406e8
|
||||
#define CPUID_KABYLAKE_H0 0x806e9
|
||||
#define CPUID_KABYLAKE_Y0 0x806ea
|
||||
#define CPUID_KABYLAKE_HA0 0x506e8
|
||||
#define CPUID_KABYLAKE_HB0 0x906e9
|
||||
#define CPUID_APOLLOLAKE_A0 0x506c8
|
||||
#define CPUID_APOLLOLAKE_B0 0x506c9
|
||||
|
||||
/*
|
||||
* MP Init callback function to Find CPU Topology. This function is common
|
||||
* among all SOCs and thus its in Common CPU block.
|
||||
*/
|
||||
int get_cpu_count(void);
|
||||
|
||||
/*
|
||||
* MP Init callback function(get_microcode_info) to find the Microcode at
|
||||
* Pre MP Init phase. This function is common among all SOCs and thus its in
|
||||
* Common CPU block.
|
||||
* This function also fills in the microcode patch (in *microcode), and also
|
||||
* sets the argument *parallel to 1, which allows microcode loading in all
|
||||
* APs to occur in parallel during MP Init.
|
||||
*/
|
||||
void get_microcode_info(const void **microcode, int *parallel);
|
||||
|
||||
/*
|
||||
* SoC Overrides
|
||||
*
|
||||
* All new SoC must implement below functionality for ramstage.
|
||||
*/
|
||||
|
||||
/*
|
||||
* In this function SOC must perform CPU feature programming
|
||||
* during Ramstage phase.
|
||||
*/
|
||||
void soc_core_init(device_t dev, const void *microcode);
|
||||
|
||||
/*
|
||||
* In this function SOC must fill required mp_ops params, also it
|
||||
* should call these mp_ops callback functions by calling
|
||||
* mp_init_with_smm() function from x86/mp_init.c file.
|
||||
*
|
||||
* Also, if there is any other SOC specific functionalities to be
|
||||
* implemented before or after MP Init, it can be done here.
|
||||
*/
|
||||
void soc_init_cpus(struct bus *cpu_bus, const void *microcode);
|
||||
|
||||
#endif /* SOC_INTEL_COMMON_BLOCK_MP_INIT_H */
|
Loading…
Reference in New Issue