]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Initialize CPU_AP_DATA for CPU APs
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
1 /** @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
17 /**
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 **/
24 CPU_STATE
25 GetApState (
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 **/
38 VOID
39 SetApState (
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 }
48
49 /**
50 Detect whether Mwait-monitor feature is supported.
51
52 @retval TRUE Mwait-monitor feature is supported.
53 @retval FALSE Mwait-monitor feature is not supported.
54 **/
55 BOOLEAN
56 IsMwaitSupport (
57 VOID
58 )
59 {
60 CPUID_VERSION_INFO_ECX VersionInfoEcx;
61
62 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);
63 return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;
64 }
65
66 /**
67 Get AP loop mode.
68
69 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
70
71 @return The AP loop mode.
72 **/
73 UINT8
74 GetApLoopMode (
75 OUT UINT32 *MonitorFilterSize
76 )
77 {
78 UINT8 ApLoopMode;
79 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;
80
81 ASSERT (MonitorFilterSize != NULL);
82
83 ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
84 ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
85 if (ApLoopMode == ApInMwaitLoop) {
86 if (!IsMwaitSupport ()) {
87 //
88 // If processor does not support MONITOR/MWAIT feature,
89 // force AP in Hlt-loop mode
90 //
91 ApLoopMode = ApInHltLoop;
92 }
93 }
94
95 if (ApLoopMode != ApInMwaitLoop) {
96 *MonitorFilterSize = sizeof (UINT32);
97 } else {
98 //
99 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
100 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
101 //
102 AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);
103 *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;
104 }
105
106 return ApLoopMode;
107 }
108 /*
109 Initialize CPU AP Data when AP is wakeup at the first time.
110
111 @param[in, out] CpuMpData Pointer to PEI CPU MP Data
112 @param[in] ProcessorNumber The handle number of processor
113 @param[in] BistData Processor BIST data
114
115 **/
116 VOID
117 InitializeApData (
118 IN OUT CPU_MP_DATA *CpuMpData,
119 IN UINTN ProcessorNumber,
120 IN UINT32 BistData
121 )
122 {
123 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
124 CpuMpData->CpuData[ProcessorNumber].Health = BistData;
125 CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
126 CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();
127 CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();
128 if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) {
129 //
130 // Set x2APIC mode if there are any logical processor reporting
131 // an Initial APIC ID of 255 or greater.
132 //
133 AcquireSpinLock(&CpuMpData->MpLock);
134 CpuMpData->X2ApicEnable = TRUE;
135 ReleaseSpinLock(&CpuMpData->MpLock);
136 }
137
138 InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);
139 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
140 }
141
142 /**
143 MP Initialize Library initialization.
144
145 This service will allocate AP reset vector and wakeup all APs to do APs
146 initialization.
147
148 This service must be invoked before all other MP Initialize Library
149 service are invoked.
150
151 @retval EFI_SUCCESS MP initialization succeeds.
152 @retval Others MP initialization fails.
153
154 **/
155 EFI_STATUS
156 EFIAPI
157 MpInitLibInitialize (
158 VOID
159 )
160 {
161 UINT32 MaxLogicalProcessorNumber;
162 UINT32 ApStackSize;
163 MP_ASSEMBLY_ADDRESS_MAP AddressMap;
164 UINTN BufferSize;
165 UINT32 MonitorFilterSize;
166 VOID *MpBuffer;
167 UINTN Buffer;
168 CPU_MP_DATA *CpuMpData;
169 UINT8 ApLoopMode;
170 UINT8 *MonitorBuffer;
171 UINTN Index;
172 UINTN ApResetVectorSize;
173 UINTN BackupBufferAddr;
174 MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);
175
176 AsmGetAddressMap (&AddressMap);
177 ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
178 ApStackSize = PcdGet32(PcdCpuApStackSize);
179 ApLoopMode = GetApLoopMode (&MonitorFilterSize);
180
181 BufferSize = ApStackSize * MaxLogicalProcessorNumber;
182 BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;
183 BufferSize += sizeof (CPU_MP_DATA);
184 BufferSize += ApResetVectorSize;
185 BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;
186 MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
187 ASSERT (MpBuffer != NULL);
188 ZeroMem (MpBuffer, BufferSize);
189 Buffer = (UINTN) MpBuffer;
190
191 MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);
192 BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;
193 CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);
194 CpuMpData->Buffer = Buffer;
195 CpuMpData->CpuApStackSize = ApStackSize;
196 CpuMpData->BackupBuffer = BackupBufferAddr;
197 CpuMpData->BackupBufferSize = ApResetVectorSize;
198 CpuMpData->EndOfPeiFlag = FALSE;
199 CpuMpData->WakeupBuffer = (UINTN) -1;
200 CpuMpData->CpuCount = 1;
201 CpuMpData->BspNumber = 0;
202 CpuMpData->WaitEvent = NULL;
203 CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);
204 CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);
205 InitializeSpinLock(&CpuMpData->MpLock);
206 //
207 // Set BSP basic information
208 //
209 InitializeApData (CpuMpData, 0, 0);
210 //
211 // Save assembly code information
212 //
213 CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
214 //
215 // Finally set AP loop mode
216 //
217 CpuMpData->ApLoopMode = ApLoopMode;
218 DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));
219 //
220 // Set up APs wakeup signal buffer
221 //
222 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
223 CpuMpData->CpuData[Index].StartupApSignal =
224 (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
225 }
226 // Store BSP's MTRR setting
227 //
228 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);
229
230 return EFI_SUCCESS;
231 }
232
233 /**
234 Gets detailed MP-related information on the requested processor at the
235 instant this call is made. This service may only be called from the BSP.
236
237 @param[in] ProcessorNumber The handle number of processor.
238 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
239 the requested processor is deposited.
240 @param[out] HealthData Return processor health data.
241
242 @retval EFI_SUCCESS Processor information was returned.
243 @retval EFI_DEVICE_ERROR The calling processor is an AP.
244 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
245 @retval EFI_NOT_FOUND The processor with the handle specified by
246 ProcessorNumber does not exist in the platform.
247 @retval EFI_NOT_READY MP Initialize Library is not initialized.
248
249 **/
250 EFI_STATUS
251 EFIAPI
252 MpInitLibGetProcessorInfo (
253 IN UINTN ProcessorNumber,
254 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
255 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
256 )
257 {
258 return EFI_UNSUPPORTED;
259 }
260 /**
261 This return the handle number for the calling processor. This service may be
262 called from the BSP and APs.
263
264 @param[out] ProcessorNumber Pointer to the handle number of AP.
265 The range is from 0 to the total number of
266 logical processors minus 1. The total number of
267 logical processors can be retrieved by
268 MpInitLibGetNumberOfProcessors().
269
270 @retval EFI_SUCCESS The current processor handle number was returned
271 in ProcessorNumber.
272 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
273 @retval EFI_NOT_READY MP Initialize Library is not initialized.
274
275 **/
276 EFI_STATUS
277 EFIAPI
278 MpInitLibWhoAmI (
279 OUT UINTN *ProcessorNumber
280 )
281 {
282 return EFI_UNSUPPORTED;
283 }
284 /**
285 Retrieves the number of logical processor in the platform and the number of
286 those logical processors that are enabled on this boot. This service may only
287 be called from the BSP.
288
289 @param[out] NumberOfProcessors Pointer to the total number of logical
290 processors in the system, including the BSP
291 and disabled APs.
292 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
293 processors that exist in system, including
294 the BSP.
295
296 @retval EFI_SUCCESS The number of logical processors and enabled
297 logical processors was retrieved.
298 @retval EFI_DEVICE_ERROR The calling processor is an AP.
299 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
300 is NULL.
301 @retval EFI_NOT_READY MP Initialize Library is not initialized.
302
303 **/
304 EFI_STATUS
305 EFIAPI
306 MpInitLibGetNumberOfProcessors (
307 OUT UINTN *NumberOfProcessors, OPTIONAL
308 OUT UINTN *NumberOfEnabledProcessors OPTIONAL
309 )
310 {
311 return EFI_UNSUPPORTED;
312 }