blob: 7384f5d0d2b6086528f064806286a9cc9a9de717 [file] [log] [blame]
Jeff Fan3e8ad6b2016-07-20 21:56:58 +08001/** @file
2 CPU MP Initialize Library common 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 "MpLib.h"
16
Jeff Fan03a1a922016-07-20 23:43:29 +080017/**
18 Get the Application Processors state.
19
20 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
21
22 @return The AP status
23**/
24CPU_STATE
25GetApState (
26 IN CPU_AP_DATA *CpuData
27 )
28{
29 return CpuData->State;
30}
31
32/**
33 Set the Application Processors state.
34
35 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
36 @param[in] State The AP status
37**/
38VOID
39SetApState (
40 IN CPU_AP_DATA *CpuData,
41 IN CPU_STATE State
42 )
43{
44 AcquireSpinLock (&CpuData->ApLock);
45 CpuData->State = State;
46 ReleaseSpinLock (&CpuData->ApLock);
47}
Jeff Fan3e8ad6b2016-07-20 21:56:58 +080048
49/**
Jeff Fan68cb9332016-07-20 23:47:59 +080050 Save the volatile registers required to be restored following INIT IPI.
51
52 @param[out] VolatileRegisters Returns buffer saved the volatile resisters
53**/
54VOID
55SaveVolatileRegisters (
56 OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
57 )
58{
59 CPUID_VERSION_INFO_EDX VersionInfoEdx;
60
61 VolatileRegisters->Cr0 = AsmReadCr0 ();
62 VolatileRegisters->Cr3 = AsmReadCr3 ();
63 VolatileRegisters->Cr4 = AsmReadCr4 ();
64
65 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
66 if (VersionInfoEdx.Bits.DE != 0) {
67 //
68 // If processor supports Debugging Extensions feature
69 // by CPUID.[EAX=01H]:EDX.BIT2
70 //
71 VolatileRegisters->Dr0 = AsmReadDr0 ();
72 VolatileRegisters->Dr1 = AsmReadDr1 ();
73 VolatileRegisters->Dr2 = AsmReadDr2 ();
74 VolatileRegisters->Dr3 = AsmReadDr3 ();
75 VolatileRegisters->Dr6 = AsmReadDr6 ();
76 VolatileRegisters->Dr7 = AsmReadDr7 ();
77 }
78}
79
80/**
81 Restore the volatile registers following INIT IPI.
82
83 @param[in] VolatileRegisters Pointer to volatile resisters
84 @param[in] IsRestoreDr TRUE: Restore DRx if supported
85 FALSE: Do not restore DRx
86**/
87VOID
88RestoreVolatileRegisters (
89 IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
90 IN BOOLEAN IsRestoreDr
91 )
92{
93 CPUID_VERSION_INFO_EDX VersionInfoEdx;
94
95 AsmWriteCr0 (VolatileRegisters->Cr0);
96 AsmWriteCr3 (VolatileRegisters->Cr3);
97 AsmWriteCr4 (VolatileRegisters->Cr4);
98
99 if (IsRestoreDr) {
100 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
101 if (VersionInfoEdx.Bits.DE != 0) {
102 //
103 // If processor supports Debugging Extensions feature
104 // by CPUID.[EAX=01H]:EDX.BIT2
105 //
106 AsmWriteDr0 (VolatileRegisters->Dr0);
107 AsmWriteDr1 (VolatileRegisters->Dr1);
108 AsmWriteDr2 (VolatileRegisters->Dr2);
109 AsmWriteDr3 (VolatileRegisters->Dr3);
110 AsmWriteDr6 (VolatileRegisters->Dr6);
111 AsmWriteDr7 (VolatileRegisters->Dr7);
112 }
113 }
114}
115
116/**
Jeff Fan9ebcf0f2016-07-20 23:32:17 +0800117 Detect whether Mwait-monitor feature is supported.
118
119 @retval TRUE Mwait-monitor feature is supported.
120 @retval FALSE Mwait-monitor feature is not supported.
121**/
122BOOLEAN
123IsMwaitSupport (
124 VOID
125 )
126{
127 CPUID_VERSION_INFO_ECX VersionInfoEcx;
128
129 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);
130 return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;
131}
132
133/**
134 Get AP loop mode.
135
136 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
137
138 @return The AP loop mode.
139**/
140UINT8
141GetApLoopMode (
142 OUT UINT32 *MonitorFilterSize
143 )
144{
145 UINT8 ApLoopMode;
146 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;
147
148 ASSERT (MonitorFilterSize != NULL);
149
150 ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
151 ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
152 if (ApLoopMode == ApInMwaitLoop) {
153 if (!IsMwaitSupport ()) {
154 //
155 // If processor does not support MONITOR/MWAIT feature,
156 // force AP in Hlt-loop mode
157 //
158 ApLoopMode = ApInHltLoop;
159 }
160 }
161
162 if (ApLoopMode != ApInMwaitLoop) {
163 *MonitorFilterSize = sizeof (UINT32);
164 } else {
165 //
166 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
167 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
168 //
169 AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);
170 *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;
171 }
172
173 return ApLoopMode;
174}
Jeff Fan03a1a922016-07-20 23:43:29 +0800175/*
176 Initialize CPU AP Data when AP is wakeup at the first time.
177
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
181
182**/
183VOID
184InitializeApData (
185 IN OUT CPU_MP_DATA *CpuMpData,
186 IN UINTN ProcessorNumber,
187 IN UINT32 BistData
188 )
189{
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) {
196 //
197 // Set x2APIC mode if there are any logical processor reporting
198 // an Initial APIC ID of 255 or greater.
199 //
200 AcquireSpinLock(&CpuMpData->MpLock);
201 CpuMpData->X2ApicEnable = TRUE;
202 ReleaseSpinLock(&CpuMpData->MpLock);
203 }
204
205 InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);
206 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
207}
208
Jeff Fan9ebcf0f2016-07-20 23:32:17 +0800209/**
Jeff Fan3e8ad6b2016-07-20 21:56:58 +0800210 MP Initialize Library initialization.
211
212 This service will allocate AP reset vector and wakeup all APs to do APs
213 initialization.
214
215 This service must be invoked before all other MP Initialize Library
216 service are invoked.
217
218 @retval EFI_SUCCESS MP initialization succeeds.
219 @retval Others MP initialization fails.
220
221**/
222EFI_STATUS
223EFIAPI
224MpInitLibInitialize (
225 VOID
226 )
227{
Jeff Fane59f8f62016-07-20 23:33:25 +0800228 UINT32 MaxLogicalProcessorNumber;
229 UINT32 ApStackSize;
Jeff Fanf7f85d82016-07-20 22:56:09 +0800230 MP_ASSEMBLY_ADDRESS_MAP AddressMap;
Jeff Fane59f8f62016-07-20 23:33:25 +0800231 UINTN BufferSize;
Jeff Fan9ebcf0f2016-07-20 23:32:17 +0800232 UINT32 MonitorFilterSize;
Jeff Fane59f8f62016-07-20 23:33:25 +0800233 VOID *MpBuffer;
234 UINTN Buffer;
235 CPU_MP_DATA *CpuMpData;
Jeff Fan9ebcf0f2016-07-20 23:32:17 +0800236 UINT8 ApLoopMode;
Jeff Fane59f8f62016-07-20 23:33:25 +0800237 UINT8 *MonitorBuffer;
Jeff Fan03a1a922016-07-20 23:43:29 +0800238 UINTN Index;
Jeff Fanf7f85d82016-07-20 22:56:09 +0800239 UINTN ApResetVectorSize;
Jeff Fane59f8f62016-07-20 23:33:25 +0800240 UINTN BackupBufferAddr;
241 MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);
Jeff Fanf7f85d82016-07-20 22:56:09 +0800242
243 AsmGetAddressMap (&AddressMap);
244 ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
Jeff Fane59f8f62016-07-20 23:33:25 +0800245 ApStackSize = PcdGet32(PcdCpuApStackSize);
Jeff Fan9ebcf0f2016-07-20 23:32:17 +0800246 ApLoopMode = GetApLoopMode (&MonitorFilterSize);
247
Jeff Fane59f8f62016-07-20 23:33:25 +0800248 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;
257
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);
273 //
Jeff Fan68cb9332016-07-20 23:47:59 +0800274 // Save BSP's Control registers to APs
275 //
276 SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);
277 //
Jeff Fan03a1a922016-07-20 23:43:29 +0800278 // Set BSP basic information
279 //
280 InitializeApData (CpuMpData, 0, 0);
281 //
Jeff Fane59f8f62016-07-20 23:33:25 +0800282 // Save assembly code information
283 //
284 CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
285 //
286 // Finally set AP loop mode
287 //
288 CpuMpData->ApLoopMode = ApLoopMode;
289 DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));
290 //
Jeff Fan03a1a922016-07-20 23:43:29 +0800291 // Set up APs wakeup signal buffer
292 //
293 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
294 CpuMpData->CpuData[Index].StartupApSignal =
295 (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
296 }
Jeff Fan94f63c72016-07-20 23:49:35 +0800297 //
298 // Load Microcode on BSP
299 //
300 MicrocodeDetect (CpuMpData);
301 //
Jeff Fane59f8f62016-07-20 23:33:25 +0800302 // Store BSP's MTRR setting
303 //
304 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);
305
Jeff Fanf7f85d82016-07-20 22:56:09 +0800306 return EFI_SUCCESS;
Jeff Fan3e8ad6b2016-07-20 21:56:58 +0800307}
308
309/**
310 Gets detailed MP-related information on the requested processor at the
311 instant this call is made. This service may only be called from the BSP.
312
313 @param[in] ProcessorNumber The handle number of processor.
314 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
315 the requested processor is deposited.
316 @param[out] HealthData Return processor health data.
317
318 @retval EFI_SUCCESS Processor information was returned.
319 @retval EFI_DEVICE_ERROR The calling processor is an AP.
320 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
321 @retval EFI_NOT_FOUND The processor with the handle specified by
322 ProcessorNumber does not exist in the platform.
323 @retval EFI_NOT_READY MP Initialize Library is not initialized.
324
325**/
326EFI_STATUS
327EFIAPI
328MpInitLibGetProcessorInfo (
329 IN UINTN ProcessorNumber,
330 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
331 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
332 )
333{
334 return EFI_UNSUPPORTED;
335}
336/**
337 This return the handle number for the calling processor. This service may be
338 called from the BSP and APs.
339
340 @param[out] ProcessorNumber Pointer to the handle number of AP.
341 The range is from 0 to the total number of
342 logical processors minus 1. The total number of
343 logical processors can be retrieved by
344 MpInitLibGetNumberOfProcessors().
345
346 @retval EFI_SUCCESS The current processor handle number was returned
347 in ProcessorNumber.
348 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
349 @retval EFI_NOT_READY MP Initialize Library is not initialized.
350
351**/
352EFI_STATUS
353EFIAPI
354MpInitLibWhoAmI (
355 OUT UINTN *ProcessorNumber
356 )
357{
358 return EFI_UNSUPPORTED;
359}
360/**
361 Retrieves the number of logical processor in the platform and the number of
362 those logical processors that are enabled on this boot. This service may only
363 be called from the BSP.
364
365 @param[out] NumberOfProcessors Pointer to the total number of logical
366 processors in the system, including the BSP
367 and disabled APs.
368 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
369 processors that exist in system, including
370 the BSP.
371
372 @retval EFI_SUCCESS The number of logical processors and enabled
373 logical processors was retrieved.
374 @retval EFI_DEVICE_ERROR The calling processor is an AP.
375 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
376 is NULL.
377 @retval EFI_NOT_READY MP Initialize Library is not initialized.
378
379**/
380EFI_STATUS
381EFIAPI
382MpInitLibGetNumberOfProcessors (
383 OUT UINTN *NumberOfProcessors, OPTIONAL
384 OUT UINTN *NumberOfEnabledProcessors OPTIONAL
385 )
386{
387 return EFI_UNSUPPORTED;
388}