]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
UefiCpuPkg/CpuFeatures: Change files format to DOS
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / PeiRegisterCpuFeaturesLib.c
CommitLineData
80c4b236
JF
1/** @file\r
2 CPU Register Table Library functions.\r
3\r
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16\r
17#include <Library/HobLib.h>\r
18#include <Library/PeiServicesLib.h>\r
19#include <Library/PeiServicesTablePointerLib.h>\r
20#include <Ppi/MpServices.h>\r
21#include "RegisterCpuFeatures.h"\r
22\r
23#define REGISTER_CPU_FEATURES_GUID \\r
24 { \\r
25 0xa694c467, 0x697a, 0x446b, { 0xb9, 0x29, 0x5b, 0x14, 0xa0, 0xcf, 0x39, 0xf } \\r
26 }\r
27\r
28EFI_GUID mRegisterCpuFeaturesHobGuid = REGISTER_CPU_FEATURES_GUID;\r
29\r
30/**\r
31 Worker function to get CPU_FEATURES_DATA pointer.\r
32\r
33 @return Pointer to CPU_FEATURES_DATA.\r
34**/\r
35CPU_FEATURES_DATA *\r
36GetCpuFeaturesData (\r
37 VOID\r
38 )\r
39{\r
40 CPU_FEATURES_DATA *CpuInitData;\r
41 EFI_HOB_GUID_TYPE *GuidHob;\r
42 VOID *DataInHob;\r
43 UINT64 Data64;\r
44\r
45 CpuInitData = NULL;\r
46 GuidHob = GetFirstGuidHob (&mRegisterCpuFeaturesHobGuid);\r
47 if (GuidHob != NULL) {\r
48 DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
49 CpuInitData = (CPU_FEATURES_DATA *) (*(UINTN *) DataInHob);\r
50 ASSERT (CpuInitData != NULL);\r
51 } else {\r
52 CpuInitData = AllocateZeroPool (sizeof (CPU_FEATURES_DATA));\r
53 ASSERT (CpuInitData != NULL);\r
54 //\r
55 // Build location of CPU MP DATA buffer in HOB\r
56 //\r
57 Data64 = (UINT64) (UINTN) CpuInitData;\r
58 BuildGuidDataHob (\r
59 &mRegisterCpuFeaturesHobGuid,\r
60 (VOID *) &Data64,\r
61 sizeof (UINT64)\r
62 );\r
63 }\r
64\r
65 return CpuInitData;\r
66}\r
67\r
68/**\r
69 Worker function to get MP PPI service pointer.\r
70\r
71 @return PEI PPI service pointer.\r
72**/\r
73EFI_PEI_MP_SERVICES_PPI *\r
74GetMpPpi (\r
75 VOID\r
76 )\r
77{\r
78 EFI_STATUS Status;\r
79 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
80\r
81 //\r
82 // Get MP Services Protocol\r
83 //\r
84 Status = PeiServicesLocatePpi (\r
85 &gEfiPeiMpServicesPpiGuid,\r
86 0,\r
87 NULL,\r
88 (VOID **)&CpuMpPpi\r
89 );\r
90 ASSERT_EFI_ERROR (Status);\r
91 return CpuMpPpi;\r
92}\r
93\r
94/**\r
95 Worker function to return processor index.\r
96\r
97 @return The processor index.\r
98**/\r
99UINTN\r
100GetProcessorIndex (\r
101 VOID\r
102 )\r
103{\r
104 EFI_STATUS Status;\r
105 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
106 UINTN ProcessorIndex;\r
107\r
108 CpuMpPpi = GetMpPpi ();\r
109\r
110 Status = CpuMpPpi->WhoAmI(GetPeiServicesTablePointer (), CpuMpPpi, &ProcessorIndex);\r
111 ASSERT_EFI_ERROR (Status);\r
112 return ProcessorIndex;\r
113}\r
114\r
115/**\r
116 Worker function to MP-related information on the requested processor at the\r
117 instant this call is made.\r
118\r
119 @param[in] ProcessorNumber The handle number of processor.\r
120 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for\r
121 the requested processor is deposited.\r
122\r
123 @return Status of MpServices->GetProcessorInfo().\r
124**/\r
125EFI_STATUS\r
126GetProcessorInformation (\r
127 IN UINTN ProcessorNumber,\r
128 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer\r
129 )\r
130{\r
131 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
132 EFI_STATUS Status;\r
133\r
134 CpuMpPpi = GetMpPpi ();\r
135 Status = CpuMpPpi->GetProcessorInfo (\r
136 GetPeiServicesTablePointer(),\r
137 CpuMpPpi,\r
138 ProcessorNumber,\r
139 ProcessorInfoBuffer\r
140 );\r
141 return Status;\r
142}\r
143\r
144/**\r
145 Worker function to execute a caller provided function on all enabled APs.\r
146\r
147 @param[in] Procedure A pointer to the function to be run on\r
148 enabled APs of the system.\r
149**/\r
150VOID\r
151StartupAPsWorker (\r
152 IN EFI_AP_PROCEDURE Procedure\r
153 )\r
154{\r
155 EFI_STATUS Status;\r
156 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
157\r
158 //\r
159 // Get MP Services Protocol\r
160 //\r
161 Status = PeiServicesLocatePpi (\r
162 &gEfiPeiMpServicesPpiGuid,\r
163 0,\r
164 NULL,\r
165 (VOID **)&CpuMpPpi\r
166 );\r
167 ASSERT_EFI_ERROR (Status);\r
168\r
169 //\r
170 // Wakeup all APs for data collection.\r
171 //\r
172 Status = CpuMpPpi->StartupAllAPs (\r
173 GetPeiServicesTablePointer (),\r
174 CpuMpPpi,\r
175 Procedure,\r
176 FALSE,\r
177 0,\r
178 NULL\r
179 );\r
180 ASSERT_EFI_ERROR (Status);\r
181}\r
182\r
183/**\r
184 Worker function to switch the requested AP to be the BSP from that point onward.\r
185\r
186 @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.\r
187**/\r
188VOID\r
189SwitchNewBsp (\r
190 IN UINTN ProcessorNumber\r
191 )\r
192{\r
193 EFI_STATUS Status;\r
194 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
195\r
196 //\r
197 // Get MP Services Protocol\r
198 //\r
199 Status = PeiServicesLocatePpi (\r
200 &gEfiPeiMpServicesPpiGuid,\r
201 0,\r
202 NULL,\r
203 (VOID **)&CpuMpPpi\r
204 );\r
205 ASSERT_EFI_ERROR (Status);\r
206\r
207 //\r
208 // Wakeup all APs for data collection.\r
209 //\r
210 Status = CpuMpPpi->SwitchBSP (\r
211 GetPeiServicesTablePointer (),\r
212 CpuMpPpi,\r
213 ProcessorNumber,\r
214 TRUE\r
215 );\r
216 ASSERT_EFI_ERROR (Status);\r
217}\r
218\r
219/**\r
220 Worker function to retrieve the number of logical processor in the platform.\r
221\r
222 @param[out] NumberOfCpus Pointer to the total number of logical\r
223 processors in the system, including the BSP\r
224 and disabled APs.\r
225 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical\r
226 processors that exist in system, including\r
227 the BSP.\r
228**/\r
229VOID\r
230GetNumberOfProcessor (\r
231 OUT UINTN *NumberOfCpus,\r
232 OUT UINTN *NumberOfEnabledProcessors\r
233 )\r
234{\r
235 EFI_STATUS Status;\r
236 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
237\r
238 //\r
239 // Get MP Services Protocol\r
240 //\r
241 Status = PeiServicesLocatePpi (\r
242 &gEfiPeiMpServicesPpiGuid,\r
243 0,\r
244 NULL,\r
245 (VOID **)&CpuMpPpi\r
246 );\r
247 ASSERT_EFI_ERROR (Status);\r
248\r
249 //\r
250 // Get the number of CPUs\r
251 //\r
252 Status = CpuMpPpi->GetNumberOfProcessors (\r
253 GetPeiServicesTablePointer (),\r
254 CpuMpPpi,\r
255 NumberOfCpus,\r
256 NumberOfEnabledProcessors\r
257 );\r
258 ASSERT_EFI_ERROR (Status);\r
259}\r
260\r
261/**\r
262 Allocates ACPI NVS memory to save ACPI_CPU_DATA.\r
263\r
264 @return Pointer to allocated ACPI_CPU_DATA.\r
265**/\r
266ACPI_CPU_DATA *\r
267AllocateAcpiCpuData (\r
268 VOID\r
269 )\r
270{\r
271 EFI_STATUS Status;\r
272 EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
273 UINTN NumberOfCpus;\r
274 UINTN NumberOfEnabledProcessors;\r
275 ACPI_CPU_DATA *AcpiCpuData;\r
276 EFI_PHYSICAL_ADDRESS Address;\r
277 UINTN TableSize;\r
278 CPU_REGISTER_TABLE *RegisterTable;\r
279 UINTN Index;\r
280 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
281\r
282 Status = PeiServicesAllocatePages (\r
283 EfiACPIMemoryNVS,\r
284 EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)),\r
285 &Address\r
286 );\r
287 ASSERT_EFI_ERROR (Status);\r
288 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) Address;\r
289 ASSERT (AcpiCpuData != NULL);\r
290\r
291 //\r
292 // Get MP Services Protocol\r
293 //\r
294 Status = PeiServicesLocatePpi (\r
295 &gEfiPeiMpServicesPpiGuid,\r
296 0,\r
297 NULL,\r
298 (VOID **)&CpuMpPpi\r
299 );\r
300 ASSERT_EFI_ERROR (Status);\r
301\r
302 //\r
303 // Get the number of CPUs\r
304 //\r
305 Status = CpuMpPpi->GetNumberOfProcessors (\r
306 GetPeiServicesTablePointer (),\r
307 CpuMpPpi,\r
308 &NumberOfCpus,\r
309 &NumberOfEnabledProcessors\r
310 );\r
311 ASSERT_EFI_ERROR (Status);\r
312 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
313\r
314 //\r
315 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs\r
316 //\r
317 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);\r
318 Status = PeiServicesAllocatePages (\r
319 EfiACPIMemoryNVS,\r
320 EFI_SIZE_TO_PAGES (TableSize),\r
321 &Address\r
322 );\r
323 ASSERT_EFI_ERROR (Status);\r
324 RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) Address;\r
325\r
326 for (Index = 0; Index < NumberOfCpus; Index++) {\r
327 Status = CpuMpPpi->GetProcessorInfo (\r
328 GetPeiServicesTablePointer (),\r
329 CpuMpPpi,\r
330 Index,\r
331 &ProcessorInfoBuffer\r
332 );\r
333 ASSERT_EFI_ERROR (Status);\r
334\r
335 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
336 RegisterTable[Index].TableLength = 0;\r
337 RegisterTable[Index].AllocatedSize = 0;\r
338 RegisterTable[Index].RegisterTableEntry = 0;\r
339\r
340 RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
341 RegisterTable[NumberOfCpus + Index].TableLength = 0;\r
342 RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;\r
343 RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;\r
344 }\r
345 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;\r
346 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);\r
347\r
348 return AcpiCpuData;\r
349}\r
350\r
351/**\r
352 Enlarges CPU register table for each processor.\r
353\r
354 @param[in, out] RegisterTable Pointer processor's CPU register table\r
355**/\r
356VOID\r
357EnlargeRegisterTable (\r
358 IN OUT CPU_REGISTER_TABLE *RegisterTable\r
359 )\r
360{\r
361 EFI_STATUS Status;\r
362 EFI_PHYSICAL_ADDRESS Address;\r
363 UINTN AllocatePages;\r
364\r
365 AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;\r
366 Status = PeiServicesAllocatePages (\r
367 EfiACPIMemoryNVS,\r
368 AllocatePages + 1,\r
369 &Address\r
370 );\r
371 ASSERT_EFI_ERROR (Status);\r
372\r
373 //\r
374 // If there are records existing in the register table, then copy its contents\r
375 // to new region and free the old one.\r
376 //\r
377 if (RegisterTable->AllocatedSize > 0) {\r
378 CopyMem (\r
379 (VOID *) (UINTN) Address,\r
380 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,\r
381 RegisterTable->AllocatedSize\r
382 );\r
383 }\r
384\r
385 //\r
386 // Adjust the allocated size and register table base address.\r
387 //\r
388 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;\r
389 RegisterTable->RegisterTableEntry = Address;\r
390}\r