VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c@ 95013

最後變更 在這個檔案從95013是 89983,由 vboxsync 提交於 4 年 前

Devices/EFI: Merge edk-stable202105 and openssl 1.1.1j and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 8.1 KB
 
1/** @file
2ACPI CPU Data initialization module
3
4This module initializes the ACPI_CPU_DATA structure and registers the address
5of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple
6version of this module. It does not provide a machine check handler or CPU
7register initialization tables for ACPI S3 resume. It also only supports the
8number of CPUs reported by the MP Services Protocol, so this module does not
9support hot plug CPUs. This module can be copied into a CPU specific package
10and customized if these additional features are required.
11
12Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
13Copyright (c) 2015, Red Hat, Inc.
14
15SPDX-License-Identifier: BSD-2-Clause-Patent
16
17**/
18
19#include <PiDxe.h>
20
21#include <AcpiCpuData.h>
22
23#include <Library/BaseLib.h>
24#include <Library/BaseMemoryLib.h>
25#include <Library/UefiBootServicesTableLib.h>
26#include <Library/DebugLib.h>
27#include <Library/MtrrLib.h>
28#include <Library/MemoryAllocationLib.h>
29
30#include <Protocol/MpService.h>
31#include <Guid/EventGroup.h>
32
33//
34// Data structure used to allocate ACPI_CPU_DATA and its supporting structures
35//
36typedef struct {
37 ACPI_CPU_DATA AcpiCpuData;
38 MTRR_SETTINGS MtrrTable;
39 IA32_DESCRIPTOR GdtrProfile;
40 IA32_DESCRIPTOR IdtrProfile;
41} ACPI_CPU_DATA_EX;
42
43/**
44 Allocate EfiACPIMemoryNVS memory.
45
46 @param[in] Size Size of memory to allocate.
47
48 @return Allocated address for output.
49
50**/
51VOID *
52AllocateAcpiNvsMemory (
53 IN UINTN Size
54 )
55{
56 EFI_PHYSICAL_ADDRESS Address;
57 EFI_STATUS Status;
58 VOID *Buffer;
59
60 Status = gBS->AllocatePages (
61 AllocateAnyPages,
62 EfiACPIMemoryNVS,
63 EFI_SIZE_TO_PAGES (Size),
64 &Address
65 );
66 if (EFI_ERROR (Status)) {
67 return NULL;
68 }
69
70 Buffer = (VOID *)(UINTN)Address;
71 ZeroMem (Buffer, Size);
72
73 return Buffer;
74}
75
76/**
77 Allocate memory and clean it with zero.
78
79 @param[in] Size Size of memory to allocate.
80
81 @return Allocated address for output.
82
83**/
84VOID *
85AllocateZeroPages (
86 IN UINTN Size
87 )
88{
89 VOID *Buffer;
90
91 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (Size));
92 if (Buffer != NULL) {
93 ZeroMem (Buffer, Size);
94 }
95
96 return Buffer;
97}
98/**
99 Callback function executed when the EndOfDxe event group is signaled.
100
101 We delay allocating StartupVector and saving the MTRR settings until BDS signals EndOfDxe.
102
103 @param[in] Event Event whose notification function is being invoked.
104 @param[out] Context Pointer to the MTRR_SETTINGS buffer to fill in.
105**/
106VOID
107EFIAPI
108CpuS3DataOnEndOfDxe (
109 IN EFI_EVENT Event,
110 OUT VOID *Context
111 )
112{
113 EFI_STATUS Status;
114 ACPI_CPU_DATA_EX *AcpiCpuDataEx;
115
116 AcpiCpuDataEx = (ACPI_CPU_DATA_EX *) Context;
117 //
118 // Allocate a 4KB reserved page below 1MB
119 //
120 AcpiCpuDataEx->AcpiCpuData.StartupVector = BASE_1MB - 1;
121 Status = gBS->AllocatePages (
122 AllocateMaxAddress,
123 EfiReservedMemoryType,
124 1,
125 &AcpiCpuDataEx->AcpiCpuData.StartupVector
126 );
127 ASSERT_EFI_ERROR (Status);
128
129 DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));
130 MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
131
132 //
133 // Close event, so it will not be invoked again.
134 //
135 gBS->CloseEvent (Event);
136}
137
138/**
139 The entry function of the CpuS3Data driver.
140
141 Allocate and initialize all fields of the ACPI_CPU_DATA structure except the
142 MTRR settings. Register an event notification on gEfiEndOfDxeEventGroupGuid
143 to capture the ACPI_CPU_DATA MTRR settings. The PcdCpuS3DataAddress is set
144 to the address that ACPI_CPU_DATA is allocated at.
145
146 @param[in] ImageHandle The firmware allocated handle for the EFI image.
147 @param[in] SystemTable A pointer to the EFI System Table.
148
149 @retval EFI_SUCCESS The entry point is executed successfully.
150 @retval EFI_UNSUPPORTED Do not support ACPI S3.
151 @retval other Some error occurs when executing this entry point.
152
153**/
154EFI_STATUS
155EFIAPI
156CpuS3DataInitialize (
157 IN EFI_HANDLE ImageHandle,
158 IN EFI_SYSTEM_TABLE *SystemTable
159 )
160{
161 EFI_STATUS Status;
162 ACPI_CPU_DATA_EX *AcpiCpuDataEx;
163 ACPI_CPU_DATA *AcpiCpuData;
164 EFI_MP_SERVICES_PROTOCOL *MpServices;
165 UINTN NumberOfCpus;
166 UINTN NumberOfEnabledProcessors;
167 VOID *Stack;
168 UINTN GdtSize;
169 UINTN IdtSize;
170 VOID *Gdt;
171 VOID *Idt;
172 EFI_EVENT Event;
173 ACPI_CPU_DATA *OldAcpiCpuData;
174
175 if (!PcdGetBool (PcdAcpiS3Enable)) {
176 return EFI_UNSUPPORTED;
177 }
178
179 //
180 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
181 //
182 OldAcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
183
184 AcpiCpuDataEx = AllocateZeroPages (sizeof (ACPI_CPU_DATA_EX));
185 ASSERT (AcpiCpuDataEx != NULL);
186 AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData;
187
188 //
189 // Get MP Services Protocol
190 //
191 Status = gBS->LocateProtocol (
192 &gEfiMpServiceProtocolGuid,
193 NULL,
194 (VOID **)&MpServices
195 );
196 ASSERT_EFI_ERROR (Status);
197
198 //
199 // Get the number of CPUs
200 //
201 Status = MpServices->GetNumberOfProcessors (
202 MpServices,
203 &NumberOfCpus,
204 &NumberOfEnabledProcessors
205 );
206 ASSERT_EFI_ERROR (Status);
207 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
208
209 //
210 // Initialize ACPI_CPU_DATA fields
211 //
212 AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize);
213 AcpiCpuData->ApMachineCheckHandlerBase = 0;
214 AcpiCpuData->ApMachineCheckHandlerSize = 0;
215 AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->GdtrProfile;
216 AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->IdtrProfile;
217 AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->MtrrTable;
218
219 //
220 // Allocate stack space for all CPUs.
221 // Use ACPI NVS memory type because this data will be directly used by APs
222 // in S3 resume phase in long mode. Also during S3 resume, the stack buffer
223 // will only be used as scratch space. i.e. we won't read anything from it
224 // before we write to it, in PiSmmCpuDxeSmm.
225 //
226 Stack = AllocateAcpiNvsMemory (NumberOfCpus * AcpiCpuData->StackSize);
227 ASSERT (Stack != NULL);
228 AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack;
229
230 //
231 // Get the boot processor's GDT and IDT
232 //
233 AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile);
234 AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile);
235
236 //
237 // Allocate GDT and IDT and copy current GDT and IDT contents
238 //
239 GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;
240 IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;
241 Gdt = AllocateZeroPages (GdtSize + IdtSize);
242 ASSERT (Gdt != NULL);
243 Idt = (VOID *)((UINTN)Gdt + GdtSize);
244 CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);
245 CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);
246 AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;
247 AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;
248
249 if (OldAcpiCpuData != NULL) {
250 AcpiCpuData->RegisterTable = OldAcpiCpuData->RegisterTable;
251 AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable;
252 AcpiCpuData->ApLocation = OldAcpiCpuData->ApLocation;
253 CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
254 }
255
256 //
257 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
258 //
259 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
260 ASSERT_EFI_ERROR (Status);
261
262 //
263 // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
264 // The notification function allocates StartupVector and saves MTRRs for ACPI_CPU_DATA
265 //
266 Status = gBS->CreateEventEx (
267 EVT_NOTIFY_SIGNAL,
268 TPL_CALLBACK,
269 CpuS3DataOnEndOfDxe,
270 AcpiCpuData,
271 &gEfiEndOfDxeEventGroupGuid,
272 &Event
273 );
274 ASSERT_EFI_ERROR (Status);
275
276 return EFI_SUCCESS;
277}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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