mov cr0, eax\r
\r
SkipEnableExecuteDisable:\r
+ mov edi, esi\r
+ add edi, InitFlagLocation\r
+ cmp dword [edi], 1 ; 1 == ApInitConfig\r
+ jnz GetApicId\r
\r
+ ; AP init\r
mov edi, esi\r
add edi, LockLocation\r
mov eax, NotVacantFlag\r
cmp eax, NotVacantFlag\r
jz TestLock\r
\r
- mov edi, esi\r
- add edi, NumApsExecutingLocation\r
- inc dword [edi]\r
- mov ebx, [edi]\r
+ mov ecx, esi\r
+ add ecx, NumApsExecutingLocation\r
+ inc dword [ecx]\r
+ mov ebx, [ecx]\r
+\r
+Releaselock:\r
+ mov eax, VacantFlag\r
+ xchg [edi], eax\r
\r
-ProgramStack:\r
mov edi, esi\r
add edi, StackSizeLocation\r
mov eax, [edi]\r
+ mov ecx, ebx\r
+ inc ecx\r
+ mul ecx ; EAX = StackSize * (CpuNumber + 1)\r
mov edi, esi\r
add edi, StackStartAddressLocation\r
add eax, [edi]\r
mov esp, eax\r
- mov [edi], eax\r
+ jmp CProcedureInvoke\r
+\r
+GetApicId:\r
+ mov eax, 0\r
+ cpuid\r
+ cmp eax, 0bh\r
+ jnb X2Apic\r
+ ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
+ mov eax, 1\r
+ cpuid\r
+ shr ebx, 24\r
+ mov edx, ebx\r
+ jmp GetProcessorNumber\r
+\r
+X2Apic:\r
+ ; Processor is x2APIC capable, so get 32-bit x2APIC ID\r
+ mov eax, 0bh\r
+ xor ecx, ecx\r
+ cpuid \r
+ ; edx save x2APIC ID\r
+ \r
+GetProcessorNumber:\r
+ ;\r
+ ; Get processor number for this AP\r
+ ; Note that BSP may become an AP due to SwitchBsp()\r
+ ;\r
+ xor ebx, ebx\r
+ lea eax, [esi + CpuInfoLocation]\r
+ mov edi, [eax]\r
\r
-Releaselock:\r
- mov eax, VacantFlag\r
- mov edi, esi\r
- add edi, LockLocation\r
- xchg [edi], eax\r
+GetNextProcNumber:\r
+ cmp [edi], edx ; APIC ID match?\r
+ jz ProgramStack\r
+ add edi, 16\r
+ inc ebx\r
+ jmp GetNextProcNumber \r
\r
+ProgramStack:\r
+ mov esp, [edi + 12]\r
+ \r
CProcedureInvoke:\r
push ebp ; push BIST data at top of AP stack\r
xor ebp, ebp ; clear ebp for call stack trace\r
InitializeApData (\r
IN OUT CPU_MP_DATA *CpuMpData,\r
IN UINTN ProcessorNumber,\r
- IN UINT32 BistData\r
+ IN UINT32 BistData,\r
+ IN UINTN ApTopOfStack\r
)\r
{\r
CPU_INFO_IN_HOB *CpuInfoInHob;\r
CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();\r
CpuInfoInHob[ProcessorNumber].Health = BistData;\r
+ CpuInfoInHob[ProcessorNumber].ApTopOfStack = (UINT32) ApTopOfStack;\r
\r
CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;\r
CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
UINT32 BistData;\r
volatile UINT32 *ApStartupSignalBuffer;\r
CPU_INFO_IN_HOB *CpuInfoInHob;\r
+ UINTN ApTopOfStack;\r
\r
//\r
// AP finished assembly code and begin to execute C code\r
//\r
// This is first time AP wakeup, get BIST information from AP stack\r
//\r
- BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));\r
+ ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;\r
+ BistData = *(UINT32 *) (ApTopOfStack - sizeof (UINTN));\r
//\r
// Do some AP initialize sync\r
//\r
// Sync BSP's Control registers to APs\r
//\r
RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
- InitializeApData (CpuMpData, ProcessorNumber, BistData);\r
+ InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);\r
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
} else {\r
//\r
//\r
// Set BSP basic information\r
//\r
- InitializeApData (CpuMpData, 0, 0);\r
+ InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer);\r
//\r
// Save assembly code information\r
//\r
UINT32 InitialApicId;\r
UINT32 ApicId;\r
UINT32 Health;\r
+ UINT32 ApTopOfStack;\r
} CPU_INFO_IN_HOB;\r
\r
//\r
mov es, ax\r
mov ss, ax\r
\r
+ mov esi, ebx\r
+ lea edi, [esi + InitFlagLocation]\r
+ cmp qword [edi], 1 ; ApInitConfig\r
+ jnz GetApicId\r
+\r
+ ; AP init\r
mov esi, ebx\r
mov edi, esi\r
add edi, LockLocation\r
cmp rax, NotVacantFlag\r
jz TestLock\r
\r
- mov edi, esi\r
- add edi, NumApsExecutingLocation\r
- inc dword [edi]\r
- mov ebx, [edi]\r
+ lea ecx, [esi + InitFlagLocation]\r
+ inc dword [ecx]\r
+ mov ebx, [ecx]\r
\r
-ProgramStack:\r
+Releaselock:\r
+ mov rax, VacantFlag\r
+ xchg qword [edi], rax\r
+ ; program stack\r
mov edi, esi\r
add edi, StackSizeLocation\r
- mov rax, qword [edi]\r
+ mov eax, dword [edi]\r
+ mov ecx, ebx\r
+ inc ecx\r
+ mul ecx ; EAX = StackSize * (CpuNumber + 1)\r
mov edi, esi\r
add edi, StackStartAddressLocation\r
add rax, qword [edi]\r
mov rsp, rax\r
- mov qword [edi], rax\r
+ jmp CProcedureInvoke\r
+\r
+GetApicId:\r
+ mov eax, 0\r
+ cpuid\r
+ cmp eax, 0bh\r
+ jnb X2Apic\r
+ ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
+ mov eax, 1\r
+ cpuid\r
+ shr ebx, 24\r
+ mov edx, ebx\r
+ jmp GetProcessorNumber\r
+\r
+X2Apic:\r
+ ; Processor is x2APIC capable, so get 32-bit x2APIC ID\r
+ mov eax, 0bh\r
+ xor ecx, ecx\r
+ cpuid \r
+ ; edx save x2APIC ID\r
+ \r
+GetProcessorNumber:\r
+ ;\r
+ ; Get processor number for this AP\r
+ ; Note that BSP may become an AP due to SwitchBsp()\r
+ ;\r
+ xor ebx, ebx\r
+ lea eax, [esi + CpuInfoLocation]\r
+ mov edi, [eax]\r
\r
-Releaselock:\r
- mov rax, VacantFlag\r
- mov edi, esi\r
- add edi, LockLocation\r
- xchg qword [edi], rax\r
+GetNextProcNumber:\r
+ cmp dword [edi], edx ; APIC ID match?\r
+ jz ProgramStack\r
+ add edi, 16\r
+ inc ebx\r
+ jmp GetNextProcNumber \r
+\r
+ProgramStack:\r
+ xor rsp, rsp\r
+ mov esp, dword [edi + 12]\r
\r
CProcedureInvoke:\r
push rbp ; Push BIST data at top of AP stack\r