All APs use the same common stack to initialization. after initialization, APs should switch to the stack of its own. the sequences are: 1. BSP detects AP count 2. BSP allocates AP stack spaces 3. AP grabs a lock 4. AP SwitchStack 5. AP releases lock
TODO: MSFT assembly code Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chen Fan <[email protected]> --- UefiCpuPkg/CpuDxe/CpuMp.c | 44 +++++++++++++++++++++++++++++++++++++- UefiCpuPkg/CpuDxe/CpuMp.h | 30 ++++++++++++++++++++++++++ UefiCpuPkg/CpuDxe/Ia32/MpAsm.nasm | 45 +++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuDxe/X64/MpAsm.nasm | 43 +++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index 5552307..82554c1 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -18,13 +18,15 @@ UINTN gApStackSize; UINTN gPollInterval = 100; // 100 microseconds -MP_SYSTEM_DATA mMpSystemData; +MP_SYSTEM_DATA mMpSystemData; +CPU_EXCHANGE_DATA mCpuExchangeData; VOID *mCommonStack = 0; VOID *mTopOfApCommonStack = 0; VOID *mApStackStart = 0; volatile UINTN mNumberOfProcessors; +volatile UINTN mIndexOfProcessors; volatile BOOLEAN mAllApsInitFinished = FALSE; EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { @@ -1197,6 +1199,33 @@ out: } /** + Application Processors do loop routine + after switch to its own stack. + +**/ +VOID +ProcessorToIdleState ( + VOID + ) +{ + CPU_DATA_BLOCK *CpuData; + + ASSERT (mIndexOfProcessors <= mNumberOfProcessors); + + // + // Update Ap's CpuData + // + CpuData = &mMpSystemData.CpuDatas[mIndexOfProcessors]; + CpuData->Info.ProcessorId = GetApicId (); + CpuData->Info.Location.Package = (UINT32) (mIndexOfProcessors); + CpuData->Info.Location.Core = 0; + CpuData->Info.Location.Thread = 0; + + mIndexOfProcessors++; + AsmApReleaseLock (); +} + +/** Application Processor C code entry point. **/ @@ -1220,6 +1249,11 @@ ApEntryPointInC ( CpuPause (); } + // + // Switch to the stack of the Ap's own + // + AsmApSwitchStack (); + CpuSleep (); } @@ -1283,6 +1317,7 @@ InitializeMpSupport ( ) { mNumberOfProcessors = 1; + mIndexOfProcessors = 1; if (mNumberOfProcessors == 1) { return; @@ -1295,6 +1330,13 @@ InitializeMpSupport ( mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES ((mNumberOfProcessors - 1) * gApStackSize)); ASSERT (mApStackStart != NULL); + // + // Save the Application Processors memory region and EntryPoint to a global variable, + // so when AP switch to new stack without stack, APs can get the parameters. + // + mCpuExchangeData.ApEntryPoint = (VOID *) (UINTN) ProcessorToIdleState; + mCpuExchangeData.StackStart = (UINTN) mApStackStart; + mMpSystemData.NumberOfProcessors = mNumberOfProcessors; mMpSystemData.NumberOfEnabledProcessors = mNumberOfProcessors; diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h index 54d4f12..9161be1 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.h +++ b/UefiCpuPkg/CpuDxe/CpuMp.h @@ -125,6 +125,36 @@ typedef struct { EFI_EVENT CheckAllAPsEvent; } MP_SYSTEM_DATA; +typedef struct { + VOID *ApEntryPoint; + UINTN StackStart; +} CPU_EXCHANGE_DATA; + +/** + Switch the common stack of the APs to its own stack which is + calculated by StackStart saved in CPU_EXCHANGE_DATA, and + then call the routine ApEntryPoint in CPU_EXCHANGE_DATA. + + there will hold a AP lock, so must call AsmApReleaseLock to + let others APs run. + +**/ +VOID +EFIAPI +AsmApSwitchStack ( + VOID + ); + +/** + Release the AP lock. + +**/ +VOID +EFIAPI +AsmApReleaseLock ( + VOID + ); + /** This service retrieves the number of logical processor in the platform and the number of those logical processors that are enabled on this boot. diff --git a/UefiCpuPkg/CpuDxe/Ia32/MpAsm.nasm b/UefiCpuPkg/CpuDxe/Ia32/MpAsm.nasm index c47cdce..ede4899 100644 --- a/UefiCpuPkg/CpuDxe/Ia32/MpAsm.nasm +++ b/UefiCpuPkg/CpuDxe/Ia32/MpAsm.nasm @@ -13,6 +13,9 @@ extern ASM_PFX(mTopOfApCommonStack) extern ASM_PFX(ApEntryPointInC) +extern ASM_PFX(mIndexOfProcessors) +extern ASM_PFX(mCpuExchangeData) +extern ASM_PFX(gApStackSize) SECTION .data @@ -66,3 +69,45 @@ ASM_PFX(AsmApDoneWithCommonStack): lock btc dword [ApStackLock], 0 ret +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmApSwitchStack ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmApSwitchStack) +ASM_PFX(AsmApSwitchStack): +AsmApAquireStackLock: +lock bts dword [ApStackLock], 0 + pause + jc AsmApAquireStackLock + + ; calculate the new stack top address of each AP's: + ; %rsp = NewStack + gApStackSize * mIndexOfProcessors + ; + mov eax, [ASM_PFX(mCpuExchangeData) + 04h] + mov edi, [ASM_PFX(gApStackSize)] + mov ebx, [ASM_PFX(mIndexOfProcessors)] + imul ebx, edi + add eax, ebx + + mov esp, eax + sub esp, 8 + + call [ASM_PFX(mCpuExchangeData)] + + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmApReleaseLock ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmApReleaseLock) +ASM_PFX(AsmApReleaseLock): +lock btc dword[ApStackLock], 0 + ret + diff --git a/UefiCpuPkg/CpuDxe/X64/MpAsm.nasm b/UefiCpuPkg/CpuDxe/X64/MpAsm.nasm index e3dc248..eedf0cf 100644 --- a/UefiCpuPkg/CpuDxe/X64/MpAsm.nasm +++ b/UefiCpuPkg/CpuDxe/X64/MpAsm.nasm @@ -13,6 +13,9 @@ extern ASM_PFX(mTopOfApCommonStack) extern ASM_PFX(ApEntryPointInC) +extern ASM_PFX(mIndexOfProcessors) +extern ASM_PFX(mCpuExchangeData) +extern ASM_PFX(gApStackSize) DEFAULT REL @@ -68,3 +71,43 @@ ASM_PFX(AsmApDoneWithCommonStack): lock btc dword [ApStackLock], 0 ret +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmApSwitchStack ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmApSwitchStack) +ASM_PFX(AsmApSwitchStack): +AsmApAquireStackLock: +lock bts dword [ApStackLock], 0 + pause + jc AsmApAquireStackLock + + ; calculate the new stack top address of each AP's: + ; %rsp = NewStack + gApStackSize * mIndexOfProcessors + ; + mov r9, [ASM_PFX(mCpuExchangeData) + 08h] + mov edi, [ASM_PFX(gApStackSize)] + mov ebx, [ASM_PFX(mIndexOfProcessors)] + imul ebx, edi + add r9, rbx + + lea rsp, [r9 - 20h] + call [ASM_PFX(mCpuExchangeData)] + + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmApReleaseLock ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmApReleaseLock) +ASM_PFX(AsmApReleaseLock): +lock btc dword[ApStackLock], 0 + ret + -- 1.9.3 ------------------------------------------------------------------------------ Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/edk2-devel
