]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg/CpuDxe: implement Mp Protocol: WhoAmI()
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
CommitLineData
6022e28c
JJ
1/** @file\r
2 CPU DXE Module.\r
3\r
4 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
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 "CpuDxe.h"\r
16#include "CpuMp.h"\r
17\r
6a26a597
CF
18UINTN gMaxLogicalProcessorNumber;\r
19UINTN gApStackSize;\r
20\r
03673ae1
CF
21MP_SYSTEM_DATA mMpSystemData;\r
22\r
fab82c18
JJ
23VOID *mCommonStack = 0;\r
24VOID *mTopOfApCommonStack = 0;\r
6a26a597 25VOID *mApStackStart = 0;\r
fab82c18 26\r
003973d9
CF
27EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {\r
28 NULL, // GetNumberOfProcessors,\r
29 NULL, // GetProcessorInfo,\r
30 NULL, // StartupAllAPs,\r
31 NULL, // StartupThisAP,\r
32 NULL, // SwitchBSP,\r
33 NULL, // EnableDisableAP,\r
cfa2fac1 34 WhoAmI\r
003973d9
CF
35};\r
36\r
cfa2fac1
CF
37/**\r
38 This return the handle number for the calling processor. This service may be\r
39 called from the BSP and APs.\r
40\r
41 This service returns the processor handle number for the calling processor.\r
42 The returned value is in the range from 0 to the total number of logical\r
43 processors minus 1. The total number of logical processors can be retrieved\r
44 with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be\r
45 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER\r
46 is returned. Otherwise, the current processors handle number is returned in\r
47 ProcessorNumber, and EFI_SUCCESS is returned.\r
48\r
49 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
50 @param[out] ProcessorNumber The handle number of AP that is to become the new\r
51 BSP. The range is from 0 to the total number of\r
52 logical processors minus 1. The total number of\r
53 logical processors can be retrieved by\r
54 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().\r
55\r
56 @retval EFI_SUCCESS The current processor handle number was returned\r
57 in ProcessorNumber.\r
58 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.\r
59\r
60**/\r
61EFI_STATUS\r
62EFIAPI\r
63WhoAmI (\r
64 IN EFI_MP_SERVICES_PROTOCOL *This,\r
65 OUT UINTN *ProcessorNumber\r
66 )\r
67{\r
68 UINTN Index;\r
69 UINT32 ProcessorId;\r
70\r
71 if (ProcessorNumber == NULL) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
74\r
75 ProcessorId = GetApicId ();\r
76 for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {\r
77 if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {\r
78 break;\r
79 }\r
80 }\r
81\r
82 *ProcessorNumber = Index;\r
83 return EFI_SUCCESS;\r
84}\r
85\r
e343f8f7
CF
86/**\r
87 Application Processors do loop routine\r
88 after switch to its own stack.\r
89\r
90 @param Context1 A pointer to the context to pass into the function.\r
91 @param Context2 A pointer to the context to pass into the function.\r
92\r
93**/\r
94VOID\r
95ProcessorToIdleState (\r
96 IN VOID *Context1, OPTIONAL\r
97 IN VOID *Context2 OPTIONAL\r
98 )\r
99{\r
100 DEBUG ((DEBUG_INFO, "Ap apicid is %d\n", GetApicId ()));\r
101\r
102 AsmApDoneWithCommonStack ();\r
103\r
104 CpuSleep ();\r
105 CpuDeadLoop ();\r
106}\r
107\r
1535c888
JJ
108/**\r
109 Application Processor C code entry point.\r
110\r
111**/\r
112VOID\r
113EFIAPI\r
114ApEntryPointInC (\r
115 VOID\r
116 )\r
117{\r
03673ae1
CF
118 VOID* TopOfApStack;\r
119\r
120 FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);\r
121 TopOfApStack = (UINT8*)mApStackStart + gApStackSize;\r
122 mApStackStart = TopOfApStack;\r
123\r
124 mMpSystemData.NumberOfProcessors++;\r
e343f8f7
CF
125\r
126 SwitchStack (\r
127 (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,\r
128 NULL,\r
129 NULL,\r
03673ae1
CF
130 TopOfApStack);\r
131}\r
132\r
133/**\r
134 This function is called by all processors (both BSP and AP) once and collects MP related data.\r
135\r
136 @param Bsp TRUE if the CPU is BSP\r
137 @param ProcessorNumber The specific processor number\r
138\r
139 @retval EFI_SUCCESS Data for the processor collected and filled in\r
140\r
141**/\r
142EFI_STATUS\r
143FillInProcessorInformation (\r
144 IN BOOLEAN Bsp,\r
145 IN UINTN ProcessorNumber\r
146 )\r
147{\r
148 CPU_DATA_BLOCK *CpuData;\r
149 UINT32 ProcessorId;\r
150\r
151 CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
152 ProcessorId = GetApicId ();\r
153 CpuData->Info.ProcessorId = ProcessorId;\r
154 CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;\r
155 if (Bsp) {\r
156 CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;\r
157 }\r
158 CpuData->Info.Location.Package = ProcessorId;\r
159 CpuData->Info.Location.Core = 0;\r
160 CpuData->Info.Location.Thread = 0;\r
161 CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;\r
162\r
163 CpuData->Procedure = NULL;\r
164 CpuData->Parameter = NULL;\r
165 InitializeSpinLock (&CpuData->CpuDataLock);\r
166\r
167 return EFI_SUCCESS;\r
1535c888
JJ
168}\r
169\r
03673ae1
CF
170/**\r
171 Prepare the System Data.\r
172\r
173 @retval EFI_SUCCESS the System Data finished initilization.\r
174\r
175**/\r
176EFI_STATUS\r
177InitMpSystemData (\r
178 VOID\r
179 )\r
180{\r
181 ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));\r
182\r
183 mMpSystemData.NumberOfProcessors = 1;\r
184 mMpSystemData.NumberOfEnabledProcessors = 1;\r
185\r
186 mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);\r
187 ASSERT(mMpSystemData.CpuDatas != NULL);\r
188\r
189 //\r
190 // BSP\r
191 //\r
192 FillInProcessorInformation (TRUE, 0);\r
193\r
194 return EFI_SUCCESS;\r
195}\r
1535c888 196\r
6022e28c
JJ
197/**\r
198 Initialize Multi-processor support.\r
199\r
200**/\r
201VOID\r
202InitializeMpSupport (\r
203 VOID\r
204 )\r
205{\r
6a26a597
CF
206 gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
207 if (gMaxLogicalProcessorNumber < 1) {\r
208 DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));\r
209 return;\r
210 }\r
211\r
212 if (gMaxLogicalProcessorNumber == 1) {\r
213 return;\r
214 }\r
215\r
216 gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);\r
217 ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);\r
218\r
219 mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
220 ASSERT (mApStackStart != NULL);\r
6022e28c 221\r
6a26a597
CF
222 //\r
223 // the first buffer of stack size used for common stack, when the amount of AP\r
224 // more than 1, we should never free the common stack which maybe used for AP reset.\r
225 //\r
226 mCommonStack = mApStackStart;\r
227 mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;\r
228 mApStackStart = mTopOfApCommonStack;\r
229\r
03673ae1 230 InitMpSystemData ();\r
6a26a597 231\r
03673ae1 232 if (mMpSystemData.NumberOfProcessors == 1) {\r
6a26a597
CF
233 FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
234 return;\r
235 }\r
236\r
03673ae1
CF
237 if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {\r
238 FreePages (mApStackStart, EFI_SIZE_TO_PAGES (\r
239 (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *\r
240 gApStackSize));\r
6a26a597
CF
241 }\r
242}\r