]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg/CpuDxe: Enable protection for newly added page table
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
CommitLineData
3e8ad6bd
JF
1/** @file\r
2 MP initialize support functions for PEI phase.\r
3\r
9293d6e4 4 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
3e8ad6bd
JF
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 "MpLib.h"\r
43c9fdcc
JF
16\r
17/**\r
18 Enable Debug Agent to support source debugging on AP function.\r
19\r
20**/\r
21VOID\r
22EnableDebugAgent (\r
23 VOID\r
24 )\r
25{\r
26}\r
27\r
93ca4c0f
JF
28/**\r
29 Get pointer to CPU MP Data structure.\r
30\r
31 @return The pointer to CPU MP Data structure.\r
32**/\r
33CPU_MP_DATA *\r
34GetCpuMpData (\r
35 VOID\r
36 )\r
37{\r
38 CPU_MP_DATA *CpuMpData;\r
39\r
40 CpuMpData = GetCpuMpDataFromGuidedHob ();\r
41 ASSERT (CpuMpData != NULL);\r
42 return CpuMpData;\r
43}\r
44\r
45/**\r
46 Save the pointer to CPU MP Data structure.\r
47\r
48 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.\r
49**/\r
50VOID\r
51SaveCpuMpData (\r
52 IN CPU_MP_DATA *CpuMpData\r
53 )\r
54{\r
55 UINT64 Data64;\r
56 //\r
57 // Build location of CPU MP DATA buffer in HOB\r
58 //\r
59 Data64 = (UINT64) (UINTN) CpuMpData;\r
60 BuildGuidDataHob (\r
61 &mCpuInitMpLibHobGuid,\r
62 (VOID *) &Data64,\r
63 sizeof (UINT64)\r
64 );\r
65}\r
66\r
ed66e0e3
JF
67/**\r
68 Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
69\r
70 @param[in] WakeupBufferStart AP wakeup buffer start address.\r
71 @param[in] WakeupBufferEnd AP wakeup buffer end address.\r
72\r
73 @retval TRUE There is overlap.\r
74 @retval FALSE There is no overlap.\r
75**/\r
76BOOLEAN\r
77CheckOverlapWithAllocatedBuffer (\r
78 IN UINTN WakeupBufferStart,\r
79 IN UINTN WakeupBufferEnd\r
80 )\r
81{\r
82 EFI_PEI_HOB_POINTERS Hob;\r
83 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
84 BOOLEAN Overlapped;\r
85 UINTN MemoryStart;\r
86 UINTN MemoryEnd;\r
87\r
88 Overlapped = FALSE;\r
89 //\r
90 // Get the HOB list for processing\r
91 //\r
92 Hob.Raw = GetHobList ();\r
93 //\r
94 // Collect memory ranges\r
95 //\r
96 while (!END_OF_HOB_LIST (Hob)) {\r
97 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
98 MemoryHob = Hob.MemoryAllocation;\r
99 MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
100 MemoryEnd = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +\r
101 MemoryHob->AllocDescriptor.MemoryLength);\r
102 if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
103 Overlapped = TRUE;\r
104 break;\r
105 }\r
106 }\r
107 Hob.Raw = GET_NEXT_HOB (Hob);\r
108 }\r
109 return Overlapped;\r
110}\r
111\r
112/**\r
113 Get available system memory below 1MB by specified size.\r
114\r
115 @param[in] WakeupBufferSize Wakeup buffer size required\r
116\r
117 @retval other Return wakeup buffer address below 1MB.\r
118 @retval -1 Cannot find free memory below 1MB.\r
119**/\r
120UINTN\r
121GetWakeupBuffer (\r
122 IN UINTN WakeupBufferSize\r
123 )\r
124{\r
125 EFI_PEI_HOB_POINTERS Hob;\r
126 UINTN WakeupBufferStart;\r
127 UINTN WakeupBufferEnd;\r
128\r
129 WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
130\r
131 //\r
132 // Get the HOB list for processing\r
133 //\r
134 Hob.Raw = GetHobList ();\r
135\r
136 //\r
137 // Collect memory ranges\r
138 //\r
139 while (!END_OF_HOB_LIST (Hob)) {\r
140 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
141 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
142 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
143 ((Hob.ResourceDescriptor->ResourceAttribute &\r
144 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
145 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
146 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
147 )) == 0)\r
148 ) {\r
149 //\r
150 // Need memory under 1MB to be collected here\r
151 //\r
152 WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
153 if (WakeupBufferEnd > BASE_1MB) {\r
154 //\r
155 // Wakeup buffer should be under 1MB\r
156 //\r
157 WakeupBufferEnd = BASE_1MB;\r
158 }\r
159 while (WakeupBufferEnd > WakeupBufferSize) {\r
160 //\r
161 // Wakeup buffer should be aligned on 4KB\r
162 //\r
163 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
164 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
165 break;\r
166 }\r
167 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
168 //\r
169 // If this range is overlapped with existing allocated buffer, skip it\r
170 // and find the next range\r
171 //\r
172 WakeupBufferEnd -= WakeupBufferSize;\r
173 continue;\r
174 }\r
175 DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
176 WakeupBufferStart, WakeupBufferSize));\r
ed66e0e3
JF
177 return WakeupBufferStart;\r
178 }\r
179 }\r
180 }\r
181 //\r
182 // Find the next HOB\r
183 //\r
184 Hob.Raw = GET_NEXT_HOB (Hob);\r
185 }\r
186\r
187 return (UINTN) -1;\r
188}\r
189\r
08085f08
JF
190/**\r
191 Checks APs status and updates APs status if needed.\r
192\r
193**/\r
194VOID\r
195CheckAndUpdateApsStatus (\r
196 VOID\r
197 )\r
198{\r
199}\r
200\r
93ca4c0f
JF
201/**\r
202 Initialize global data for MP support.\r
203\r
204 @param[in] CpuMpData The pointer to CPU MP Data structure.\r
205**/\r
206VOID\r
207InitMpGlobalData (\r
208 IN CPU_MP_DATA *CpuMpData\r
209 )\r
210{\r
93ca4c0f
JF
211 SaveCpuMpData (CpuMpData);\r
212}\r
213\r
3e8ad6bd
JF
214/**\r
215 This service executes a caller provided function on all enabled APs.\r
216\r
217 @param[in] Procedure A pointer to the function to be run on\r
218 enabled APs of the system. See type\r
219 EFI_AP_PROCEDURE.\r
220 @param[in] SingleThread If TRUE, then all the enabled APs execute\r
221 the function specified by Procedure one by\r
222 one, in ascending order of processor handle\r
223 number. If FALSE, then all the enabled APs\r
224 execute the function specified by Procedure\r
225 simultaneously.\r
226 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
227 service. If it is NULL, then execute in\r
228 blocking mode. BSP waits until all APs finish\r
229 or TimeoutInMicroSeconds expires. If it's\r
230 not NULL, then execute in non-blocking mode.\r
231 BSP requests the function specified by\r
232 Procedure to be started on all the enabled\r
233 APs, and go on executing immediately. If\r
234 all return from Procedure, or TimeoutInMicroSeconds\r
235 expires, this event is signaled. The BSP\r
236 can use the CheckEvent() or WaitForEvent()\r
237 services to check the state of event. Type\r
238 EFI_EVENT is defined in CreateEvent() in\r
239 the Unified Extensible Firmware Interface\r
240 Specification.\r
367284e7 241 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
242 APs to return from Procedure, either for\r
243 blocking or non-blocking mode. Zero means\r
244 infinity. If the timeout expires before\r
245 all APs return from Procedure, then Procedure\r
246 on the failed APs is terminated. All enabled\r
247 APs are available for next function assigned\r
248 by MpInitLibStartupAllAPs() or\r
249 MPInitLibStartupThisAP().\r
250 If the timeout expires in blocking mode,\r
251 BSP returns EFI_TIMEOUT. If the timeout\r
252 expires in non-blocking mode, WaitEvent\r
253 is signaled with SignalEvent().\r
254 @param[in] ProcedureArgument The parameter passed into Procedure for\r
255 all APs.\r
256 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,\r
257 if all APs finish successfully, then its\r
258 content is set to NULL. If not all APs\r
259 finish before timeout expires, then its\r
260 content is set to address of the buffer\r
261 holding handle numbers of the failed APs.\r
262 The buffer is allocated by MP Initialization\r
263 library, and it's the caller's responsibility to\r
264 free the buffer with FreePool() service.\r
265 In blocking mode, it is ready for consumption\r
266 when the call returns. In non-blocking mode,\r
267 it is ready when WaitEvent is signaled. The\r
268 list of failed CPU is terminated by\r
269 END_OF_CPU_LIST.\r
270\r
271 @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
272 the timeout expired.\r
273 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
274 to all enabled APs.\r
275 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
276 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
277 signaled.\r
278 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
279 supported.\r
280 @retval EFI_DEVICE_ERROR Caller processor is AP.\r
281 @retval EFI_NOT_STARTED No enabled APs exist in the system.\r
282 @retval EFI_NOT_READY Any enabled APs are busy.\r
283 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
284 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
285 all enabled APs have finished.\r
286 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
287\r
288**/\r
289EFI_STATUS\r
290EFIAPI\r
291MpInitLibStartupAllAPs (\r
292 IN EFI_AP_PROCEDURE Procedure,\r
293 IN BOOLEAN SingleThread,\r
294 IN EFI_EVENT WaitEvent OPTIONAL,\r
295 IN UINTN TimeoutInMicroseconds,\r
296 IN VOID *ProcedureArgument OPTIONAL,\r
297 OUT UINTN **FailedCpuList OPTIONAL\r
298 )\r
299{\r
86efe976
JF
300 if (WaitEvent != NULL) {\r
301 return EFI_UNSUPPORTED;\r
302 }\r
303\r
304 return StartupAllAPsWorker (\r
305 Procedure,\r
306 SingleThread,\r
307 NULL,\r
308 TimeoutInMicroseconds,\r
309 ProcedureArgument,\r
310 FailedCpuList\r
311 );\r
3e8ad6bd
JF
312}\r
313\r
314/**\r
315 This service lets the caller get one enabled AP to execute a caller-provided\r
316 function.\r
317\r
318 @param[in] Procedure A pointer to the function to be run on the\r
319 designated AP of the system. See type\r
320 EFI_AP_PROCEDURE.\r
321 @param[in] ProcessorNumber The handle number of the AP. The range is\r
322 from 0 to the total number of logical\r
323 processors minus 1. The total number of\r
324 logical processors can be retrieved by\r
325 MpInitLibGetNumberOfProcessors().\r
326 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
327 service. If it is NULL, then execute in\r
328 blocking mode. BSP waits until this AP finish\r
329 or TimeoutInMicroSeconds expires. If it's\r
330 not NULL, then execute in non-blocking mode.\r
331 BSP requests the function specified by\r
332 Procedure to be started on this AP,\r
333 and go on executing immediately. If this AP\r
334 return from Procedure or TimeoutInMicroSeconds\r
335 expires, this event is signaled. The BSP\r
336 can use the CheckEvent() or WaitForEvent()\r
337 services to check the state of event. Type\r
338 EFI_EVENT is defined in CreateEvent() in\r
339 the Unified Extensible Firmware Interface\r
340 Specification.\r
367284e7 341 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
342 this AP to finish this Procedure, either for\r
343 blocking or non-blocking mode. Zero means\r
344 infinity. If the timeout expires before\r
345 this AP returns from Procedure, then Procedure\r
346 on the AP is terminated. The\r
347 AP is available for next function assigned\r
348 by MpInitLibStartupAllAPs() or\r
349 MpInitLibStartupThisAP().\r
350 If the timeout expires in blocking mode,\r
351 BSP returns EFI_TIMEOUT. If the timeout\r
352 expires in non-blocking mode, WaitEvent\r
353 is signaled with SignalEvent().\r
354 @param[in] ProcedureArgument The parameter passed into Procedure on the\r
355 specified AP.\r
356 @param[out] Finished If NULL, this parameter is ignored. In\r
357 blocking mode, this parameter is ignored.\r
358 In non-blocking mode, if AP returns from\r
359 Procedure before the timeout expires, its\r
360 content is set to TRUE. Otherwise, the\r
361 value is set to FALSE. The caller can\r
362 determine if the AP returned from Procedure\r
363 by evaluating this value.\r
364\r
365 @retval EFI_SUCCESS In blocking mode, specified AP finished before\r
366 the timeout expires.\r
367 @retval EFI_SUCCESS In non-blocking mode, the function has been\r
368 dispatched to specified AP.\r
369 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
370 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
371 signaled.\r
372 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
373 supported.\r
374 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
375 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
376 the specified AP has finished.\r
377 @retval EFI_NOT_READY The specified AP is busy.\r
378 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
379 @retval EFI_NOT_FOUND The processor with the handle specified by\r
380 ProcessorNumber does not exist.\r
381 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
382 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
383\r
384**/\r
385EFI_STATUS\r
386EFIAPI\r
387MpInitLibStartupThisAP (\r
388 IN EFI_AP_PROCEDURE Procedure,\r
389 IN UINTN ProcessorNumber,\r
390 IN EFI_EVENT WaitEvent OPTIONAL,\r
391 IN UINTN TimeoutInMicroseconds,\r
392 IN VOID *ProcedureArgument OPTIONAL,\r
393 OUT BOOLEAN *Finished OPTIONAL\r
394 )\r
395{\r
20ae5774
JF
396 if (WaitEvent != NULL) {\r
397 return EFI_UNSUPPORTED;\r
398 }\r
399\r
400 return StartupThisAPWorker (\r
401 Procedure,\r
402 ProcessorNumber,\r
403 NULL,\r
404 TimeoutInMicroseconds,\r
405 ProcedureArgument,\r
406 Finished\r
407 );\r
3e8ad6bd
JF
408}\r
409\r
410/**\r
411 This service switches the requested AP to be the BSP from that point onward.\r
412 This service changes the BSP for all purposes. This call can only be performed\r
413 by the current BSP.\r
414\r
415 @param[in] ProcessorNumber The handle number of AP that is to become the new\r
416 BSP. The range is from 0 to the total number of\r
417 logical processors minus 1. The total number of\r
418 logical processors can be retrieved by\r
419 MpInitLibGetNumberOfProcessors().\r
420 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an\r
421 enabled AP. Otherwise, it will be disabled.\r
422\r
423 @retval EFI_SUCCESS BSP successfully switched.\r
424 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to\r
425 this service returning.\r
426 @retval EFI_UNSUPPORTED Switching the BSP is not supported.\r
427 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
428 @retval EFI_NOT_FOUND The processor with the handle specified by\r
429 ProcessorNumber does not exist.\r
430 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or\r
431 a disabled AP.\r
432 @retval EFI_NOT_READY The specified AP is busy.\r
433 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
434\r
435**/\r
436EFI_STATUS\r
437EFIAPI\r
438MpInitLibSwitchBSP (\r
439 IN UINTN ProcessorNumber,\r
440 IN BOOLEAN EnableOldBSP\r
441 )\r
442{\r
41be0da5 443 return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
3e8ad6bd
JF
444}\r
445\r
446/**\r
447 This service lets the caller enable or disable an AP from this point onward.\r
448 This service may only be called from the BSP.\r
449\r
450 @param[in] ProcessorNumber The handle number of AP.\r
451 The range is from 0 to the total number of\r
452 logical processors minus 1. The total number of\r
453 logical processors can be retrieved by\r
454 MpInitLibGetNumberOfProcessors().\r
455 @param[in] EnableAP Specifies the new state for the processor for\r
456 enabled, FALSE for disabled.\r
457 @param[in] HealthFlag If not NULL, a pointer to a value that specifies\r
458 the new health status of the AP. This flag\r
459 corresponds to StatusFlag defined in\r
460 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only\r
461 the PROCESSOR_HEALTH_STATUS_BIT is used. All other\r
462 bits are ignored. If it is NULL, this parameter\r
463 is ignored.\r
464\r
465 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.\r
466 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed\r
467 prior to this service returning.\r
468 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.\r
469 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
470 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber\r
471 does not exist.\r
472 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.\r
473 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
474\r
475**/\r
476EFI_STATUS\r
477EFIAPI\r
478MpInitLibEnableDisableAP (\r
479 IN UINTN ProcessorNumber,\r
480 IN BOOLEAN EnableAP,\r
481 IN UINT32 *HealthFlag OPTIONAL\r
482 )\r
483{\r
e37109bc 484 return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
3e8ad6bd
JF
485}\r
486\r
487\r