diff options
author | Chen Fan <chen.fan.fnst@cn.fujitsu.com> | 2014-11-13 18:27:09 +0000 |
---|---|---|
committer | jljusten <jljusten@Edk2> | 2014-11-13 18:27:09 +0000 |
commit | fa7ce675b991bca6e18fcda8446737717ae3c1f6 (patch) | |
tree | ab69cdfc5489c539a26563bc194c85663227e1e2 /UefiCpuPkg/CpuDxe/CpuMp.c | |
parent | e7938b5a869fc42df7f026752f39ea85090eb3f9 (diff) | |
download | edk2-fa7ce675b991bca6e18fcda8446737717ae3c1f6.tar.gz edk2-fa7ce675b991bca6e18fcda8446737717ae3c1f6.tar.bz2 edk2-fa7ce675b991bca6e18fcda8446737717ae3c1f6.zip |
UefiCpuPkg/CpuDxe: implement Mp Protocol:EnableDisableAP()
Due to the implementation of AcquireSpinLock() is not MP safe,
so we should use AcquireSpinLockOrFail directly instead.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16357 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'UefiCpuPkg/CpuDxe/CpuMp.c')
-rw-r--r-- | UefiCpuPkg/CpuDxe/CpuMp.c | 186 |
1 files changed, 185 insertions, 1 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index 4fae3f2f0d..1d3d16bcc0 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -30,7 +30,7 @@ EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { NULL, // StartupAllAPs,
NULL, // StartupThisAP,
NULL, // SwitchBSP,
- NULL, // EnableDisableAP,
+ EnableDisableAP,
WhoAmI
};
@@ -58,6 +58,101 @@ IsBSP ( }
/**
+ 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;
+
+ while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
+ CpuPause ();
+ }
+
+ 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;
+
+ while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
+ CpuPause ();
+ }
+
+ 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
+ )
+{
+ while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
+ CpuPause ();
+ }
+
+ 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
+ )
+{
+ while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
+ CpuPause ();
+ }
+
+ CpuData->Info.StatusFlag &= ~Flags;
+ ReleaseSpinLock (&CpuData->CpuDataLock);
+}
+
+/**
This service retrieves the number of logical processor in the platform
and the number of those logical processors that are enabled on this boot.
This service may only be called from the BSP.
@@ -165,6 +260,95 @@ GetProcessorInfo ( }
/**
+ 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) != CpuStateIdle) {
+ 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, (UINT32)~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
called from the BSP and APs.
|