VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 14 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1/** @file
2Provides services to access SMRAM Save State Map
3
4Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
5Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
6
7SPDX-License-Identifier: BSD-2-Clause-Patent
8
9**/
10
11#include <PiSmm.h>
12
13#include <Library/SmmCpuFeaturesLib.h>
14
15#include <Library/BaseLib.h>
16#include <Library/BaseMemoryLib.h>
17#include <Library/SmmServicesTableLib.h>
18#include <Library/DebugLib.h>
19
20#include "PiSmmCpuDxeSmm.h"
21
22typedef struct {
23 UINT64 Signature; // Offset 0x00
24 UINT16 Reserved1; // Offset 0x08
25 UINT16 Reserved2; // Offset 0x0A
26 UINT16 Reserved3; // Offset 0x0C
27 UINT16 SmmCs; // Offset 0x0E
28 UINT16 SmmDs; // Offset 0x10
29 UINT16 SmmSs; // Offset 0x12
30 UINT16 SmmOtherSegment; // Offset 0x14
31 UINT16 Reserved4; // Offset 0x16
32 UINT64 Reserved5; // Offset 0x18
33 UINT64 Reserved6; // Offset 0x20
34 UINT64 Reserved7; // Offset 0x28
35 UINT64 SmmGdtPtr; // Offset 0x30
36 UINT32 SmmGdtSize; // Offset 0x38
37 UINT32 Reserved8; // Offset 0x3C
38 UINT64 Reserved9; // Offset 0x40
39 UINT64 Reserved10; // Offset 0x48
40 UINT16 Reserved11; // Offset 0x50
41 UINT16 Reserved12; // Offset 0x52
42 UINT32 Reserved13; // Offset 0x54
43 UINT64 Reserved14; // Offset 0x58
44} PROCESSOR_SMM_DESCRIPTOR;
45
46extern CONST PROCESSOR_SMM_DESCRIPTOR gcPsd;
47
48//
49// EFER register LMA bit
50//
51#define LMA BIT10
52
53///
54/// Variables from SMI Handler
55///
56X86_ASSEMBLY_PATCH_LABEL gPatchSmbase;
57X86_ASSEMBLY_PATCH_LABEL gPatchSmiStack;
58X86_ASSEMBLY_PATCH_LABEL gPatchSmiCr3;
59extern volatile UINT8 gcSmiHandlerTemplate[];
60extern CONST UINT16 gcSmiHandlerSize;
61
62//
63// Variables used by SMI Handler
64//
65IA32_DESCRIPTOR gSmiHandlerIdtr;
66
67///
68/// The mode of the CPU at the time an SMI occurs
69///
70UINT8 mSmmSaveStateRegisterLma;
71
72/**
73 Hook the code executed immediately after an RSM instruction on the currently
74 executing CPU. The mode of code executed immediately after RSM must be
75 detected, and the appropriate hook must be selected. Always clear the auto
76 HALT restart flag if it is set.
77
78 @param[in] CpuIndex The processor index for the currently
79 executing CPU.
80 @param[in] CpuState Pointer to SMRAM Save State Map for the
81 currently executing CPU.
82 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
83 32-bit mode from 64-bit SMM.
84 @param[in] NewInstructionPointer Instruction pointer to use if resuming to
85 same mode as SMM.
86
87 @retval The value of the original instruction pointer before it was hooked.
88
89**/
90UINT64
91EFIAPI
92HookReturnFromSmm (
93 IN UINTN CpuIndex,
94 SMRAM_SAVE_STATE_MAP *CpuState,
95 UINT64 NewInstructionPointer32,
96 UINT64 NewInstructionPointer
97 )
98{
99 UINT64 OriginalInstructionPointer;
100
101 OriginalInstructionPointer = SmmCpuFeaturesHookReturnFromSmm (
102 CpuIndex,
103 CpuState,
104 NewInstructionPointer32,
105 NewInstructionPointer
106 );
107 if (OriginalInstructionPointer != 0) {
108 return OriginalInstructionPointer;
109 }
110
111 if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
112 OriginalInstructionPointer = (UINT64)CpuState->x86._EIP;
113 CpuState->x86._EIP = (UINT32)NewInstructionPointer;
114 //
115 // Clear the auto HALT restart flag so the RSM instruction returns
116 // program control to the instruction following the HLT instruction.
117 //
118 if ((CpuState->x86.AutoHALTRestart & BIT0) != 0) {
119 CpuState->x86.AutoHALTRestart &= ~BIT0;
120 }
121 } else {
122 OriginalInstructionPointer = CpuState->x64._RIP;
123 if ((CpuState->x64.IA32_EFER & LMA) == 0) {
124 CpuState->x64._RIP = (UINT32)NewInstructionPointer32;
125 } else {
126 CpuState->x64._RIP = (UINT32)NewInstructionPointer;
127 }
128
129 //
130 // Clear the auto HALT restart flag so the RSM instruction returns
131 // program control to the instruction following the HLT instruction.
132 //
133 if ((CpuState->x64.AutoHALTRestart & BIT0) != 0) {
134 CpuState->x64.AutoHALTRestart &= ~BIT0;
135 }
136 }
137
138 return OriginalInstructionPointer;
139}
140
141/**
142 Get the size of the SMI Handler in bytes.
143
144 @retval The size, in bytes, of the SMI Handler.
145
146**/
147UINTN
148EFIAPI
149GetSmiHandlerSize (
150 VOID
151 )
152{
153 UINTN Size;
154
155 Size = SmmCpuFeaturesGetSmiHandlerSize ();
156 if (Size != 0) {
157 return Size;
158 }
159
160 return gcSmiHandlerSize;
161}
162
163/**
164 Install the SMI handler for the CPU specified by CpuIndex. This function
165 is called by the CPU that was elected as monarch during System Management
166 Mode initialization.
167
168 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
169 The value must be between 0 and the NumberOfCpus field
170 in the System Management System Table (SMST).
171 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
172 @param[in] SmiStack The stack to use when an SMI is processed by the
173 the CPU specified by CpuIndex.
174 @param[in] StackSize The size, in bytes, if the stack used when an SMI is
175 processed by the CPU specified by CpuIndex.
176 @param[in] GdtBase The base address of the GDT to use when an SMI is
177 processed by the CPU specified by CpuIndex.
178 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
179 processed by the CPU specified by CpuIndex.
180 @param[in] IdtBase The base address of the IDT to use when an SMI is
181 processed by the CPU specified by CpuIndex.
182 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
183 processed by the CPU specified by CpuIndex.
184 @param[in] Cr3 The base address of the page tables to use when an SMI
185 is processed by the CPU specified by CpuIndex.
186**/
187VOID
188EFIAPI
189InstallSmiHandler (
190 IN UINTN CpuIndex,
191 IN UINT32 SmBase,
192 IN VOID *SmiStack,
193 IN UINTN StackSize,
194 IN UINTN GdtBase,
195 IN UINTN GdtSize,
196 IN UINTN IdtBase,
197 IN UINTN IdtSize,
198 IN UINT32 Cr3
199 )
200{
201 PROCESSOR_SMM_DESCRIPTOR *Psd;
202 UINT32 CpuSmiStack;
203
204 //
205 // Initialize PROCESSOR_SMM_DESCRIPTOR
206 //
207 Psd = (PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + SMM_PSD_OFFSET);
208 CopyMem (Psd, &gcPsd, sizeof (gcPsd));
209 Psd->SmmGdtPtr = (UINT64)GdtBase;
210 Psd->SmmGdtSize = (UINT32)GdtSize;
211
212 if (SmmCpuFeaturesGetSmiHandlerSize () != 0) {
213 //
214 // Install SMI handler provided by library
215 //
216 SmmCpuFeaturesInstallSmiHandler (
217 CpuIndex,
218 SmBase,
219 SmiStack,
220 StackSize,
221 GdtBase,
222 GdtSize,
223 IdtBase,
224 IdtSize,
225 Cr3
226 );
227 return;
228 }
229
230 InitShadowStack (CpuIndex, (VOID *)((UINTN)SmiStack + StackSize));
231
232 //
233 // Initialize values in template before copy
234 //
235 CpuSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
236 PatchInstructionX86 (gPatchSmiStack, CpuSmiStack, 4);
237 PatchInstructionX86 (gPatchSmiCr3, Cr3, 4);
238 PatchInstructionX86 (gPatchSmbase, SmBase, 4);
239 gSmiHandlerIdtr.Base = IdtBase;
240 gSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
241
242 //
243 // Set the value at the top of the CPU stack to the CPU Index
244 //
245 *(UINTN *)(UINTN)CpuSmiStack = CpuIndex;
246
247 //
248 // Copy template to CPU specific SMI handler location
249 //
250 CopyMem (
251 (VOID *)((UINTN)SmBase + SMM_HANDLER_OFFSET),
252 (VOID *)gcSmiHandlerTemplate,
253 gcSmiHandlerSize
254 );
255}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette