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