blob: 4004726e292efef5a82707f64d8cd6ce6e6684ab [file] [log] [blame]
Felix Heldbc134812021-02-10 02:26:10 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
Arthur Heymanse48dcb72022-05-31 21:48:15 +02003#include <cpu/x86/mtrr.h>
4#include <cpu/x86/mp.h>
5#include <amdblocks/cpu.h>
Felix Heldbc134812021-02-10 02:26:10 +01006#include <amdblocks/smm.h>
7#include <console/console.h>
8#include <cpu/amd/amd64_save_state.h>
Grzegorz Bernackid34dbe52023-04-25 15:30:14 +00009#include <cpu/amd/microcode.h>
Felix Heldbc134812021-02-10 02:26:10 +010010#include <cpu/amd/msr.h>
Arthur Heymanse48dcb72022-05-31 21:48:15 +020011#include <cpu/amd/mtrr.h>
Felix Heldbc134812021-02-10 02:26:10 +010012#include <cpu/cpu.h>
13#include <cpu/x86/msr.h>
14#include <cpu/x86/smm.h>
15#include <types.h>
16
Arthur Heymanse48dcb72022-05-31 21:48:15 +020017/* AP MTRRs will be synced to the BSP in the SIPI vector so set them up before MP init. */
18static void pre_mp_init(void)
19{
20 const msr_t syscfg = rdmsr(SYSCFG_MSR);
21 if (syscfg.lo & SYSCFG_MSR_TOM2WB)
22 x86_setup_mtrrs_with_detect_no_above_4gb();
23 else
24 x86_setup_mtrrs_with_detect();
25 x86_mtrr_check();
Grzegorz Bernackid34dbe52023-04-25 15:30:14 +000026 if (CONFIG(SOC_AMD_COMMON_BLOCK_UCODE))
27 amd_load_microcode_from_cbfs();
Arthur Heymanse48dcb72022-05-31 21:48:15 +020028}
29
30static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
31 size_t *smm_save_state_size)
Felix Heldbc134812021-02-10 02:26:10 +010032{
Arthur Heymans8cd1dfa2022-05-31 22:00:13 +020033 printk(BIOS_DEBUG, "Setting up SMI for CPU\n");
34
Felix Heldbc134812021-02-10 02:26:10 +010035 uintptr_t tseg_base;
36 size_t tseg_size;
37
38 smm_region(&tseg_base, &tseg_size);
39
Arthur Heymans8cd1dfa2022-05-31 22:00:13 +020040 if (!IS_ALIGNED(tseg_base, tseg_size)) {
41 printk(BIOS_ERR, "TSEG base not aligned to TSEG size\n");
42 return;
43 }
44 /* Minimum granularity for TSEG MSRs */
45 if (tseg_size < 128 * KiB) {
46 printk(BIOS_ERR, "TSEG size (0x%zx) too small\n", tseg_size);
47 return;
48 }
Felix Heldbc134812021-02-10 02:26:10 +010049
Felix Heldbc134812021-02-10 02:26:10 +010050
51 smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize);
52 *smm_save_state_size = sizeof(amd64_smm_state_save_area_t);
53}
54
Arthur Heymans43ed5d22022-05-31 21:50:51 +020055static void tseg_valid(void)
56{
57 msr_t mask = rdmsr(SMM_MASK_MSR);
58 mask.lo |= SMM_TSEG_VALID;
59
60 wrmsr(SMM_MASK_MSR, mask);
61}
62
Arthur Heymans56776a12022-05-19 11:31:10 +020063static void smm_relocation_handler(void)
Felix Heldbc134812021-02-10 02:26:10 +010064{
Arthur Heymans8cd1dfa2022-05-31 22:00:13 +020065 uintptr_t tseg_base;
66 size_t tseg_size;
67
68 smm_region(&tseg_base, &tseg_size);
69
70 msr_t msr;
Felix Heldcabf6ea2023-03-09 19:43:18 +010071 msr.raw = tseg_base;
Arthur Heymans8cd1dfa2022-05-31 22:00:13 +020072 wrmsr(SMM_ADDR_MSR, msr);
73
74 msr.lo = ~(tseg_size - 1);
75 msr.lo |= SMM_TSEG_WB;
76 msr.hi = (1 << (cpu_phys_address_size() - 32)) - 1;
77 wrmsr(SMM_MASK_MSR, msr);
Felix Heldbc134812021-02-10 02:26:10 +010078
Arthur Heymans56776a12022-05-19 11:31:10 +020079 uintptr_t smbase = smm_get_cpu_smbase(cpu_index());
80 msr_t smm_base = {
Felix Heldcabf6ea2023-03-09 19:43:18 +010081 .raw = smbase
Arthur Heymans56776a12022-05-19 11:31:10 +020082 };
83 wrmsr(SMM_BASE_MSR, smm_base);
Arthur Heymans43ed5d22022-05-31 21:50:51 +020084
85 tseg_valid();
86 lock_smm();
Felix Heldbc134812021-02-10 02:26:10 +010087}
Arthur Heymanse48dcb72022-05-31 21:48:15 +020088
Grzegorz Bernackid34dbe52023-04-25 15:30:14 +000089static void post_mp_init(void)
90{
91 if (CONFIG(SOC_AMD_COMMON_BLOCK_UCODE))
92 amd_free_microcode();
93 global_smi_enable();
94}
95
Arthur Heymanse48dcb72022-05-31 21:48:15 +020096const struct mp_ops amd_mp_ops_with_smm = {
97 .pre_mp_init = pre_mp_init,
98 .get_cpu_count = get_cpu_count,
99 .get_smm_info = get_smm_info,
Arthur Heymans56776a12022-05-19 11:31:10 +0200100 .per_cpu_smm_trigger = smm_relocation_handler,
Grzegorz Bernackid34dbe52023-04-25 15:30:14 +0000101 .post_mp_init = post_mp_init,
Arthur Heymanse48dcb72022-05-31 21:48:15 +0200102};
Arthur Heymans4fcaccf2022-06-02 13:17:37 +0200103
104const struct mp_ops amd_mp_ops_no_smm = {
105 .pre_mp_init = pre_mp_init,
106 .get_cpu_count = get_cpu_count,
107};