2 CPU PEI Module installs CPU Multiple Processor PPI.
4 Copyright (c) 2015, 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
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.
18 // Global Descriptor Table (GDT)
20 GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries
[] = {
21 /* selector { Global Segment Descriptor } */
22 /* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor
23 /* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor
24 /* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor
25 /* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
26 /* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor
27 /* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
28 /* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
29 /* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor
30 /* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
36 GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt
= {
37 sizeof (mGdtEntries
) - 1,
42 Get available system memory below 1MB by specified size.
44 @param WakeupBufferSize Wakeup buffer size required
46 @retval other Return wakeup buffer address below 1MB.
47 @retval -1 Cannot find free memory below 1MB.
51 IN UINTN WakeupBufferSize
54 EFI_PEI_HOB_POINTERS Hob
;
55 UINTN WakeupBufferStart
;
56 UINTN WakeupBufferEnd
;
59 // Get the HOB list for processing
61 Hob
.Raw
= GetHobList ();
64 // Collect memory ranges
66 while (!END_OF_HOB_LIST (Hob
)) {
67 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
68 if ((Hob
.ResourceDescriptor
->PhysicalStart
< BASE_1MB
) &&
69 (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
70 ((Hob
.ResourceDescriptor
->ResourceAttribute
&
71 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
|
72 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
|
73 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
77 // Need memory under 1MB to be collected here
79 WakeupBufferEnd
= (UINTN
) (Hob
.ResourceDescriptor
->PhysicalStart
+ Hob
.ResourceDescriptor
->ResourceLength
);
80 if (WakeupBufferEnd
> BASE_1MB
) {
82 // Wakeup buffer should be under 1MB
84 WakeupBufferEnd
= BASE_1MB
;
87 // Wakeup buffer should be aligned on 4KB
89 WakeupBufferStart
= (WakeupBufferEnd
- WakeupBufferSize
) & ~(SIZE_4KB
- 1);
90 if (WakeupBufferStart
< Hob
.ResourceDescriptor
->PhysicalStart
) {
94 // Create a memory allocation HOB.
96 BuildMemoryAllocationHob (
101 return WakeupBufferStart
;
107 Hob
.Raw
= GET_NEXT_HOB (Hob
);
114 Get available system memory below 1MB by specified size.
116 @param PeiCpuMpData Pointer to PEI CPU MP Data
119 BackupAndPrepareWakeupBuffer(
120 IN PEI_CPU_MP_DATA
*PeiCpuMpData
124 (VOID
*) PeiCpuMpData
->BackupBuffer
,
125 (VOID
*) PeiCpuMpData
->WakeupBuffer
,
126 PeiCpuMpData
->BackupBufferSize
129 (VOID
*) PeiCpuMpData
->WakeupBuffer
,
130 (VOID
*) PeiCpuMpData
->AddressMap
.RendezvousFunnelAddress
,
131 PeiCpuMpData
->AddressMap
.RendezvousFunnelSize
135 Prepare for AP wakeup buffer and copy AP reset code into it.
137 Get wakeup buffer below 1MB. Allocate memory for CPU MP Data and APs Stack.
139 @return Pointer to PEI CPU MP Data
142 PrepareAPStartupVector (
148 PEI_CPU_MP_DATA
*PeiCpuMpData
;
149 EFI_PHYSICAL_ADDRESS Buffer
;
152 UINTN WakeupBufferSize
;
153 MP_ASSEMBLY_ADDRESS_MAP AddressMap
;
155 AsmGetAddressMap (&AddressMap
);
156 WakeupBufferSize
= AddressMap
.RendezvousFunnelSize
+ sizeof (MP_CPU_EXCHANGE_INFO
);
157 WakeupBuffer
= GetWakeupBuffer ((WakeupBufferSize
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1));
158 DEBUG ((EFI_D_INFO
, "CpuMpPei: WakeupBuffer = 0x%x\n", WakeupBuffer
));
161 // Allocate Pages for APs stack, CPU MP Data and backup buffer for wakeup buffer
163 MaxCpuCount
= PcdGet32(PcdCpuMaxLogicalProcessorNumber
);
164 BufferSize
= PcdGet32 (PcdCpuApStackSize
) * MaxCpuCount
+ sizeof (PEI_CPU_MP_DATA
)
165 + WakeupBufferSize
+ sizeof (PEI_CPU_DATA
) * MaxCpuCount
;
166 Status
= PeiServicesAllocatePages (
168 EFI_SIZE_TO_PAGES (BufferSize
),
171 ASSERT_EFI_ERROR (Status
);
173 PeiCpuMpData
= (PEI_CPU_MP_DATA
*) (UINTN
) (Buffer
+ PcdGet32 (PcdCpuApStackSize
) * MaxCpuCount
);
174 PeiCpuMpData
->Buffer
= (UINTN
) Buffer
;
175 PeiCpuMpData
->CpuApStackSize
= PcdGet32 (PcdCpuApStackSize
);
176 PeiCpuMpData
->WakeupBuffer
= WakeupBuffer
;
177 PeiCpuMpData
->BackupBuffer
= (UINTN
)PeiCpuMpData
+ sizeof (PEI_CPU_MP_DATA
);
178 PeiCpuMpData
->BackupBufferSize
= WakeupBufferSize
;
179 PeiCpuMpData
->MpCpuExchangeInfo
= (MP_CPU_EXCHANGE_INFO
*) (UINTN
) (WakeupBuffer
+ AddressMap
.RendezvousFunnelSize
);
181 PeiCpuMpData
->CpuCount
= 1;
182 PeiCpuMpData
->BspNumber
= 0;
183 PeiCpuMpData
->CpuData
= (PEI_CPU_DATA
*) (PeiCpuMpData
->MpCpuExchangeInfo
+ 1);
184 PeiCpuMpData
->CpuData
[0].ApicId
= GetInitialApicId ();
185 PeiCpuMpData
->CpuData
[0].Health
.Uint32
= 0;
186 CopyMem (&PeiCpuMpData
->AddressMap
, &AddressMap
, sizeof (MP_ASSEMBLY_ADDRESS_MAP
));
189 // Backup original data and copy AP reset code in it
191 BackupAndPrepareWakeupBuffer(PeiCpuMpData
);
196 The Entry point of the MP CPU PEIM.
198 This function will wakeup APs and collect CPU AP count and install the
201 @param FileHandle Handle of the file being invoked.
202 @param PeiServices Describes the list of possible PEI Services.
204 @retval EFI_SUCCESS MpServicePpi is installed successfully.
210 IN EFI_PEI_FILE_HANDLE FileHandle
,
211 IN CONST EFI_PEI_SERVICES
**PeiServices
215 PEI_CPU_MP_DATA
*PeiCpuMpData
;
218 // Load new GDT table on BSP
220 AsmInitializeGdt (&mGdt
);
222 // Get wakeup buffer and copy AP reset code in it
224 PeiCpuMpData
= PrepareAPStartupVector ();