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:
Barnali Sarkar 2017-06-13 19:17:35 +05:30 committed by Aaron Durbin
parent 71dacacb74
commit 91d38a5b0e
6 changed files with 247 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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 */