coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
mp_init.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <cpu/x86/mtrr.h>
5 #include <cpu/x86/mp.h>
6 #include <cpu/intel/microcode.h>
7 #include <cpu/intel/smm_reloc.h>
9 #include <device/device.h>
10 #include <types.h>
11 
12 /* Parallel MP initialization support. */
13 static void pre_mp_init(void)
14 {
15  const void *patch = intel_microcode_find();
17 
18  /* Setup MTRRs based on physical address size. */
21 }
22 
23 static int get_cpu_count(void)
24 {
25  const struct cpuid_result cpuid1 = cpuid(1);
26  const unsigned int cores = (cpuid1.ebx >> 16) & 0xf;
27 
28  printk(BIOS_DEBUG, "CPU has %u cores.\n", cores);
29 
30  return cores;
31 }
32 
33 static void get_microcode_info(const void **microcode, int *parallel)
34 {
36  *parallel = !intel_ht_supported();
37 }
38 
39 /* the SMRR enable and lock bit need to be set in IA32_FEATURE_CONTROL
40  to enable SMRR so configure IA32_FEATURE_CONTROL early on */
41 static void pre_mp_smm_init(void)
42 {
44 }
45 
46 #define SMRR_SUPPORTED (1 << 11)
47 
48 static void per_cpu_smm_trigger(void)
49 {
50  msr_t mtrr_cap = rdmsr(MTRR_CAP_MSR);
51  if (cpu_has_alternative_smrr() && mtrr_cap.lo & SMRR_SUPPORTED) {
53  msr_t ia32_ft_ctrl = rdmsr(IA32_FEATURE_CONTROL);
54  /* We don't care if the lock is already setting
55  as our smm relocation handler is able to handle
56  setups where SMRR is not enabled here. */
57  if (ia32_ft_ctrl.lo & (1 << 0)) {
58  /* IA32_FEATURE_CONTROL locked. If we set it again we
59  get an illegal instruction. */
60  printk(BIOS_DEBUG, "IA32_FEATURE_CONTROL already locked\n");
61  printk(BIOS_DEBUG, "SMRR status: %senabled\n",
62  ia32_ft_ctrl.lo & (1 << 3) ? "" : "not ");
63  } else {
64  if (!CONFIG(SET_IA32_FC_LOCK_BIT))
66  "Overriding CONFIG(SET_IA32_FC_LOCK_BIT) to enable SMRR\n");
67  ia32_ft_ctrl.lo |= (1 << 3) | (1 << 0);
68  wrmsr(IA32_FEATURE_CONTROL, ia32_ft_ctrl);
69  }
70  } else {
72  }
73 
74  /* Relocate the SMM handler. */
75  smm_relocate();
76 }
77 
78 static void post_mp_init(void)
79 {
80  /* Now that all APs have been relocated as well as the BSP let SMIs
81  * start flowing. */
83 
84  /* Lock down the SMRAM space. */
85  smm_lock();
86 }
87 
88 static const struct mp_ops mp_ops = {
90  .get_cpu_count = get_cpu_count,
91  .get_smm_info = smm_info,
92  .get_microcode_info = get_microcode_info,
93  .pre_mp_smm_init = pre_mp_smm_init,
94  .per_cpu_smm_trigger = per_cpu_smm_trigger,
95  .relocation_handler = smm_relocation_handler,
96  .post_mp_init = post_mp_init,
97 };
98 
99 void mp_init_cpus(struct bus *cpu_bus)
100 {
101  /* TODO: Handle mp_init_with_smm failure? */
102  mp_init_with_smm(cpu_bus, &mp_ops);
103 }
#define printk(level,...)
Definition: stdlib.h:16
void set_feature_ctrl_vmx(void)
Definition: common_init.c:67
void set_vmx_and_lock(void)
Definition: common_init.c:15
bool intel_ht_supported(void)
Definition: hyperthreading.c:7
void smm_relocate(void)
Definition: smmrelocate.c:247
void smm_relocation_handler(int cpu, uintptr_t curr_smbase, uintptr_t staggered_smbase)
Definition: smmrelocate.c:90
void smm_initialize(void)
Definition: smmrelocate.c:227
void smm_lock(void)
Definition: smmrelocate.c:261
void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size)
Definition: smmrelocate.c:213
static void get_microcode_info(const void **microcode, int *parallel)
Definition: mp_init.c:33
void mp_init_cpus(struct bus *cpu_bus)
Definition: mp_init.c:99
#define SMRR_SUPPORTED
Definition: mp_init.c:46
static void pre_mp_init(void)
Definition: mp_init.c:13
static void per_cpu_smm_trigger(void)
Definition: mp_init.c:48
static void pre_mp_smm_init(void)
Definition: mp_init.c:41
static int get_cpu_count(void)
Definition: mp_init.c:23
static void post_mp_init(void)
Definition: mp_init.c:78
bool cpu_has_alternative_smrr(void)
Definition: smmrelocate.c:31
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
@ CONFIG
Definition: dsi_common.h:201
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_FEATURE_CONTROL
Definition: msr.h:20
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
void global_smi_enable(void)
Set the EOS bit and enable SMI generation from southbridge.
Definition: smi_util.c:60
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
void intel_microcode_load_unlocked(const void *microcode_patch)
Definition: microcode.c:71
const void * intel_microcode_find(void)
Definition: microcode.c:223
u32 cpuid
Definition: device.h:76
uint32_t ebx
Definition: cpu.h:31
Definition: mp.h:20
void(* pre_mp_init)(void)
Definition: mp.h:27
unsigned int lo
Definition: msr.h:111
#define MTRR_CAP_MSR
Definition: mtrr.h:17