| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #ifndef __INTEL_SMM_RELOC_H__ |
| #define __INTEL_SMM_RELOC_H__ |
| |
| #include <console/console.h> |
| #include <types.h> |
| #include <cpu/x86/msr.h> |
| #include <cpu/x86/mtrr.h> |
| |
| struct smm_relocation_params { |
| uintptr_t ied_base; |
| size_t ied_size; |
| msr_t smrr_base; |
| msr_t smrr_mask; |
| msr_t prmrr_base; |
| msr_t prmrr_mask; |
| msr_t uncore_prmrr_base; |
| msr_t uncore_prmrr_mask; |
| /* |
| * The smm_save_state_in_msrs field indicates if SMM save state |
| * locations live in MSRs. This indicates to the CPUs how to adjust |
| * the SMMBASE and IEDBASE |
| */ |
| int smm_save_state_in_msrs; |
| }; |
| |
| extern struct smm_relocation_params smm_reloc_params; |
| |
| struct ied_header { |
| char signature[10]; |
| u32 size; |
| u8 reserved[34]; |
| } __packed; |
| |
| /* These helpers are for performing SMM relocation. */ |
| void northbridge_write_smram(u8 smram); |
| |
| void smm_open_aseg(void); |
| void smm_lock(void); |
| void smm_relocate(void); |
| |
| /* The initialization of the southbridge is split into 2 components. One is |
| * for clearing the state in the SMM registers. The other is for enabling |
| * SMIs. They are split so that other work between the 2 actions. */ |
| void smm_southbridge_clear_state(void); |
| |
| /* To be removed. */ |
| void smm_initialize(void); |
| void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size); |
| void smm_relocation_handler(int cpu, uintptr_t curr_smbase, uintptr_t staggered_smbase); |
| |
| bool cpu_has_alternative_smrr(void); |
| |
| #define MSR_PRMRR_PHYS_BASE 0x1f4 |
| #define MSR_PRMRR_PHYS_MASK 0x1f5 |
| #define MSR_UNCORE_PRMRR_PHYS_BASE 0x2f4 |
| #define MSR_UNCORE_PRMRR_PHYS_MASK 0x2f5 |
| |
| static inline void write_smrr(struct smm_relocation_params *relo_params) |
| { |
| printk(BIOS_DEBUG, "Writing SMRR. base = 0x%08x, mask=0x%08x\n", |
| relo_params->smrr_base.lo, relo_params->smrr_mask.lo); |
| wrmsr(IA32_SMRR_PHYS_BASE, relo_params->smrr_base); |
| wrmsr(IA32_SMRR_PHYS_MASK, relo_params->smrr_mask); |
| } |
| |
| static inline void write_prmrr(struct smm_relocation_params *relo_params) |
| { |
| printk(BIOS_DEBUG, "Writing PRMRR. base = 0x%08x, mask=0x%08x\n", |
| relo_params->prmrr_base.lo, relo_params->prmrr_mask.lo); |
| wrmsr(MSR_PRMRR_PHYS_BASE, relo_params->prmrr_base); |
| wrmsr(MSR_PRMRR_PHYS_MASK, relo_params->prmrr_mask); |
| } |
| |
| static inline void write_uncore_prmrr(struct smm_relocation_params *relo_params) |
| { |
| printk(BIOS_DEBUG, |
| "Writing UNCORE_PRMRR. base = 0x%08x, mask=0x%08x\n", |
| relo_params->uncore_prmrr_base.lo, |
| relo_params->uncore_prmrr_mask.lo); |
| wrmsr(MSR_UNCORE_PRMRR_PHYS_BASE, relo_params->uncore_prmrr_base); |
| wrmsr(MSR_UNCORE_PRMRR_PHYS_MASK, relo_params->uncore_prmrr_mask); |
| } |
| |
| #endif |