coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
cpu.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpigen.h>
4 #include <assert.h>
5 #include <console/console.h>
6 #include <console/debug.h>
7 #include <cpu/cpu.h>
10 #include <cpu/intel/microcode.h>
11 #include <cpu/intel/smm_reloc.h>
12 #include <cpu/intel/turbo.h>
13 #include <cpu/x86/mp.h>
14 #include <cpu/x86/mtrr.h>
15 #include <intelblocks/cpulib.h>
16 #include <intelblocks/mp_init.h>
17 #include <intelpch/lockdown.h>
18 #include <soc/cpu.h>
19 #include <soc/msr.h>
20 #include <soc/pci_devs.h>
21 #include <soc/pm.h>
22 #include <soc/smmrelocate.h>
23 #include <soc/soc_util.h>
24 #include <soc/util.h>
25 #include <types.h>
26 
27 #include "chip.h"
28 
29 static const void *microcode_patch;
30 
31 static const config_t *chip_config = NULL;
32 
34 {
35  /* IA_UNTRUSTED_MODE is not supported in Cooper Lake */
36  return false;
37 }
38 
39 static void xeon_configure_mca(void)
40 {
41  msr_t msr;
42  struct cpuid_result cpuid_regs;
43 
44  /*
45  * Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE
46  * and CPUID.(EAX=1):EDX[14]==1 MCA
47  */
48  cpuid_regs = cpuid(1);
49  if ((cpuid_regs.edx & (1 << 7 | 1 << 14)) != (1 << 7 | 1 << 14))
50  return;
51 
52  msr = rdmsr(IA32_MCG_CAP);
53  if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) {
54  /* Enable all error logging */
55  msr.lo = msr.hi = 0xffffffff;
56  wrmsr(IA32_MCG_CTL, msr);
57  }
58 
59  mca_configure();
60 }
61 
62 /*
63  * On server platforms the FIT mechanism only updates the microcode on
64  * the BSP. Loading MCU on AP in parallel seems to fail in 10% of the cases
65  * so do it serialized.
66  */
67 void get_microcode_info(const void **microcode, int *parallel)
68 {
70  *parallel = 0;
71 }
72 
73 static void each_cpu_init(struct device *cpu)
74 {
75  msr_t msr;
76 
77  printk(BIOS_SPEW, "%s dev: %s, cpu: %d, apic_id: 0x%x\n",
78  __func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id);
79 
80  /*
81  * Set HWP base feature, EPP reg enumeration, lock thermal and msr
82  * This is package level MSR. Need to check if it updates correctly on
83  * multi-socket platform.
84  */
85  msr = rdmsr(MSR_MISC_PWR_MGMT);
86  if (!(msr.lo & LOCK_MISC_PWR_MGMT_MSR)) { /* if already locked skip update */
90  }
91 
92  /* Enable Fast Strings */
93  msr = rdmsr(IA32_MISC_ENABLE);
95  wrmsr(IA32_MISC_ENABLE, msr);
96  /* Enable Turbo */
97  enable_turbo();
98 
99  /* Enable speed step. */
100  if (get_turbo_state() == TURBO_ENABLED) {
101  msr = rdmsr(IA32_MISC_ENABLE);
102  msr.lo |= SPEED_STEP_ENABLE_BIT;
103  wrmsr(IA32_MISC_ENABLE, msr);
104  }
105 
106  /* Clear out pending MCEs */
108 
109  /* Enable Vmx */
111  set_aesni_lock();
112 
113  /* The MSRs and CSRS have the same register layout. Use the CSRS bit definitions
114  Lock Turbo. Did FSP-S set this up??? */
118 }
119 
120 static struct device_operations cpu_dev_ops = {
121  .init = each_cpu_init,
122 };
123 
124 static const struct cpu_device_id cpu_table[] = {
127  {0, 0},
128 };
129 
130 static const struct cpu_driver driver __cpu_driver = {
131  .ops = &cpu_dev_ops,
132  .id_table = cpu_table,
133 };
134 
135 static void set_max_turbo_freq(void)
136 {
137  msr_t msr, perf_ctl;
138 
139  FUNC_ENTER();
140  perf_ctl.hi = 0;
141 
142  /* Check for configurable TDP option */
143  if (get_turbo_state() == TURBO_ENABLED) {
145  perf_ctl.lo = (msr.lo & 0xff) << 8;
146  } else if (cpu_config_tdp_levels()) {
147  /* Set to nominal TDP ratio */
149  perf_ctl.lo = (msr.lo & 0xff) << 8;
150  } else {
151  /* Platform Info bits 15:8 give max ratio */
152  msr = rdmsr(MSR_PLATFORM_INFO);
153  perf_ctl.lo = msr.lo & 0xff00;
154  }
155  wrmsr(IA32_PERF_CTL, perf_ctl);
156 
157  printk(BIOS_DEBUG, "cpu: frequency set to %d\n",
158  ((perf_ctl.lo >> 8) & 0xff) * CONFIG_CPU_BCLK_MHZ);
159  FUNC_EXIT();
160 }
161 
162 /*
163  * Do essential initialization tasks before APs can be fired up
164  */
165 static void pre_mp_init(void)
166 {
168  x86_mtrr_check();
169 }
170 
171 static int get_thread_count(void)
172 {
173  unsigned int num_phys = 0, num_virts = 0;
174 
175  cpu_read_topology(&num_phys, &num_virts);
176  printk(BIOS_SPEW, "Detected %u cores and %u threads\n", num_phys, num_virts);
177  /*
178  * Currently we do not know a way to figure out how many CPUs we have total
179  * on multi-socketed. So we pretend all sockets are populated with CPUs with
180  * same thread/core fusing.
181  * TODO: properly figure out number of active sockets OR refactor MPinit code
182  * to remove requirements of having to know total number of CPUs in advance.
183  */
184  return num_virts * CONFIG_MAX_SOCKET;
185 }
186 
187 static void post_mp_init(void)
188 {
189  /* Set Max Ratio */
191 
192  if (CONFIG(HAVE_SMI_HANDLER)) {
195  pmc_lock_smi();
196  }
197 }
198 
199 static const struct mp_ops mp_ops = {
201  .get_cpu_count = get_thread_count,
202  .get_smm_info = get_smm_info,
203  .pre_mp_smm_init = smm_southbridge_clear_state,
204  .relocation_handler = smm_relocation_handler,
205  .get_microcode_info = get_microcode_info,
206  .post_mp_init = post_mp_init,
207 };
208 
209 void cpx_init_cpus(struct device *dev)
210 {
212 
213  if (!microcode_patch)
214  printk(BIOS_ERR, "microcode not found in CBFS!\n");
215 
217 
218  /* TODO: Handle mp_init_with_smm failure? */
220 
221  /*
222  * chip_config is used in cpu device callback. Other than cpu 0,
223  * rest of the CPU devices do not have chip_info updated.
224  */
225  chip_config = dev->chip_info;
226 
227  /* update numa domain for all cpu devices */
229 }
int cpu_index(void)
Definition: cpu.c:332
#define X86_VENDOR_INTEL
Definition: cpu.h:138
#define printk(level,...)
Definition: stdlib.h:16
void set_aesni_lock(void)
Definition: common_init.c:146
void set_vmx_and_lock(void)
Definition: common_init.c:15
#define MSR_MISC_PWR_MGMT
Definition: haswell.h:51
#define MSR_TURBO_RATIO_LIMIT
Definition: haswell.h:53
#define MSR_TURBO_ACTIVATION_RATIO
Definition: haswell.h:99
int cpu_config_tdp_levels(void)
Definition: haswell_init.c:300
#define MSR_CONFIG_TDP_NOMINAL
Definition: haswell.h:95
void smm_relocation_handler(int cpu, uintptr_t curr_smbase, uintptr_t staggered_smbase)
Definition: smmrelocate.c:90
enum cb_err mp_init_with_smm(struct bus *cpu_bus, const struct mp_ops *mp_ops)
Definition: mp_init.c:1145
void x86_mtrr_check(void)
Definition: mtrr.c:836
void x86_setup_mtrrs_with_detect(void)
Definition: mtrr.c:823
#define CPUID_COOPERLAKE_SP_A0
Definition: cpu_ids.h:9
#define CPUID_COOPERLAKE_SP_A1
Definition: cpu_ids.h:10
void mca_configure(void)
Definition: cpulib.c:376
int cpu_read_topology(unsigned int *num_phys, unsigned int *num_virt)
Definition: cpulib.c:267
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
@ CONFIG
Definition: dsi_common.h:201
#define MSR_PLATFORM_INFO
Definition: fsb.c:16
#define FUNC_ENTER()
Definition: debug.h:17
#define FUNC_EXIT()
Definition: debug.h:18
#define FAST_STRINGS_ENABLE_BIT
Definition: msr.h:46
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_MISC_ENABLE
Definition: msr.h:45
#define IA32_PERF_CTL
Definition: msr.h:43
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
#define IA32_MCG_CAP
Definition: msr.h:39
#define SPEED_STEP_ENABLE_BIT
Definition: msr.h:47
void global_smi_enable(void)
Set the EOS bit and enable SMI generation from southbridge.
Definition: smi_util.c:60
int get_lockdown_config(void)
Definition: lockdown.c:22
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
void intel_microcode_load_unlocked(const void *microcode_patch)
Definition: microcode.c:71
const void * intel_microcode_find(void)
Definition: microcode.c:223
void smm_southbridge_clear_state(void)
Definition: smm.c:22
u32 cpuid
bool cpu_soc_is_in_untrusted_mode(void)
Definition: cpu.c:33
void get_microcode_info(const void **microcode, int *parallel)
Definition: cpu.c:180
static void pmc_lock_smi(void)
Definition: lockdown.c:33
@ CHIPSET_LOCKDOWN_COREBOOT
Definition: cfg.h:12
static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size)
Definition: cpu.c:149
#define IA32_MCG_CTL
Definition: msr.h:19
#define IA32_MCG_CAP_CTL_P_MASK
Definition: msr.h:18
static void set_max_turbo_freq(void)
Definition: cpu.c:135
static void each_cpu_init(struct device *cpu)
Definition: cpu.c:73
static void xeon_configure_mca(void)
Definition: cpu.c:39
static const struct cpu_driver driver __cpu_driver
Definition: cpu.c:130
static int get_thread_count(void)
Definition: cpu.c:171
static const config_t * chip_config
Definition: cpu.c:31
static const void * microcode_patch
Definition: cpu.c:29
static void pre_mp_init(void)
Definition: cpu.c:165
void cpx_init_cpus(struct device *dev)
Definition: cpu.c:209
static const struct cpu_device_id cpu_table[]
Definition: cpu.c:124
static struct device_operations cpu_dev_ops
Definition: cpu.c:120
static void post_mp_init(void)
Definition: cpu.c:187
#define TURBO_ACTIVATION_RATIO_LOCK
Definition: pci_devs.h:30
#define HWP_EPP_ENUM_ENABLE
Definition: msr.h:66
#define LOCK_MISC_PWR_MGMT_MSR
Definition: msr.h:68
#define LOCK_THERM_INT
Definition: msr.h:70
#define HWP_ENUM_ENABLE
Definition: msr.h:64
void xeonsp_init_cpu_config(void)
#define NULL
Definition: stddef.h:19
unsigned int apic_id
Definition: path.h:72
Definition: cpu.h:13
struct device_operations * ops
Definition: cpu.h:14
uint32_t edx
Definition: cpu.h:33
void(* init)(struct device *dev)
Definition: device.h:42
struct apic_path apic
Definition: path.h:119
Definition: device.h:107
struct device_path path
Definition: device.h:115
DEVTREE_CONST struct bus * link_list
Definition: device.h:139
DEVTREE_CONST void * chip_info
Definition: device.h:164
Definition: mp.h:20
void(* pre_mp_init)(void)
Definition: mp.h:27
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
int get_turbo_state(void)
Definition: turbo.c:75
void enable_turbo(void)
Definition: turbo.c:89
@ TURBO_ENABLED
Definition: turbo.h:18