1 | /** @file
|
---|
2 | Config SMRAM Save State for SmmBases Relocation.
|
---|
3 |
|
---|
4 | Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
---|
5 | Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 | #include "InternalSmmRelocationLib.h"
|
---|
10 | #include <Register/Amd/SmramSaveStateMap.h>
|
---|
11 |
|
---|
12 | /**
|
---|
13 | Get the mode of the CPU at the time an SMI occurs
|
---|
14 |
|
---|
15 | @retval EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT 32 bit.
|
---|
16 | @retval EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT 64 bit.
|
---|
17 |
|
---|
18 | **/
|
---|
19 | UINT8
|
---|
20 | GetMmSaveStateRegisterLma (
|
---|
21 | VOID
|
---|
22 | )
|
---|
23 | {
|
---|
24 | UINT8 SmmSaveStateRegisterLma;
|
---|
25 | MSR_IA32_EFER_REGISTER Msr;
|
---|
26 |
|
---|
27 | Msr.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
|
---|
28 |
|
---|
29 | SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
|
---|
30 |
|
---|
31 | if (Msr.Bits.LMA) {
|
---|
32 | SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
|
---|
33 | }
|
---|
34 |
|
---|
35 | return SmmSaveStateRegisterLma;
|
---|
36 | }
|
---|
37 |
|
---|
38 | /**
|
---|
39 | This function configures the SmBase on the currently executing CPU.
|
---|
40 |
|
---|
41 | @param[in] SmBase The SmBase on the currently executing CPU.
|
---|
42 |
|
---|
43 | **/
|
---|
44 | VOID
|
---|
45 | EFIAPI
|
---|
46 | ConfigureSmBase (
|
---|
47 | IN UINT64 SmBase
|
---|
48 | )
|
---|
49 | {
|
---|
50 | AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
|
---|
51 |
|
---|
52 | AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
---|
53 |
|
---|
54 | AmdCpuState->x64.SMBASE = (UINT32)SmBase;
|
---|
55 | }
|
---|
56 |
|
---|
57 | /**
|
---|
58 | This function updates the SMRAM save state on the currently executing CPU
|
---|
59 | to resume execution at a specific address after an RSM instruction. This
|
---|
60 | function must evaluate the SMRAM save state to determine the execution mode
|
---|
61 | the RSM instruction resumes and update the resume execution address with
|
---|
62 | either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
---|
63 | flag in the SMRAM save state must always be cleared. This function returns
|
---|
64 | the value of the instruction pointer from the SMRAM save state that was
|
---|
65 | replaced. If this function returns 0, then the SMRAM save state was not
|
---|
66 | modified.
|
---|
67 |
|
---|
68 | This function is called during the very first SMI on each CPU after
|
---|
69 | SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
---|
70 | to signal that the SMBASE of each CPU has been updated before the default
|
---|
71 | SMBASE address is used for the first SMI to the next CPU.
|
---|
72 |
|
---|
73 | @param[in,out] CpuState Pointer to SMRAM Save State Map for the
|
---|
74 | currently executing CPU.
|
---|
75 | @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
|
---|
76 | 32-bit mode from 64-bit SMM.
|
---|
77 | @param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
---|
78 | same mode as SMM.
|
---|
79 |
|
---|
80 | @retval The value of the original instruction pointer before it was hooked.
|
---|
81 |
|
---|
82 | **/
|
---|
83 | UINT64
|
---|
84 | EFIAPI
|
---|
85 | HookReturnFromSmm (
|
---|
86 | IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
|
---|
87 | IN UINT64 NewInstructionPointer32,
|
---|
88 | IN UINT64 NewInstructionPointer
|
---|
89 | )
|
---|
90 | {
|
---|
91 | UINT64 OriginalInstructionPointer;
|
---|
92 | AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
|
---|
93 | MSR_IA32_EFER_REGISTER Msr;
|
---|
94 |
|
---|
95 | AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
|
---|
96 |
|
---|
97 | OriginalInstructionPointer = AmdCpuState->x64._RIP;
|
---|
98 | Msr.Uint64 = AmdCpuState->x64.EFER;
|
---|
99 |
|
---|
100 | if (!Msr.Bits.LMA) {
|
---|
101 | AmdCpuState->x64._RIP = NewInstructionPointer32;
|
---|
102 | } else {
|
---|
103 | AmdCpuState->x64._RIP = NewInstructionPointer;
|
---|
104 | }
|
---|
105 |
|
---|
106 | //
|
---|
107 | // Clear the auto HALT restart flag so the RSM instruction returns
|
---|
108 | // program control to the instruction following the HLT instruction.
|
---|
109 | //
|
---|
110 | if ((AmdCpuState->x64.AutoHALTRestart & BIT0) != 0) {
|
---|
111 | AmdCpuState->x64.AutoHALTRestart &= ~BIT0;
|
---|
112 | }
|
---|
113 |
|
---|
114 | return OriginalInstructionPointer;
|
---|
115 | }
|
---|