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