If timeout expires before AP returns from Procedure, the AP should
be terminated, we introduce ResetApStackLess() to send init IPI
to let AP exit Procedurce and re-available.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com>
---
 UefiCpuPkg/CpuDxe/ApStartup.c | 19 ++++++++++++++++++-
 UefiCpuPkg/CpuDxe/CpuMp.c     | 36 +++++++++++++++++++++++++++++++-----
 UefiCpuPkg/CpuDxe/CpuMp.h     | 15 +++++++++++++++
 3 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/UefiCpuPkg/CpuDxe/ApStartup.c b/UefiCpuPkg/CpuDxe/ApStartup.c
index f985a5c..860b7c3 100644
--- a/UefiCpuPkg/CpuDxe/ApStartup.c
+++ b/UefiCpuPkg/CpuDxe/ApStartup.c
@@ -203,7 +203,7 @@ FreeApStartupCode (
   )
 {
   if (StartupCode != NULL) {
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(VOID *) StartupCode,
+    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)(VOID*) StartupCode,
                     EFI_SIZE_TO_PAGES (sizeof (*StartupCode)));
   }
 }
@@ -233,3 +233,20 @@ StartApsStackless (
   return EFI_SUCCESS;
 }
 
+/**
+  Resets the Application Processor and directs it to jump to the
+  specified routine.
+
+  The processor jumps to this code in flat mode, but the processor's
+  stack is not initialized.
+
+  @param ProcessorId           the AP of ProcessorId was reset
+**/
+VOID
+ResetApStackless (
+  IN UINT32 ProcessorId
+  )
+{
+  SendInitSipiSipi (ProcessorId,
+                    (UINT32)(UINTN)(VOID*) StartupCode);
+}
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c
index 428ea9e..96513e8 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.c
+++ b/UefiCpuPkg/CpuDxe/CpuMp.c
@@ -25,6 +25,7 @@ VOID *mCommonStack = 0;
 VOID *mTopOfApCommonStack = 0;
 VOID *mApStackStart = 0;
 
+BOOLEAN mAPsAlreadyInitFinished = FALSE;
 volatile BOOLEAN mStopCheckAllAPsStatus = TRUE;
 
 EFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {
@@ -1112,6 +1113,7 @@ ResetProcessorToIdleState (
   IN CPU_DATA_BLOCK  *CpuData
   )
 {
+  ResetApStackless(CpuData->Info.ProcessorId);
 }
 
 /**
@@ -1138,6 +1140,14 @@ ProcessorToIdleState (
 
   AsmApDoneWithCommonStack ();
 
+  //
+  // Avoid forcibly reset AP caused the AP State is not updated.
+  //
+  GetMpSpinLock (CpuData);
+  CpuData->State = CpuStateIdle;
+  CpuData->Procedure = NULL;
+  ReleaseMpSpinLock (CpuData);
+
   while (TRUE) {
     GetMpSpinLock (CpuData);
     ProcedureArgument = CpuData->Parameter;
@@ -1319,13 +1329,27 @@ ApEntryPointInC (
   VOID
   )
 {
-  VOID* TopOfApStack;
+  VOID*           TopOfApStack;
+  UINTN           ProcessorNumber;
 
-  FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
-  TopOfApStack  = (UINT8*)mApStackStart + gApStackSize;
-  mApStackStart = TopOfApStack;
+  if (!mAPsAlreadyInitFinished) {
+    FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
+    TopOfApStack  = (UINT8*)mApStackStart + gApStackSize;
+    mApStackStart = TopOfApStack;
 
-  mMpSystemData.NumberOfProcessors++;
+    //
+    // Store the Stack address, when reset the AP, We can found the original 
address.
+    //
+    mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = 
TopOfApStack;
+    mMpSystemData.NumberOfProcessors++;
+    mMpSystemData.NumberOfEnabledProcessors++;
+  } else {
+    WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
+    //
+    // Get the original stack address.
+    //
+    TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;
+  }
 
   SwitchStack (
     (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
@@ -1462,6 +1486,8 @@ InitializeMpSupport (
     return;
   }
 
+  mAPsAlreadyInitFinished = TRUE;
+
   if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
     FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
                                 (gMaxLogicalProcessorNumber - 
mMpSystemData.NumberOfProcessors) *
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h
index 40fda72..2533f4e 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.h
+++ b/UefiCpuPkg/CpuDxe/CpuMp.h
@@ -99,6 +99,7 @@ typedef struct {
   EFI_EVENT                      WaitEvent;
   BOOLEAN                        TimeoutActive;
   EFI_EVENT                      CheckThisAPEvent;
+  VOID                           *TopOfStack;
 } CPU_DATA_BLOCK;
 
 /**
@@ -622,5 +623,19 @@ FreeApStartupCode (
   VOID
   );
 
+/**
+  Resets the Application Processor and directs it to jump to the
+  specified routine.
+
+  The processor jumps to this code in flat mode, but the processor's
+  stack is not initialized.
+
+  @param ProcessorId           the AP of ProcessorId was reset
+**/
+VOID
+ResetApStackless (
+  IN UINT32 ProcessorId
+  );
+
 #endif // _CPU_MP_H_
 
-- 
1.9.3


------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to