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

Reply via email to