VirtualBox

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

Last change on this file since 100307 was 99404, checked in by vboxsync, 20 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
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 - 2021, 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/**
100 Callback function executed when the EndOfDxe event group is signaled.
101
102 We delay allocating StartupVector and saving the MTRR settings until BDS signals EndOfDxe.
103
104 @param[in] Event Event whose notification function is being invoked.
105 @param[out] Context Pointer to the MTRR_SETTINGS buffer to fill in.
106**/
107VOID
108EFIAPI
109CpuS3DataOnEndOfDxe (
110 IN EFI_EVENT Event,
111 OUT VOID *Context
112 )
113{
114 EFI_STATUS Status;
115 ACPI_CPU_DATA_EX *AcpiCpuDataEx;
116
117 AcpiCpuDataEx = (ACPI_CPU_DATA_EX *)Context;
118 //
119 // Allocate a 4KB reserved page below 1MB
120 //
121 AcpiCpuDataEx->AcpiCpuData.StartupVector = BASE_1MB - 1;
122 Status = gBS->AllocatePages (
123 AllocateMaxAddress,
124 EfiReservedMemoryType,
125 1,
126 &AcpiCpuDataEx->AcpiCpuData.StartupVector
127 );
128 ASSERT_EFI_ERROR (Status);
129
130 DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));
131 MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
132
133 //
134 // Close event, so it will not be invoked again.
135 //
136 gBS->CloseEvent (Event);
137}
138
139/**
140 The entry function of the CpuS3Data driver.
141
142 Allocate and initialize all fields of the ACPI_CPU_DATA structure except the
143 MTRR settings. Register an event notification on gEfiEndOfDxeEventGroupGuid
144 to capture the ACPI_CPU_DATA MTRR settings. The PcdCpuS3DataAddress is set
145 to the address that ACPI_CPU_DATA is allocated at.
146
147 @param[in] ImageHandle The firmware allocated handle for the EFI image.
148 @param[in] SystemTable A pointer to the EFI System Table.
149
150 @retval EFI_SUCCESS The entry point is executed successfully.
151 @retval EFI_UNSUPPORTED Do not support ACPI S3.
152 @retval other Some error occurs when executing this entry point.
153
154**/
155EFI_STATUS
156EFIAPI
157CpuS3DataInitialize (
158 IN EFI_HANDLE ImageHandle,
159 IN EFI_SYSTEM_TABLE *SystemTable
160 )
161{
162 EFI_STATUS Status;
163 ACPI_CPU_DATA_EX *AcpiCpuDataEx;
164 ACPI_CPU_DATA *AcpiCpuData;
165 EFI_MP_SERVICES_PROTOCOL *MpServices;
166 UINTN NumberOfCpus;
167 UINTN NumberOfEnabledProcessors;
168 VOID *Stack;
169 UINTN GdtSize;
170 UINTN IdtSize;
171 VOID *Gdt;
172 VOID *Idt;
173 EFI_EVENT Event;
174 ACPI_CPU_DATA *OldAcpiCpuData;
175
176 if (!PcdGetBool (PcdAcpiS3Enable)) {
177 return EFI_UNSUPPORTED;
178 }
179
180 //
181 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
182 //
183 OldAcpiCpuData = (ACPI_CPU_DATA *)(UINTN)PcdGet64 (PcdCpuS3DataAddress);
184
185 AcpiCpuDataEx = AllocateZeroPages (sizeof (ACPI_CPU_DATA_EX));
186 ASSERT (AcpiCpuDataEx != NULL);
187 AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData;
188
189 //
190 // Get MP Services Protocol
191 //
192 Status = gBS->LocateProtocol (
193 &gEfiMpServiceProtocolGuid,
194 NULL,
195 (VOID **)&MpServices
196 );
197 ASSERT_EFI_ERROR (Status);
198
199 //
200 // Get the number of CPUs
201 //
202 Status = MpServices->GetNumberOfProcessors (
203 MpServices,
204 &NumberOfCpus,
205 &NumberOfEnabledProcessors
206 );
207 ASSERT_EFI_ERROR (Status);
208 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
209
210 //
211 // Initialize ACPI_CPU_DATA fields
212 //
213 AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize);
214 AcpiCpuData->ApMachineCheckHandlerBase = 0;
215 AcpiCpuData->ApMachineCheckHandlerSize = 0;
216 AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->GdtrProfile;
217 AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->IdtrProfile;
218 AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->MtrrTable;
219
220 //
221 // Allocate stack space for all CPUs.
222 // Use ACPI NVS memory type because this data will be directly used by APs
223 // in S3 resume phase in long mode. Also during S3 resume, the stack buffer
224 // will only be used as scratch space. i.e. we won't read anything from it
225 // before we write to it, in PiSmmCpuDxeSmm.
226 //
227 Stack = AllocateAcpiNvsMemory (NumberOfCpus * AcpiCpuData->StackSize);
228 ASSERT (Stack != NULL);
229 AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack;
230
231 //
232 // Get the boot processor's GDT and IDT
233 //
234 AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile);
235 AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile);
236
237 //
238 // Allocate GDT and IDT and copy current GDT and IDT contents
239 //
240 GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;
241 IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;
242 Gdt = AllocateZeroPages (GdtSize + IdtSize);
243 ASSERT (Gdt != NULL);
244 Idt = (VOID *)((UINTN)Gdt + GdtSize);
245 CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);
246 CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);
247 AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;
248 AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;
249
250 if (OldAcpiCpuData != NULL) {
251 CopyMem (&AcpiCpuData->CpuFeatureInitData, &OldAcpiCpuData->CpuFeatureInitData, sizeof (CPU_FEATURE_INIT_DATA));
252 }
253
254 //
255 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
256 //
257 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
258 ASSERT_EFI_ERROR (Status);
259
260 //
261 // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
262 // The notification function allocates StartupVector and saves MTRRs for ACPI_CPU_DATA
263 //
264 Status = gBS->CreateEventEx (
265 EVT_NOTIFY_SIGNAL,
266 TPL_CALLBACK,
267 CpuS3DataOnEndOfDxe,
268 AcpiCpuData,
269 &gEfiEndOfDxeEventGroupGuid,
270 &Event
271 );
272 ASSERT_EFI_ERROR (Status);
273
274 return EFI_SUCCESS;
275}
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