1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef __INTEL_SMM_RELOC_H__
4 #define __INTEL_SMM_RELOC_H__
5
6 #include <console/console.h>
7 #include <types.h>
8 #include <cpu/x86/msr.h>
9 #include <cpu/x86/mtrr.h>
10
11 struct smm_relocation_params {
12 uintptr_t ied_base;
13 size_t ied_size;
14 msr_t smrr_base;
15 msr_t smrr_mask;
16 msr_t prmrr_base;
17 msr_t prmrr_mask;
18 msr_t uncore_prmrr_base;
19 msr_t uncore_prmrr_mask;
20 /*
21 * The smm_save_state_in_msrs field indicates if SMM save state
22 * locations live in MSRs. This indicates to the CPUs how to adjust
23 * the SMMBASE and IEDBASE
24 */
25 int smm_save_state_in_msrs;
26 };
27
28 extern struct smm_relocation_params smm_reloc_params;
29
30 struct ied_header {
31 char signature[10];
32 u32 size;
33 u8 reserved[34];
34 } __packed;
35
36 /* These helpers are for performing SMM relocation. */
37 void northbridge_write_smram(u8 smram);
38
39 void smm_close(void);
40 void smm_open(void);
41 void smm_lock(void);
42 void smm_relocate(void);
43
44 /* The initialization of the southbridge is split into 2 components. One is
45 * for clearing the state in the SMM registers. The other is for enabling
46 * SMIs. They are split so that other work between the 2 actions. */
47 void smm_southbridge_clear_state(void);
48
49 /* To be removed. */
50 void smm_initialize(void);
51 void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size);
52 void smm_relocation_handler(int cpu, uintptr_t curr_smbase, uintptr_t staggered_smbase);
53
54 bool cpu_has_alternative_smrr(void);
55
56 #define MSR_PRMRR_PHYS_BASE 0x1f4
57 #define MSR_PRMRR_PHYS_MASK 0x1f5
58 #define MSR_UNCORE_PRMRR_PHYS_BASE 0x2f4
59 #define MSR_UNCORE_PRMRR_PHYS_MASK 0x2f5
60
write_smrr(struct smm_relocation_params * relo_params)61 static inline void write_smrr(struct smm_relocation_params *relo_params)
62 {
63 printk(BIOS_DEBUG, "Writing SMRR. base = 0x%08x, mask=0x%08x\n",
64 relo_params->smrr_base.lo, relo_params->smrr_mask.lo);
65 wrmsr(IA32_SMRR_PHYS_BASE, relo_params->smrr_base);
66 wrmsr(IA32_SMRR_PHYS_MASK, relo_params->smrr_mask);
67 }
68
write_prmrr(struct smm_relocation_params * relo_params)69 static inline void write_prmrr(struct smm_relocation_params *relo_params)
70 {
71 printk(BIOS_DEBUG, "Writing PRMRR. base = 0x%08x, mask=0x%08x\n",
72 relo_params->prmrr_base.lo, relo_params->prmrr_mask.lo);
73 wrmsr(MSR_PRMRR_PHYS_BASE, relo_params->prmrr_base);
74 wrmsr(MSR_PRMRR_PHYS_MASK, relo_params->prmrr_mask);
75 }
76
write_uncore_prmrr(struct smm_relocation_params * relo_params)77 static inline void write_uncore_prmrr(struct smm_relocation_params *relo_params)
78 {
79 printk(BIOS_DEBUG,
80 "Writing UNCORE_PRMRR. base = 0x%08x, mask=0x%08x\n",
81 relo_params->uncore_prmrr_base.lo,
82 relo_params->uncore_prmrr_mask.lo);
83 wrmsr(MSR_UNCORE_PRMRR_PHYS_BASE, relo_params->uncore_prmrr_base);
84 wrmsr(MSR_UNCORE_PRMRR_PHYS_MASK, relo_params->uncore_prmrr_mask);
85 }
86
87 #endif
88