/**\r
Create 4G PageTable in SMRAM.\r
\r
- @param ExtraPages Additional page numbers besides for 4G memory\r
- @param Is32BitPageTable Whether the page table is 32-bit PAE\r
+ @param[in] Is32BitPageTable Whether the page table is 32-bit PAE\r
@return PageTable Address\r
\r
**/\r
UINT32\r
Gen4GPageTable (\r
- IN UINTN ExtraPages,\r
IN BOOLEAN Is32BitPageTable\r
)\r
{\r
//\r
// Allocate the page table\r
//\r
- PageTable = AllocatePageTableMemory (ExtraPages + 5 + PagesNeeded);\r
+ PageTable = AllocatePageTableMemory (5 + PagesNeeded);\r
ASSERT (PageTable != NULL);\r
\r
- PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages));\r
+ PageTable = (VOID *)((UINTN)PageTable);\r
Pte = (UINT64*)PageTable;\r
\r
//\r
PageTable[PTIndex] |= (UINT64)Cacheability;\r
}\r
\r
-\r
/**\r
Schedule a procedure to run on the specified CPU.\r
\r
- @param Procedure The address of the procedure to run\r
- @param CpuIndex Target CPU Index\r
- @param ProcArguments The parameter to pass to the procedure\r
+ @param[in] Procedure The address of the procedure to run\r
+ @param[in] CpuIndex Target CPU Index\r
+ @param[in, OUT] ProcArguments The parameter to pass to the procedure\r
+ @param[in] BlockingMode Startup AP in blocking mode or not\r
\r
@retval EFI_INVALID_PARAMETER CpuNumber not valid\r
@retval EFI_INVALID_PARAMETER CpuNumber specifying BSP\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-SmmStartupThisAp (\r
+InternalSmmStartupThisAp (\r
IN EFI_AP_PROCEDURE Procedure,\r
IN UINTN CpuIndex,\r
- IN OUT VOID *ProcArguments OPTIONAL\r
+ IN OUT VOID *ProcArguments OPTIONAL,\r
+ IN BOOLEAN BlockingMode\r
)\r
{\r
- if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus ||\r
- CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu ||\r
- !(*(mSmmMpSyncData->CpuData[CpuIndex].Present)) ||\r
- gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove ||\r
- !AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) {\r
+ if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus) {\r
+ DEBUG((DEBUG_ERROR, "CpuIndex(%d) >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus(%d)\n", CpuIndex, gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) {\r
+ DEBUG((DEBUG_ERROR, "CpuIndex(%d) == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu\n", CpuIndex));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (!(*(mSmmMpSyncData->CpuData[CpuIndex].Present))) {\r
+ if (mSmmMpSyncData->EffectiveSyncMode == SmmCpuSyncModeTradition) {\r
+ DEBUG((DEBUG_ERROR, "!mSmmMpSyncData->CpuData[%d].Present\n", CpuIndex));\r
+ }\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove) {\r
+ if (!FeaturePcdGet (PcdCpuHotPlugSupport)) {\r
+ DEBUG((DEBUG_ERROR, "gSmmCpuPrivate->Operation[%d] == SmmCpuRemove\n", CpuIndex));\r
+ }\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if (BlockingMode) {\r
+ AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+ } else {\r
+ if (!AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) {\r
+ DEBUG((DEBUG_ERROR, "mSmmMpSyncData->CpuData[%d].Busy\n", CpuIndex));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;\r
mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;\r
ReleaseSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
\r
- if (FeaturePcdGet (PcdCpuSmmBlockStartupThisAp)) {\r
+ if (BlockingMode) {\r
AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Schedule a procedure to run on the specified CPU in blocking mode.\r
+\r
+ @param[in] Procedure The address of the procedure to run\r
+ @param[in] CpuIndex Target CPU Index\r
+ @param[in, out] ProcArguments The parameter to pass to the procedure\r
+\r
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid\r
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy\r
+ @retval EFI_SUCCESS The procedure has been successfully scheduled\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmBlockingStartupThisAp (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN UINTN CpuIndex,\r
+ IN OUT VOID *ProcArguments OPTIONAL\r
+ )\r
+{\r
+ return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, TRUE);\r
+}\r
+\r
+/**\r
+ Schedule a procedure to run on the specified CPU.\r
+\r
+ @param Procedure The address of the procedure to run\r
+ @param CpuIndex Target CPU Index\r
+ @param ProcArguments The parameter to pass to the procedure\r
+\r
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid\r
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy\r
+ @retval EFI_SUCCESS The procedure has been successfully scheduled\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmStartupThisAp (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN UINTN CpuIndex,\r
+ IN OUT VOID *ProcArguments OPTIONAL\r
+ )\r
+{\r
+ return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, FeaturePcdGet (PcdCpuSmmBlockStartupThisAp));\r
+}\r
+\r
/**\r
This function sets DR6 & DR7 according to SMM save state, before running SMM C code.\r
They are useful when you want to enable hardware breakpoints in SMM without entry SMM mode.\r
SMRAM_SAVE_STATE_MAP *CpuSaveState;\r
\r
if (FeaturePcdGet (PcdCpuSmmDebug)) {\r
+ ASSERT(CpuIndex < mMaxNumberOfCpus);\r
CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex];\r
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {\r
AsmWriteDr6 (CpuSaveState->x86._DR6);\r
SMRAM_SAVE_STATE_MAP *CpuSaveState;\r
\r
if (FeaturePcdGet (PcdCpuSmmDebug)) {\r
+ ASSERT(CpuIndex < mMaxNumberOfCpus);\r
CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex];\r
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {\r
CpuSaveState->x86._DR7 = (UINT32)AsmReadDr7 ();\r
BOOLEAN BspInProgress;\r
UINTN Index;\r
UINTN Cr2;\r
- BOOLEAN XdDisableFlag;\r
- MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;\r
+\r
+ ASSERT(CpuIndex < mMaxNumberOfCpus);\r
\r
//\r
// Save Cr2 because Page Fault exception in SMM may override its value\r
InitializeSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
}\r
\r
- //\r
- // Try to enable XD\r
- //\r
- XdDisableFlag = FALSE;\r
- if (mXdSupported) {\r
- MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
- if (MiscEnableMsr.Bits.XD == 1) {\r
- XdDisableFlag = TRUE;\r
- MiscEnableMsr.Bits.XD = 0;\r
- AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64);\r
- }\r
- ActivateXd ();\r
- }\r
-\r
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
ActivateSmmProfile (CpuIndex);\r
}\r
//\r
while (*mSmmMpSyncData->AllCpusInSync) {\r
CpuPause ();\r
- }\r
-\r
- //\r
- // Restore XD\r
- //\r
- if (XdDisableFlag) {\r
- MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
- MiscEnableMsr.Bits.XD = 1;\r
- AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64);\r
}\r
}\r
\r
VOID\r
)\r
{\r
- UINTN CpuIndex;\r
UINTN ProcessorCount;\r
UINTN TotalSize;\r
UINTN GlobalSemaphoresSize;\r
UINTN CpuSemaphoresSize;\r
+ UINTN MsrSemahporeSize;\r
UINTN SemaphoreSize;\r
UINTN Pages;\r
UINTN *SemaphoreBlock;\r
ProcessorCount = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
GlobalSemaphoresSize = (sizeof (SMM_CPU_SEMAPHORE_GLOBAL) / sizeof (VOID *)) * SemaphoreSize;\r
CpuSemaphoresSize = (sizeof (SMM_CPU_SEMAPHORE_CPU) / sizeof (VOID *)) * ProcessorCount * SemaphoreSize;\r
- TotalSize = GlobalSemaphoresSize + CpuSemaphoresSize;\r
+ MsrSemahporeSize = MSR_SPIN_LOCK_INIT_NUM * SemaphoreSize;\r
+ TotalSize = GlobalSemaphoresSize + CpuSemaphoresSize + MsrSemahporeSize;\r
DEBUG((EFI_D_INFO, "One Semaphore Size = 0x%x\n", SemaphoreSize));\r
DEBUG((EFI_D_INFO, "Total Semaphores Size = 0x%x\n", TotalSize));\r
Pages = EFI_SIZE_TO_PAGES (TotalSize);\r
SemaphoreAddr += SemaphoreSize;\r
mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock\r
= (SPIN_LOCK *)SemaphoreAddr;\r
+ SemaphoreAddr += SemaphoreSize;\r
+ mSmmCpuSemaphores.SemaphoreGlobal.MemoryMappedLock\r
+ = (SPIN_LOCK *)SemaphoreAddr;\r
\r
SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize;\r
mSmmCpuSemaphores.SemaphoreCpu.Busy = (SPIN_LOCK *)SemaphoreAddr;\r
SemaphoreAddr += ProcessorCount * SemaphoreSize;\r
mSmmCpuSemaphores.SemaphoreCpu.Present = (BOOLEAN *)SemaphoreAddr;\r
\r
- mSmmMpSyncData->Counter = mSmmCpuSemaphores.SemaphoreGlobal.Counter;\r
- mSmmMpSyncData->InsideSmm = mSmmCpuSemaphores.SemaphoreGlobal.InsideSmm;\r
- mSmmMpSyncData->AllCpusInSync = mSmmCpuSemaphores.SemaphoreGlobal.AllCpusInSync;\r
+ SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize + CpuSemaphoresSize;\r
+ mSmmCpuSemaphores.SemaphoreMsr.Msr = (SPIN_LOCK *)SemaphoreAddr;\r
+ mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter =\r
+ ((UINTN)SemaphoreBlock + Pages * SIZE_4KB - SemaphoreAddr) / SemaphoreSize;\r
+ ASSERT (mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter >= MSR_SPIN_LOCK_INIT_NUM);\r
+\r
mPFLock = mSmmCpuSemaphores.SemaphoreGlobal.PFLock;\r
mConfigSmmCodeAccessCheckLock = mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock;\r
-\r
- for (CpuIndex = 0; CpuIndex < ProcessorCount; CpuIndex ++) {\r
- mSmmMpSyncData->CpuData[CpuIndex].Busy =\r
- (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Busy + SemaphoreSize * CpuIndex);\r
- mSmmMpSyncData->CpuData[CpuIndex].Run =\r
- (UINT32 *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Run + SemaphoreSize * CpuIndex);\r
- mSmmMpSyncData->CpuData[CpuIndex].Present =\r
- (BOOLEAN *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Present + SemaphoreSize * CpuIndex);\r
- }\r
+ mMemoryMappedLock = mSmmCpuSemaphores.SemaphoreGlobal.MemoryMappedLock;\r
\r
mSemaphoreSize = SemaphoreSize;\r
}\r
VOID\r
)\r
{\r
+ UINTN CpuIndex;\r
+\r
if (mSmmMpSyncData != NULL) {\r
+ //\r
+ // mSmmMpSyncDataSize includes one structure of SMM_DISPATCHER_MP_SYNC_DATA, one\r
+ // CpuData array of SMM_CPU_DATA_BLOCK and one CandidateBsp array of BOOLEAN.\r
+ //\r
ZeroMem (mSmmMpSyncData, mSmmMpSyncDataSize);\r
mSmmMpSyncData->CpuData = (SMM_CPU_DATA_BLOCK *)((UINT8 *)mSmmMpSyncData + sizeof (SMM_DISPATCHER_MP_SYNC_DATA));\r
mSmmMpSyncData->CandidateBsp = (BOOLEAN *)(mSmmMpSyncData->CpuData + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);\r
}\r
mSmmMpSyncData->EffectiveSyncMode = (SMM_CPU_SYNC_MODE) PcdGet8 (PcdCpuSmmSyncMode);\r
\r
- InitializeSmmCpuSemaphores ();\r
+ mSmmMpSyncData->Counter = mSmmCpuSemaphores.SemaphoreGlobal.Counter;\r
+ mSmmMpSyncData->InsideSmm = mSmmCpuSemaphores.SemaphoreGlobal.InsideSmm;\r
+ mSmmMpSyncData->AllCpusInSync = mSmmCpuSemaphores.SemaphoreGlobal.AllCpusInSync;\r
+ ASSERT (mSmmMpSyncData->Counter != NULL && mSmmMpSyncData->InsideSmm != NULL &&\r
+ mSmmMpSyncData->AllCpusInSync != NULL);\r
+ *mSmmMpSyncData->Counter = 0;\r
+ *mSmmMpSyncData->InsideSmm = FALSE;\r
+ *mSmmMpSyncData->AllCpusInSync = FALSE;\r
+\r
+ for (CpuIndex = 0; CpuIndex < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; CpuIndex ++) {\r
+ mSmmMpSyncData->CpuData[CpuIndex].Busy =\r
+ (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Busy + mSemaphoreSize * CpuIndex);\r
+ mSmmMpSyncData->CpuData[CpuIndex].Run =\r
+ (UINT32 *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Run + mSemaphoreSize * CpuIndex);\r
+ mSmmMpSyncData->CpuData[CpuIndex].Present =\r
+ (BOOLEAN *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Present + mSemaphoreSize * CpuIndex);\r
+ }\r
}\r
}\r
\r
UINT8 *GdtTssTables;\r
UINTN GdtTableStepSize;\r
\r
+ //\r
+ // Allocate memory for all locks and semaphores\r
+ //\r
+ InitializeSmmCpuSemaphores ();\r
+\r
//\r
// Initialize mSmmMpSyncData\r
//\r