]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg/CpuDxe: introduce MP_SYSTEM_DATA for Mp Service Protocol
[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 NULL // WhoAmI
35 };
36
37 /**
38 Application Processors do loop routine
39 after switch to its own stack.
40
41 @param Context1 A pointer to the context to pass into the function.
42 @param Context2 A pointer to the context to pass into the function.
43
44 **/
45 VOID
46 ProcessorToIdleState (
47 IN VOID *Context1, OPTIONAL
48 IN VOID *Context2 OPTIONAL
49 )
50 {
51 DEBUG ((DEBUG_INFO, "Ap apicid is %d\n", GetApicId ()));
52
53 AsmApDoneWithCommonStack ();
54
55 CpuSleep ();
56 CpuDeadLoop ();
57 }
58
59 /**
60 Application Processor C code entry point.
61
62 **/
63 VOID
64 EFIAPI
65 ApEntryPointInC (
66 VOID
67 )
68 {
69 VOID* TopOfApStack;
70
71 FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
72 TopOfApStack = (UINT8*)mApStackStart + gApStackSize;
73 mApStackStart = TopOfApStack;
74
75 mMpSystemData.NumberOfProcessors++;
76
77 SwitchStack (
78 (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
79 NULL,
80 NULL,
81 TopOfApStack);
82 }
83
84 /**
85 This function is called by all processors (both BSP and AP) once and collects MP related data.
86
87 @param Bsp TRUE if the CPU is BSP
88 @param ProcessorNumber The specific processor number
89
90 @retval EFI_SUCCESS Data for the processor collected and filled in
91
92 **/
93 EFI_STATUS
94 FillInProcessorInformation (
95 IN BOOLEAN Bsp,
96 IN UINTN ProcessorNumber
97 )
98 {
99 CPU_DATA_BLOCK *CpuData;
100 UINT32 ProcessorId;
101
102 CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
103 ProcessorId = GetApicId ();
104 CpuData->Info.ProcessorId = ProcessorId;
105 CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
106 if (Bsp) {
107 CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
108 }
109 CpuData->Info.Location.Package = ProcessorId;
110 CpuData->Info.Location.Core = 0;
111 CpuData->Info.Location.Thread = 0;
112 CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;
113
114 CpuData->Procedure = NULL;
115 CpuData->Parameter = NULL;
116 InitializeSpinLock (&CpuData->CpuDataLock);
117
118 return EFI_SUCCESS;
119 }
120
121 /**
122 Prepare the System Data.
123
124 @retval EFI_SUCCESS the System Data finished initilization.
125
126 **/
127 EFI_STATUS
128 InitMpSystemData (
129 VOID
130 )
131 {
132 ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));
133
134 mMpSystemData.NumberOfProcessors = 1;
135 mMpSystemData.NumberOfEnabledProcessors = 1;
136
137 mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);
138 ASSERT(mMpSystemData.CpuDatas != NULL);
139
140 //
141 // BSP
142 //
143 FillInProcessorInformation (TRUE, 0);
144
145 return EFI_SUCCESS;
146 }
147
148 /**
149 Initialize Multi-processor support.
150
151 **/
152 VOID
153 InitializeMpSupport (
154 VOID
155 )
156 {
157 gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
158 if (gMaxLogicalProcessorNumber < 1) {
159 DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
160 return;
161 }
162
163 if (gMaxLogicalProcessorNumber == 1) {
164 return;
165 }
166
167 gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);
168 ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);
169
170 mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
171 ASSERT (mApStackStart != NULL);
172
173 //
174 // the first buffer of stack size used for common stack, when the amount of AP
175 // more than 1, we should never free the common stack which maybe used for AP reset.
176 //
177 mCommonStack = mApStackStart;
178 mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;
179 mApStackStart = mTopOfApCommonStack;
180
181 InitMpSystemData ();
182
183 if (mMpSystemData.NumberOfProcessors == 1) {
184 FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
185 return;
186 }
187
188 if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
189 FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
190 (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *
191 gApStackSize));
192 }
193 }