VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.c

Last change on this file was 101291, checked in by vboxsync, 12 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: 13.5 KB
Line 
1/** @file
2Implementation specific to the SmmCpuFeatureLib library instance
3for AMD based platforms.
4
5Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
6Copyright (c) Microsoft Corporation.<BR>
7Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
8SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <Library/SmmCpuFeaturesLib.h>
13#include <Uefi/UefiBaseType.h>
14#include <Register/Amd/SmramSaveStateMap.h>
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/MmSaveStateLib.h>
18
19// EFER register LMA bit
20#define LMA BIT10
21
22// Machine Specific Registers (MSRs)
23#define SMMADDR_ADDRESS 0xC0010112ul
24#define SMMMASK_ADDRESS 0xC0010113ul
25#define EFER_ADDRESS 0XC0000080ul
26
27// The mode of the CPU at the time an SMI occurs
28STATIC UINT8 mSmmSaveStateRegisterLma;
29
30/**
31 Performs library initialization.
32
33 This initialization function contains common functionality shared betwen all
34 library instance constructors.
35
36**/
37VOID
38CpuFeaturesLibInitialization (
39 VOID
40 )
41{
42 UINT32 LMAValue;
43
44 LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
45 mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
46 if (LMAValue) {
47 mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
48 }
49}
50
51/**
52 Called during the very first SMI into System Management Mode to initialize
53 CPU features, including SMBASE, for the currently executing CPU. Since this
54 is the first SMI, the SMRAM Save State Map is at the default address of
55 AMD_SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
56 CPU is specified by CpuIndex and CpuIndex can be used to access information
57 about the currently executing CPU in the ProcessorInfo array and the
58 HotPlugCpuData data structure.
59
60 @param[in] CpuIndex The index of the CPU to initialize. The value
61 must be between 0 and the NumberOfCpus field in
62 the System Management System Table (SMST).
63 @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
64 was elected as monarch during System Management
65 Mode initialization.
66 FALSE if the CpuIndex is not the index of the CPU
67 that was elected as monarch during System
68 Management Mode initialization.
69 @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
70 structures. ProcessorInfo[CpuIndex] contains the
71 information for the currently executing CPU.
72 @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
73 contains the ApidId and SmBase arrays.
74**/
75VOID
76EFIAPI
77SmmCpuFeaturesInitializeProcessor (
78 IN UINTN CpuIndex,
79 IN BOOLEAN IsMonarch,
80 IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
81 IN CPU_HOT_PLUG_DATA *CpuHotPlugData
82 )
83{
84 AMD_SMRAM_SAVE_STATE_MAP *CpuState;
85 UINT32 LMAValue;
86
87 //
88 // Configure SMBASE.
89 //
90 CpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
91 CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
92
93 // Re-initialize the value of mSmmSaveStateRegisterLma flag which might have been changed in PiCpuSmmDxeSmm Driver
94 // Entry point, to make sure correct value on AMD platform is assigned to be used by SmmCpuFeaturesLib.
95 LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
96 mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
97 if (LMAValue) {
98 mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
99 }
100
101 //
102 // If SMRR is supported, then program SMRR base/mask MSRs.
103 // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
104 // The code that initializes SMM environment is running in normal mode
105 // from SMRAM region. If SMRR is enabled here, then the SMRAM region
106 // is protected and the normal mode code execution will fail.
107 //
108 if (FeaturePcdGet (PcdSmrrEnable)) {
109 //
110 // SMRR size cannot be less than 4-KBytes
111 // SMRR size must be of length 2^n
112 // SMRR base alignment cannot be less than SMRR length
113 //
114 if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||
115 (CpuHotPlugData->SmrrSize != GetPowerOfTwo32 (CpuHotPlugData->SmrrSize)) ||
116 ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) != CpuHotPlugData->SmrrBase))
117 {
118 //
119 // Print message and halt if CPU is Monarch
120 //
121 if (IsMonarch) {
122 DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size requirement!\n"));
123 CpuDeadLoop ();
124 }
125 } else {
126 AsmWriteMsr64 (SMMADDR_ADDRESS, CpuHotPlugData->SmrrBase);
127 AsmWriteMsr64 (SMMMASK_ADDRESS, ((~(UINT64)(CpuHotPlugData->SmrrSize - 1)) | 0x6600));
128 }
129 }
130}
131
132/**
133 This function updates the SMRAM save state on the currently executing CPU
134 to resume execution at a specific address after an RSM instruction. This
135 function must evaluate the SMRAM save state to determine the execution mode
136 the RSM instruction resumes and update the resume execution address with
137 either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
138 flag in the SMRAM save state must always be cleared. This function returns
139 the value of the instruction pointer from the SMRAM save state that was
140 replaced. If this function returns 0, then the SMRAM save state was not
141 modified.
142
143 This function is called during the very first SMI on each CPU after
144 SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
145 to signal that the SMBASE of each CPU has been updated before the default
146 SMBASE address is used for the first SMI to the next CPU.
147
148 @param[in] CpuIndex The index of the CPU to hook. The value
149 must be between 0 and the NumberOfCpus
150 field in the System Management System Table
151 (SMST).
152 @param[in] CpuState Pointer to SMRAM Save State Map for the
153 currently executing CPU.
154 @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
155 32-bit execution mode from 64-bit SMM.
156 @param[in] NewInstructionPointer Instruction pointer to use if resuming to
157 same execution mode as SMM.
158
159 @retval 0 This function did modify the SMRAM save state.
160 @retval > 0 The original instruction pointer value from the SMRAM save state
161 before it was replaced.
162**/
163UINT64
164EFIAPI
165SmmCpuFeaturesHookReturnFromSmm (
166 IN UINTN CpuIndex,
167 IN SMRAM_SAVE_STATE_MAP *CpuState,
168 IN UINT64 NewInstructionPointer32,
169 IN UINT64 NewInstructionPointer
170 )
171{
172 UINT64 OriginalInstructionPointer;
173 AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
174
175 AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
176
177 if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
178 OriginalInstructionPointer = (UINT64)AmdCpuState->x86._EIP;
179 AmdCpuState->x86._EIP = (UINT32)NewInstructionPointer;
180 //
181 // Clear the auto HALT restart flag so the RSM instruction returns
182 // program control to the instruction following the HLT instruction.
183 //
184 if ((AmdCpuState->x86.AutoHALTRestart & BIT0) != 0) {
185 AmdCpuState->x86.AutoHALTRestart &= ~BIT0;
186 }
187 } else {
188 OriginalInstructionPointer = AmdCpuState->x64._RIP;
189 if ((AmdCpuState->x64.EFER & LMA) == 0) {
190 AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer32;
191 } else {
192 AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer;
193 }
194
195 //
196 // Clear the auto HALT restart flag so the RSM instruction returns
197 // program control to the instruction following the HLT instruction.
198 //
199 if ((AmdCpuState->x64.AutoHALTRestart & BIT0) != 0) {
200 AmdCpuState->x64.AutoHALTRestart &= ~BIT0;
201 }
202 }
203
204 return OriginalInstructionPointer;
205}
206
207/**
208 Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
209 returned, then a custom SMI handler is not provided by this library,
210 and the default SMI handler must be used.
211
212 @retval 0 Use the default SMI handler.
213 @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
214 The caller is required to allocate enough SMRAM for each CPU to
215 support the size of the custom SMI handler.
216**/
217UINTN
218EFIAPI
219SmmCpuFeaturesGetSmiHandlerSize (
220 VOID
221 )
222{
223 return 0;
224}
225
226/**
227 Install a custom SMI handler for the CPU specified by CpuIndex. This function
228 is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
229 than zero and is called by the CPU that was elected as monarch during System
230 Management Mode initialization.
231
232 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
233 The value must be between 0 and the NumberOfCpus field
234 in the System Management System Table (SMST).
235 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
236 @param[in] SmiStack The stack to use when an SMI is processed by the
237 the CPU specified by CpuIndex.
238 @param[in] StackSize The size, in bytes, if the stack used when an SMI is
239 processed by the CPU specified by CpuIndex.
240 @param[in] GdtBase The base address of the GDT to use when an SMI is
241 processed by the CPU specified by CpuIndex.
242 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
243 processed by the CPU specified by CpuIndex.
244 @param[in] IdtBase The base address of the IDT to use when an SMI is
245 processed by the CPU specified by CpuIndex.
246 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
247 processed by the CPU specified by CpuIndex.
248 @param[in] Cr3 The base address of the page tables to use when an SMI
249 is processed by the CPU specified by CpuIndex.
250**/
251VOID
252EFIAPI
253SmmCpuFeaturesInstallSmiHandler (
254 IN UINTN CpuIndex,
255 IN UINT32 SmBase,
256 IN VOID *SmiStack,
257 IN UINTN StackSize,
258 IN UINTN GdtBase,
259 IN UINTN GdtSize,
260 IN UINTN IdtBase,
261 IN UINTN IdtSize,
262 IN UINT32 Cr3
263 )
264{
265}
266
267/**
268 Determines if MTRR registers must be configured to set SMRAM cache-ability
269 when executing in System Management Mode.
270
271 @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
272 @retval FALSE MTRR registers do not need to be configured to set SMRAM
273 cache-ability.
274**/
275BOOLEAN
276EFIAPI
277SmmCpuFeaturesNeedConfigureMtrrs (
278 VOID
279 )
280{
281 return FALSE;
282}
283
284/**
285 Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
286 returns TRUE.
287**/
288VOID
289EFIAPI
290SmmCpuFeaturesDisableSmrr (
291 VOID
292 )
293{
294}
295
296/**
297 Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
298 returns TRUE.
299**/
300VOID
301EFIAPI
302SmmCpuFeaturesReenableSmrr (
303 VOID
304 )
305{
306}
307
308/**
309 Processor specific hook point each time a CPU enters System Management Mode.
310
311 @param[in] CpuIndex The index of the CPU that has entered SMM. The value
312 must be between 0 and the NumberOfCpus field in the
313 System Management System Table (SMST).
314**/
315VOID
316EFIAPI
317SmmCpuFeaturesRendezvousEntry (
318 IN UINTN CpuIndex
319 )
320{
321}
322
323/**
324 Returns the current value of the SMM register for the specified CPU.
325 If the SMM register is not supported, then 0 is returned.
326
327 @param[in] CpuIndex The index of the CPU to read the SMM register. The
328 value must be between 0 and the NumberOfCpus field in
329 the System Management System Table (SMST).
330 @param[in] RegName Identifies the SMM register to read.
331
332 @return The value of the SMM register specified by RegName from the CPU
333 specified by CpuIndex.
334**/
335UINT64
336EFIAPI
337SmmCpuFeaturesGetSmmRegister (
338 IN UINTN CpuIndex,
339 IN SMM_REG_NAME RegName
340 )
341{
342 return 0;
343}
344
345/**
346 Sets the value of an SMM register on a specified CPU.
347 If the SMM register is not supported, then no action is performed.
348
349 @param[in] CpuIndex The index of the CPU to write the SMM register. The
350 value must be between 0 and the NumberOfCpus field in
351 the System Management System Table (SMST).
352 @param[in] RegName Identifies the SMM register to write.
353 registers are read-only.
354 @param[in] Value The value to write to the SMM register.
355**/
356VOID
357EFIAPI
358SmmCpuFeaturesSetSmmRegister (
359 IN UINTN CpuIndex,
360 IN SMM_REG_NAME RegName,
361 IN UINT64 Value
362 )
363{
364}
365
366/**
367 Check to see if an SMM register is supported by a specified CPU.
368
369 @param[in] CpuIndex The index of the CPU to check for SMM register support.
370 The value must be between 0 and the NumberOfCpus field
371 in the System Management System Table (SMST).
372 @param[in] RegName Identifies the SMM register to check for support.
373
374 @retval TRUE The SMM register specified by RegName is supported by the CPU
375 specified by CpuIndex.
376 @retval FALSE The SMM register specified by RegName is not supported by the
377 CPU specified by CpuIndex.
378**/
379BOOLEAN
380EFIAPI
381SmmCpuFeaturesIsSmmRegisterSupported (
382 IN UINTN CpuIndex,
383 IN SMM_REG_NAME RegName
384 )
385{
386 return FALSE;
387}
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