aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarnali Sarkar <barnali.sarkar@intel.com>2017-06-13 19:17:35 +0530
committerAaron Durbin <adurbin@chromium.org>2017-06-23 15:48:30 +0000
commit91d38a5b0e070e75f32b30cb7297a801e31282f6 (patch)
tree5f784d79ac6220ed86b0a04994b60827ab103b0b
parent71dacacb748a73e44ea86ec571cc4ec9ff667d9d (diff)
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>
-rw-r--r--src/soc/intel/common/block/cpu/Kconfig13
-rw-r--r--src/soc/intel/common/block/cpu/Makefile.inc1
-rw-r--r--src/soc/intel/common/block/cpu/cpulib.c14
-rw-r--r--src/soc/intel/common/block/cpu/mp_init.c141
-rw-r--r--src/soc/intel/common/block/include/intelblocks/cpulib.h7
-rw-r--r--src/soc/intel/common/block/include/intelblocks/mp_init.h72
6 files changed, 247 insertions, 1 deletions
diff --git a/src/soc/intel/common/block/cpu/Kconfig b/src/soc/intel/common/block/cpu/Kconfig
index 56b0064d59..48f3f1645c 100644
--- a/src/soc/intel/common/block/cpu/Kconfig
+++ b/src/soc/intel/common/block/cpu/Kconfig
@@ -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
diff --git a/src/soc/intel/common/block/cpu/Makefile.inc b/src/soc/intel/common/block/cpu/Makefile.inc
index 4253844582..aa61ffc7f2 100644
--- a/src/soc/intel/common/block/cpu/Makefile.inc
+++ b/src/soc/intel/common/block/cpu/Makefile.inc
@@ -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
diff --git a/src/soc/intel/common/block/cpu/cpulib.c b/src/soc/intel/common/block/cpu/cpulib.c
index 325e1bb857..5920512cd4 100644
--- a/src/soc/intel/common/block/cpu/cpulib.c
+++ b/src/soc/intel/common/block/cpu/cpulib.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);
+}
diff --git a/src/soc/intel/common/block/cpu/mp_init.c b/src/soc/intel/common/block/cpu/mp_init.c
new file mode 100644
index 0000000000..e147bb01f3
--- /dev/null
+++ b/src/soc/intel/common/block/cpu/mp_init.c
@@ -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);
diff --git a/src/soc/intel/common/block/include/intelblocks/cpulib.h b/src/soc/intel/common/block/include/intelblocks/cpulib.h
index 0038ecdb7a..f4145219b5 100644
--- a/src/soc/intel/common/block/include/intelblocks/cpulib.h
+++ b/src/soc/intel/common/block/include/intelblocks/cpulib.h
@@ -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 */
diff --git a/src/soc/intel/common/block/include/intelblocks/mp_init.h b/src/soc/intel/common/block/include/intelblocks/mp_init.h
new file mode 100644
index 0000000000..3a021c6f84
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/mp_init.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 */