Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chen Fan <[email protected]>
---
 UefiCpuPkg/CpuDxe/CpuDxe.inf |   1 +
 UefiCpuPkg/CpuDxe/CpuMp.c    | 174 ++++++++++++++++++++++++++++++++++++++++++-
 UefiCpuPkg/CpuDxe/CpuMp.h    |  50 +++++++++++++
 UefiCpuPkg/UefiCpuPkg.dsc    |   1 +
 4 files changed, 225 insertions(+), 1 deletion(-)

diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf
index f73b845..ed90ff2 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.inf
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -41,6 +41,7 @@
   UefiCpuLib
   UefiLib
   CpuExceptionHandlerLib
+  SynchronizationLib
 
 [Sources]
   ApStartup.c
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c
index b28783e..04f625a 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.c
+++ b/UefiCpuPkg/CpuDxe/CpuMp.c
@@ -36,7 +36,7 @@ EFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {
   NULL, // StartupAllAps,
   NULL, // StartupThisAP,
   NULL, // SwitchBSP,
-  NULL, // EnableDisableAP,
+  EnableDisableAP,
   WhoAmI
 };
 
@@ -61,6 +61,88 @@ IsBSP (
   return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE;
 }
 
+/**
+  Get the Application Processors state.
+
+  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified AP
+
+  @retval  CPU_STATE  the AP status
+
+**/
+CPU_STATE
+GetApState (
+  IN  CPU_DATA_BLOCK  *CpuData
+  )
+{
+  CPU_STATE State;
+
+  AcquireSpinLock (&CpuData->CpuDataLock);
+  State = CpuData->State;
+  ReleaseSpinLock (&CpuData->CpuDataLock);
+
+  return State;
+}
+
+/**
+  Check the Application Processors Status whether contains the Flags.
+
+  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
+  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION 
+
+  @retval    TRUE     the AP status includes the StatusFlag
+  @retval    FALSE    the AP status excludes the StatusFlag
+
+**/
+BOOLEAN
+TestCpuStatusFlag (
+  IN  CPU_DATA_BLOCK  *CpuData,
+  IN  UINT32          Flags
+  )
+{
+  UINT32 Ret;
+
+  AcquireSpinLock (&CpuData->CpuDataLock);
+  Ret = CpuData->Info.StatusFlag & Flags;
+  ReleaseSpinLock (&CpuData->CpuDataLock);
+
+  return !!(Ret);
+}
+
+/**
+  Bitwise-Or of the Application Processors Status with the Flags.
+
+  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
+  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION 
+
+**/
+VOID
+CpuStatusFlagOr (
+  IN  CPU_DATA_BLOCK  *CpuData,
+  IN  UINT32          Flags
+  )
+{
+  AcquireSpinLock (&CpuData->CpuDataLock);
+  CpuData->Info.StatusFlag |= Flags;
+  ReleaseSpinLock (&CpuData->CpuDataLock);
+}
+
+/**
+  Bitwise-AndNot of the Application Processors Status with the Flags.
+
+  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
+  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION 
+
+**/
+VOID
+CpuStatusFlagAndNot (
+  IN  CPU_DATA_BLOCK  *CpuData,
+  IN  UINT32          Flags
+  )
+{
+  AcquireSpinLock (&CpuData->CpuDataLock);
+  CpuData->Info.StatusFlag &= ~Flags;
+  ReleaseSpinLock (&CpuData->CpuDataLock);
+}
 
 /**
   This service retrieves the number of logical processor in the platform
@@ -169,6 +251,95 @@ GetProcessorInfo (
   return EFI_SUCCESS;
 }
 
+/**
+  This service lets the caller enable or disable an AP from this point onward.
+  This service may only be called from the BSP.
+
+  This service allows the caller enable or disable an AP from this point 
onward.
+  The caller can optionally specify the health status of the AP by Health. If
+  an AP is being disabled, then the state of the disabled AP is implementation
+  dependent. If an AP is enabled, then the implementation must guarantee that a
+  complete initialization sequence is performed on the AP, so the AP is in a 
state
+  that is compatible with an MP operating system. This service may not be 
supported
+  after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
+
+  If the enable or disable AP operation cannot be completed prior to the return
+  from this service, then EFI_UNSUPPORTED must be returned.
+
+  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL 
instance.
+  @param[in] ProcessorNumber   The handle number of AP that is to become the 
new
+                               BSP. The range is from 0 to the total number of
+                               logical processors minus 1. The total number of
+                               logical processors can be retrieved by
+                               
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
+  @param[in] EnableAP          Specifies the new state for the processor for
+                               enabled, FALSE for disabled.
+  @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
+                               the new health status of the AP. This flag
+                               corresponds to StatusFlag defined in
+                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). 
Only
+                               the PROCESSOR_HEALTH_STATUS_BIT is used. All 
other
+                               bits are ignored.  If it is NULL, this parameter
+                               is ignored.
+
+  @retval EFI_SUCCESS             The specified AP was enabled or disabled 
successfully.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be 
completed
+                                  prior to this service returning.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
+  @retval EFI_NOT_FOUND           Processor with the handle specified by 
ProcessorNumber
+                                  does not exist.
+  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+  IN  EFI_MP_SERVICES_PROTOCOL  *This,
+  IN  UINTN                     ProcessorNumber,
+  IN  BOOLEAN                   EnableAP,
+  IN  UINT32                    *HealthFlag OPTIONAL
+  )
+{
+  CPU_DATA_BLOCK *CpuData;
+
+  if (!IsBSP ()) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
+    return EFI_NOT_FOUND;
+  }
+
+  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
+  if (!TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (GetApState (CpuData) != CPU_STATE_IDLE) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (EnableAP) {
+    if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) {
+      mMpSystemData.NumberOfEnabledProcessors++;
+    }
+    CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT);
+  } else {
+    if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
+      mMpSystemData.NumberOfEnabledProcessors--;
+    }
+    CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT);
+  }
+
+  if (HealthFlag != NULL) {
+    CpuStatusFlagAndNot (CpuData, ~PROCESSOR_HEALTH_STATUS_BIT);
+    CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));
+  }
+
+  return EFI_SUCCESS;
+}
+
 
 /**
   This return the handle number for the calling processor.  This service may be
@@ -292,6 +463,7 @@ InitMpSystemData (
       CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
       CpuData->Info.ProcessorId = GetApicId ();
     }
+    InitializeSpinLock (&CpuData->CpuDataLock);
   }
 
   return EFI_SUCCESS;
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h
index c5f2eee..c2ce304 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.h
+++ b/UefiCpuPkg/CpuDxe/CpuMp.h
@@ -216,6 +216,56 @@ GetProcessorInfo (
   OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
   );
 
+/**
+  This service lets the caller enable or disable an AP from this point onward.
+  This service may only be called from the BSP.
+
+  This service allows the caller enable or disable an AP from this point 
onward.
+  The caller can optionally specify the health status of the AP by Health. If
+  an AP is being disabled, then the state of the disabled AP is implementation
+  dependent. If an AP is enabled, then the implementation must guarantee that a
+  complete initialization sequence is performed on the AP, so the AP is in a 
state
+  that is compatible with an MP operating system. This service may not be 
supported
+  after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
+
+  If the enable or disable AP operation cannot be completed prior to the return
+  from this service, then EFI_UNSUPPORTED must be returned.
+
+  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL 
instance.
+  @param[in] ProcessorNumber   The handle number of AP that is to become the 
new
+                               BSP. The range is from 0 to the total number of
+                               logical processors minus 1. The total number of
+                               logical processors can be retrieved by
+                               
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
+  @param[in] EnableAP          Specifies the new state for the processor for
+                               enabled, FALSE for disabled.
+  @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
+                               the new health status of the AP. This flag
+                               corresponds to StatusFlag defined in
+                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). 
Only
+                               the PROCESSOR_HEALTH_STATUS_BIT is used. All 
other
+                               bits are ignored.  If it is NULL, this parameter
+                               is ignored.
+
+  @retval EFI_SUCCESS             The specified AP was enabled or disabled 
successfully.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be 
completed
+                                  prior to this service returning.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
+  @retval EFI_NOT_FOUND           Processor with the handle specified by 
ProcessorNumber
+                                  does not exist.
+  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+  IN  EFI_MP_SERVICES_PROTOCOL  *This,
+  IN  UINTN                     ProcessorNumber,
+  IN  BOOLEAN                   EnableAP,
+  IN  UINT32                    *HealthFlag OPTIONAL
+  );
+
 
 /**
   This return the handle number for the calling processor.  This service may be
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 70d5bb0..9fa9270 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -52,6 +52,7 @@
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
   
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
  
+  
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
 
 [LibraryClasses.common.PEIM]
   
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
-- 
1.9.3


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to