2 CPU MP Initialize Library common functions.
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
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.
18 Get the Application Processors state.
20 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
26 IN CPU_AP_DATA
*CpuData
29 return CpuData
->State
;
33 Set the Application Processors state.
35 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
36 @param[in] State The AP status
40 IN CPU_AP_DATA
*CpuData
,
44 AcquireSpinLock (&CpuData
->ApLock
);
45 CpuData
->State
= State
;
46 ReleaseSpinLock (&CpuData
->ApLock
);
50 Save the volatile registers required to be restored following INIT IPI.
52 @param[out] VolatileRegisters Returns buffer saved the volatile resisters
55 SaveVolatileRegisters (
56 OUT CPU_VOLATILE_REGISTERS
*VolatileRegisters
59 CPUID_VERSION_INFO_EDX VersionInfoEdx
;
61 VolatileRegisters
->Cr0
= AsmReadCr0 ();
62 VolatileRegisters
->Cr3
= AsmReadCr3 ();
63 VolatileRegisters
->Cr4
= AsmReadCr4 ();
65 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &VersionInfoEdx
.Uint32
);
66 if (VersionInfoEdx
.Bits
.DE
!= 0) {
68 // If processor supports Debugging Extensions feature
69 // by CPUID.[EAX=01H]:EDX.BIT2
71 VolatileRegisters
->Dr0
= AsmReadDr0 ();
72 VolatileRegisters
->Dr1
= AsmReadDr1 ();
73 VolatileRegisters
->Dr2
= AsmReadDr2 ();
74 VolatileRegisters
->Dr3
= AsmReadDr3 ();
75 VolatileRegisters
->Dr6
= AsmReadDr6 ();
76 VolatileRegisters
->Dr7
= AsmReadDr7 ();
81 Restore the volatile registers following INIT IPI.
83 @param[in] VolatileRegisters Pointer to volatile resisters
84 @param[in] IsRestoreDr TRUE: Restore DRx if supported
85 FALSE: Do not restore DRx
88 RestoreVolatileRegisters (
89 IN CPU_VOLATILE_REGISTERS
*VolatileRegisters
,
90 IN BOOLEAN IsRestoreDr
93 CPUID_VERSION_INFO_EDX VersionInfoEdx
;
95 AsmWriteCr0 (VolatileRegisters
->Cr0
);
96 AsmWriteCr3 (VolatileRegisters
->Cr3
);
97 AsmWriteCr4 (VolatileRegisters
->Cr4
);
100 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &VersionInfoEdx
.Uint32
);
101 if (VersionInfoEdx
.Bits
.DE
!= 0) {
103 // If processor supports Debugging Extensions feature
104 // by CPUID.[EAX=01H]:EDX.BIT2
106 AsmWriteDr0 (VolatileRegisters
->Dr0
);
107 AsmWriteDr1 (VolatileRegisters
->Dr1
);
108 AsmWriteDr2 (VolatileRegisters
->Dr2
);
109 AsmWriteDr3 (VolatileRegisters
->Dr3
);
110 AsmWriteDr6 (VolatileRegisters
->Dr6
);
111 AsmWriteDr7 (VolatileRegisters
->Dr7
);
117 Detect whether Mwait-monitor feature is supported.
119 @retval TRUE Mwait-monitor feature is supported.
120 @retval FALSE Mwait-monitor feature is not supported.
127 CPUID_VERSION_INFO_ECX VersionInfoEcx
;
129 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, &VersionInfoEcx
.Uint32
, NULL
);
130 return (VersionInfoEcx
.Bits
.MONITOR
== 1) ? TRUE
: FALSE
;
136 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
138 @return The AP loop mode.
142 OUT UINT32
*MonitorFilterSize
146 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx
;
148 ASSERT (MonitorFilterSize
!= NULL
);
150 ApLoopMode
= PcdGet8 (PcdCpuApLoopMode
);
151 ASSERT (ApLoopMode
>= ApInHltLoop
&& ApLoopMode
<= ApInRunLoop
);
152 if (ApLoopMode
== ApInMwaitLoop
) {
153 if (!IsMwaitSupport ()) {
155 // If processor does not support MONITOR/MWAIT feature,
156 // force AP in Hlt-loop mode
158 ApLoopMode
= ApInHltLoop
;
162 if (ApLoopMode
!= ApInMwaitLoop
) {
163 *MonitorFilterSize
= sizeof (UINT32
);
166 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
167 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
169 AsmCpuid (CPUID_MONITOR_MWAIT
, NULL
, &MonitorMwaitEbx
.Uint32
, NULL
, NULL
);
170 *MonitorFilterSize
= MonitorMwaitEbx
.Bits
.LargestMonitorLineSize
;
176 Initialize CPU AP Data when AP is wakeup at the first time.
178 @param[in, out] CpuMpData Pointer to PEI CPU MP Data
179 @param[in] ProcessorNumber The handle number of processor
180 @param[in] BistData Processor BIST data
185 IN OUT CPU_MP_DATA
*CpuMpData
,
186 IN UINTN ProcessorNumber
,
190 CpuMpData
->CpuData
[ProcessorNumber
].Waiting
= FALSE
;
191 CpuMpData
->CpuData
[ProcessorNumber
].Health
= BistData
;
192 CpuMpData
->CpuData
[ProcessorNumber
].CpuHealthy
= (BistData
== 0) ? TRUE
: FALSE
;
193 CpuMpData
->CpuData
[ProcessorNumber
].ApicId
= GetApicId ();
194 CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
= GetInitialApicId ();
195 if (CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
>= 0xFF) {
197 // Set x2APIC mode if there are any logical processor reporting
198 // an Initial APIC ID of 255 or greater.
200 AcquireSpinLock(&CpuMpData
->MpLock
);
201 CpuMpData
->X2ApicEnable
= TRUE
;
202 ReleaseSpinLock(&CpuMpData
->MpLock
);
205 InitializeSpinLock(&CpuMpData
->CpuData
[ProcessorNumber
].ApLock
);
206 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateIdle
);
210 MP Initialize Library initialization.
212 This service will allocate AP reset vector and wakeup all APs to do APs
215 This service must be invoked before all other MP Initialize Library
218 @retval EFI_SUCCESS MP initialization succeeds.
219 @retval Others MP initialization fails.
224 MpInitLibInitialize (
228 UINT32 MaxLogicalProcessorNumber
;
230 MP_ASSEMBLY_ADDRESS_MAP AddressMap
;
232 UINT32 MonitorFilterSize
;
235 CPU_MP_DATA
*CpuMpData
;
237 UINT8
*MonitorBuffer
;
239 UINTN ApResetVectorSize
;
240 UINTN BackupBufferAddr
;
241 MaxLogicalProcessorNumber
= PcdGet32(PcdCpuMaxLogicalProcessorNumber
);
243 AsmGetAddressMap (&AddressMap
);
244 ApResetVectorSize
= AddressMap
.RendezvousFunnelSize
+ sizeof (MP_CPU_EXCHANGE_INFO
);
245 ApStackSize
= PcdGet32(PcdCpuApStackSize
);
246 ApLoopMode
= GetApLoopMode (&MonitorFilterSize
);
248 BufferSize
= ApStackSize
* MaxLogicalProcessorNumber
;
249 BufferSize
+= MonitorFilterSize
* MaxLogicalProcessorNumber
;
250 BufferSize
+= sizeof (CPU_MP_DATA
);
251 BufferSize
+= ApResetVectorSize
;
252 BufferSize
+= (sizeof (CPU_AP_DATA
) + sizeof (CPU_INFO_IN_HOB
))* MaxLogicalProcessorNumber
;
253 MpBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize
));
254 ASSERT (MpBuffer
!= NULL
);
255 ZeroMem (MpBuffer
, BufferSize
);
256 Buffer
= (UINTN
) MpBuffer
;
258 MonitorBuffer
= (UINT8
*) (Buffer
+ ApStackSize
* MaxLogicalProcessorNumber
);
259 BackupBufferAddr
= (UINTN
) MonitorBuffer
+ MonitorFilterSize
* MaxLogicalProcessorNumber
;
260 CpuMpData
= (CPU_MP_DATA
*) (BackupBufferAddr
+ ApResetVectorSize
);
261 CpuMpData
->Buffer
= Buffer
;
262 CpuMpData
->CpuApStackSize
= ApStackSize
;
263 CpuMpData
->BackupBuffer
= BackupBufferAddr
;
264 CpuMpData
->BackupBufferSize
= ApResetVectorSize
;
265 CpuMpData
->EndOfPeiFlag
= FALSE
;
266 CpuMpData
->WakeupBuffer
= (UINTN
) -1;
267 CpuMpData
->CpuCount
= 1;
268 CpuMpData
->BspNumber
= 0;
269 CpuMpData
->WaitEvent
= NULL
;
270 CpuMpData
->CpuData
= (CPU_AP_DATA
*) (CpuMpData
+ 1);
271 CpuMpData
->CpuInfoInHob
= (UINT64
) (UINTN
) (CpuMpData
->CpuData
+ MaxLogicalProcessorNumber
);
272 InitializeSpinLock(&CpuMpData
->MpLock
);
274 // Save BSP's Control registers to APs
276 SaveVolatileRegisters (&CpuMpData
->CpuData
[0].VolatileRegisters
);
278 // Set BSP basic information
280 InitializeApData (CpuMpData
, 0, 0);
282 // Save assembly code information
284 CopyMem (&CpuMpData
->AddressMap
, &AddressMap
, sizeof (MP_ASSEMBLY_ADDRESS_MAP
));
286 // Finally set AP loop mode
288 CpuMpData
->ApLoopMode
= ApLoopMode
;
289 DEBUG ((DEBUG_INFO
, "AP Loop Mode is %d\n", CpuMpData
->ApLoopMode
));
291 // Set up APs wakeup signal buffer
293 for (Index
= 0; Index
< MaxLogicalProcessorNumber
; Index
++) {
294 CpuMpData
->CpuData
[Index
].StartupApSignal
=
295 (UINT32
*)(MonitorBuffer
+ MonitorFilterSize
* Index
);
297 // Store BSP's MTRR setting
299 MtrrGetAllMtrrs (&CpuMpData
->MtrrTable
);
305 Gets detailed MP-related information on the requested processor at the
306 instant this call is made. This service may only be called from the BSP.
308 @param[in] ProcessorNumber The handle number of processor.
309 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
310 the requested processor is deposited.
311 @param[out] HealthData Return processor health data.
313 @retval EFI_SUCCESS Processor information was returned.
314 @retval EFI_DEVICE_ERROR The calling processor is an AP.
315 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
316 @retval EFI_NOT_FOUND The processor with the handle specified by
317 ProcessorNumber does not exist in the platform.
318 @retval EFI_NOT_READY MP Initialize Library is not initialized.
323 MpInitLibGetProcessorInfo (
324 IN UINTN ProcessorNumber
,
325 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
,
326 OUT EFI_HEALTH_FLAGS
*HealthData OPTIONAL
329 return EFI_UNSUPPORTED
;
332 This return the handle number for the calling processor. This service may be
333 called from the BSP and APs.
335 @param[out] ProcessorNumber Pointer to the handle number of AP.
336 The range is from 0 to the total number of
337 logical processors minus 1. The total number of
338 logical processors can be retrieved by
339 MpInitLibGetNumberOfProcessors().
341 @retval EFI_SUCCESS The current processor handle number was returned
343 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
344 @retval EFI_NOT_READY MP Initialize Library is not initialized.
350 OUT UINTN
*ProcessorNumber
353 return EFI_UNSUPPORTED
;
356 Retrieves the number of logical processor in the platform and the number of
357 those logical processors that are enabled on this boot. This service may only
358 be called from the BSP.
360 @param[out] NumberOfProcessors Pointer to the total number of logical
361 processors in the system, including the BSP
363 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
364 processors that exist in system, including
367 @retval EFI_SUCCESS The number of logical processors and enabled
368 logical processors was retrieved.
369 @retval EFI_DEVICE_ERROR The calling processor is an AP.
370 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
372 @retval EFI_NOT_READY MP Initialize Library is not initialized.
377 MpInitLibGetNumberOfProcessors (
378 OUT UINTN
*NumberOfProcessors
, OPTIONAL
379 OUT UINTN
*NumberOfEnabledProcessors OPTIONAL
382 return EFI_UNSUPPORTED
;