X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FMpService.c;h=4ac5e8e26462b146919047a61c6767e3e377585e;hp=12466ef5de1f633b20c24bcec75e1ffff0c1e586;hb=b7025df8f9102a1698879aa451bf5af592c37bc1;hpb=e78a2a49ee6b0c0d7c6997c87ace31d7761cf636 diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c index 12466ef5de..4ac5e8e264 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c @@ -1,7 +1,9 @@ /** @file SMM MP service implementation -Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -17,13 +19,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // // Slots for all MTRR( FIXED MTRR + VARIABLE MTRR + MTRR_LIB_IA32_MTRR_DEF_TYPE) // -UINT64 gSmiMtrrs[MTRR_NUMBER_OF_FIXED_MTRR + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; +MTRR_SETTINGS gSmiMtrrs; UINT64 gPhyMask; SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData = NULL; UINTN mSmmMpSyncDataSize; SMM_CPU_SEMAPHORES mSmmCpuSemaphores; UINTN mSemaphoreSize; SPIN_LOCK *mPFLock = NULL; +SMM_CPU_SYNC_MODE mCpuSmmSyncMode; /** Performs an atomic compare exchange operation to get semaphore. @@ -282,20 +285,12 @@ ReplaceOSMtrrs ( IN UINTN CpuIndex ) { - PROCESSOR_SMM_DESCRIPTOR *Psd; - UINT64 *SmiMtrrs; - MTRR_SETTINGS *BiosMtrr; - - Psd = (PROCESSOR_SMM_DESCRIPTOR*)(mCpuHotPlugData.SmBase[CpuIndex] + SMM_PSD_OFFSET); - SmiMtrrs = (UINT64*)(UINTN)Psd->MtrrBaseMaskPtr; - SmmCpuFeaturesDisableSmrr (); // // Replace all MTRRs registers // - BiosMtrr = (MTRR_SETTINGS*)SmiMtrrs; - MtrrSetAllMtrrs(BiosMtrr); + MtrrSetAllMtrrs (&gSmiMtrrs); } /** @@ -412,7 +407,7 @@ BSPHandler ( // // The BUSY lock is initialized to Acquired state // - AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy); + AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); // // Perform the pre tasks @@ -734,14 +729,12 @@ APHandler ( /** Create 4G PageTable in SMRAM. - @param ExtraPages Additional page numbers besides for 4G memory - @param Is32BitPageTable Whether the page table is 32-bit PAE + @param[in] Is32BitPageTable Whether the page table is 32-bit PAE @return PageTable Address **/ UINT32 Gen4GPageTable ( - IN UINTN ExtraPages, IN BOOLEAN Is32BitPageTable ) { @@ -775,10 +768,10 @@ Gen4GPageTable ( // // Allocate the page table // - PageTable = AllocatePageTableMemory (ExtraPages + 5 + PagesNeeded); + PageTable = AllocatePageTableMemory (5 + PagesNeeded); ASSERT (PageTable != NULL); - PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages)); + PageTable = (VOID *)((UINTN)PageTable); Pte = (UINT64*)PageTable; // @@ -790,7 +783,8 @@ Gen4GPageTable ( // Set Page Directory Pointers // for (Index = 0; Index < 4; Index++) { - Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS); + Pte[Index] = ((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask | + (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS); } Pte += EFI_PAGE_SIZE / sizeof (*Pte); @@ -798,7 +792,7 @@ Gen4GPageTable ( // Fill in Page Directory Entries // for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) { - Pte[Index] = (Index << 21) | IA32_PG_PS | PAGE_ATTRIBUTE_BITS; + Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS; } if (FeaturePcdGet (PcdCpuSmmStackGuard)) { @@ -806,8 +800,8 @@ Gen4GPageTable ( GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE; Pdpte = (UINT64*)PageTable; for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) { - Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~(EFI_PAGE_SIZE - 1)); - Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | PAGE_ATTRIBUTE_BITS; + Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1)); + Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS; // // Fill in Page Table Entries // @@ -818,13 +812,13 @@ Gen4GPageTable ( // // Mark the guard page as non-present // - Pte[Index] = PageAddress; + Pte[Index] = PageAddress | mAddressEncMask; GuardPage += mSmmStackSize; if (GuardPage > mSmmStackArrayEnd) { GuardPage = 0; } } else { - Pte[Index] = PageAddress | PAGE_ATTRIBUTE_BITS; + Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS; } PageAddress+= EFI_PAGE_SIZE; } @@ -836,74 +830,97 @@ Gen4GPageTable ( } /** - Set memory cache ability. + Schedule a procedure to run on the specified CPU. - @param PageTable PageTable Address - @param Address Memory Address to change cache ability - @param Cacheability Cache ability to set + @param[in] Procedure The address of the procedure to run + @param[in] CpuIndex Target CPU Index + @param[in, out] ProcArguments The parameter to pass to the procedure + @param[in] BlockingMode Startup AP in blocking mode or not + + @retval EFI_INVALID_PARAMETER CpuNumber not valid + @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP + @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM + @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy + @retval EFI_SUCCESS The procedure has been successfully scheduled **/ -VOID -SetCacheability ( - IN UINT64 *PageTable, - IN UINTN Address, - IN UINT8 Cacheability +EFI_STATUS +InternalSmmStartupThisAp ( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuIndex, + IN OUT VOID *ProcArguments OPTIONAL, + IN BOOLEAN BlockingMode ) { - UINTN PTIndex; - VOID *NewPageTableAddress; - UINT64 *NewPageTable; - UINTN Index; - - ASSERT ((Address & EFI_PAGE_MASK) == 0); - - if (sizeof (UINTN) == sizeof (UINT64)) { - PTIndex = (UINTN)RShiftU64 (Address, 39) & 0x1ff; - ASSERT (PageTable[PTIndex] & IA32_PG_P); - PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); + if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus) { + DEBUG((DEBUG_ERROR, "CpuIndex(%d) >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus(%d)\n", CpuIndex, gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus)); + return EFI_INVALID_PARAMETER; + } + if (CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) { + DEBUG((DEBUG_ERROR, "CpuIndex(%d) == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu\n", CpuIndex)); + return EFI_INVALID_PARAMETER; + } + if (gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId == INVALID_APIC_ID) { + return EFI_INVALID_PARAMETER; + } + if (!(*(mSmmMpSyncData->CpuData[CpuIndex].Present))) { + if (mSmmMpSyncData->EffectiveSyncMode == SmmCpuSyncModeTradition) { + DEBUG((DEBUG_ERROR, "!mSmmMpSyncData->CpuData[%d].Present\n", CpuIndex)); + } + return EFI_INVALID_PARAMETER; + } + if (gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove) { + if (!FeaturePcdGet (PcdCpuHotPlugSupport)) { + DEBUG((DEBUG_ERROR, "gSmmCpuPrivate->Operation[%d] == SmmCpuRemove\n", CpuIndex)); + } + return EFI_INVALID_PARAMETER; } - PTIndex = (UINTN)RShiftU64 (Address, 30) & 0x1ff; - ASSERT (PageTable[PTIndex] & IA32_PG_P); - PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); + if (BlockingMode) { + AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); + } else { + if (!AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) { + DEBUG((DEBUG_ERROR, "mSmmMpSyncData->CpuData[%d].Busy\n", CpuIndex)); + return EFI_INVALID_PARAMETER; + } + } - // - // A perfect implementation should check the original cacheability with the - // one being set, and break a 2M page entry into pieces only when they - // disagreed. - // - PTIndex = (UINTN)RShiftU64 (Address, 21) & 0x1ff; - if ((PageTable[PTIndex] & IA32_PG_PS) != 0) { - // - // Allocate a page from SMRAM - // - NewPageTableAddress = AllocatePageTableMemory (1); - ASSERT (NewPageTableAddress != NULL); + mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure; + mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments; + ReleaseSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run); - NewPageTable = (UINT64 *)NewPageTableAddress; + if (BlockingMode) { + AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); + ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); + } + return EFI_SUCCESS; +} - for (Index = 0; Index < 0x200; Index++) { - NewPageTable[Index] = PageTable[PTIndex]; - if ((NewPageTable[Index] & IA32_PG_PAT_2M) != 0) { - NewPageTable[Index] &= ~((UINT64)IA32_PG_PAT_2M); - NewPageTable[Index] |= (UINT64)IA32_PG_PAT_4K; - } - NewPageTable[Index] |= (UINT64)(Index << EFI_PAGE_SHIFT); - } +/** + Schedule a procedure to run on the specified CPU in blocking mode. - PageTable[PTIndex] = ((UINTN)NewPageTableAddress & gPhyMask) | PAGE_ATTRIBUTE_BITS; - } + @param[in] Procedure The address of the procedure to run + @param[in] CpuIndex Target CPU Index + @param[in, out] ProcArguments The parameter to pass to the procedure - ASSERT (PageTable[PTIndex] & IA32_PG_P); - PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); + @retval EFI_INVALID_PARAMETER CpuNumber not valid + @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP + @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM + @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy + @retval EFI_SUCCESS The procedure has been successfully scheduled - PTIndex = (UINTN)RShiftU64 (Address, 12) & 0x1ff; - ASSERT (PageTable[PTIndex] & IA32_PG_P); - PageTable[PTIndex] &= ~((UINT64)((IA32_PG_PAT_4K | IA32_PG_CD | IA32_PG_WT))); - PageTable[PTIndex] |= (UINT64)Cacheability; +**/ +EFI_STATUS +EFIAPI +SmmBlockingStartupThisAp ( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuIndex, + IN OUT VOID *ProcArguments OPTIONAL + ) +{ + return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, TRUE); } - /** Schedule a procedure to run on the specified CPU. @@ -926,23 +943,7 @@ SmmStartupThisAp ( IN OUT VOID *ProcArguments OPTIONAL ) { - if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus || - CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu || - !(*(mSmmMpSyncData->CpuData[CpuIndex].Present)) || - gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove || - !AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) { - return EFI_INVALID_PARAMETER; - } - - mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure; - mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments; - ReleaseSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run); - - if (FeaturePcdGet (PcdCpuSmmBlockStartupThisAp)) { - AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); - ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); - } - return EFI_SUCCESS; + return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, FeaturePcdGet (PcdCpuSmmBlockStartupThisAp)); } /** @@ -964,6 +965,7 @@ CpuSmmDebugEntry ( SMRAM_SAVE_STATE_MAP *CpuSaveState; if (FeaturePcdGet (PcdCpuSmmDebug)) { + ASSERT(CpuIndex < mMaxNumberOfCpus); CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex]; if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) { AsmWriteDr6 (CpuSaveState->x86._DR6); @@ -993,6 +995,7 @@ CpuSmmDebugExit ( SMRAM_SAVE_STATE_MAP *CpuSaveState; if (FeaturePcdGet (PcdCpuSmmDebug)) { + ASSERT(CpuIndex < mMaxNumberOfCpus); CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex]; if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) { CpuSaveState->x86._DR7 = (UINT32)AsmReadDr7 (); @@ -1022,8 +1025,8 @@ SmiRendezvous ( BOOLEAN BspInProgress; UINTN Index; UINTN Cr2; - BOOLEAN XdDisableFlag; - MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr; + + ASSERT(CpuIndex < mMaxNumberOfCpus); // // Save Cr2 because Page Fault exception in SMM may override its value @@ -1082,20 +1085,6 @@ SmiRendezvous ( InitializeSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy); } - // - // Try to enable XD - // - XdDisableFlag = FALSE; - if (mXdSupported) { - MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE); - if (MiscEnableMsr.Bits.XD == 1) { - XdDisableFlag = TRUE; - MiscEnableMsr.Bits.XD = 0; - AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64); - } - ActivateXd (); - } - if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { ActivateSmmProfile (CpuIndex); } @@ -1176,15 +1165,6 @@ SmiRendezvous ( // while (*mSmmMpSyncData->AllCpusInSync) { CpuPause (); - } - - // - // Restore XD - // - if (XdDisableFlag) { - MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE); - MiscEnableMsr.Bits.XD = 1; - AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64); } } @@ -1289,7 +1269,7 @@ InitializeMpSyncData ( // mSmmMpSyncData->BspIndex = (UINT32)-1; } - mSmmMpSyncData->EffectiveSyncMode = (SMM_CPU_SYNC_MODE) PcdGet8 (PcdCpuSmmSyncMode); + mSmmMpSyncData->EffectiveSyncMode = mCpuSmmSyncMode; mSmmMpSyncData->Counter = mSmmCpuSemaphores.SemaphoreGlobal.Counter; mSmmMpSyncData->InsideSmm = mSmmCpuSemaphores.SemaphoreGlobal.InsideSmm; @@ -1307,6 +1287,9 @@ InitializeMpSyncData ( (UINT32 *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Run + mSemaphoreSize * CpuIndex); mSmmMpSyncData->CpuData[CpuIndex].Present = (BOOLEAN *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Present + mSemaphoreSize * CpuIndex); + *(mSmmMpSyncData->CpuData[CpuIndex].Busy) = 0; + *(mSmmMpSyncData->CpuData[CpuIndex].Run) = 0; + *(mSmmMpSyncData->CpuData[CpuIndex].Present) = FALSE; } } } @@ -1326,8 +1309,6 @@ InitializeMpServiceData ( { UINT32 Cr3; UINTN Index; - MTRR_SETTINGS *Mtrr; - PROCESSOR_SMM_DESCRIPTOR *Psd; UINT8 *GdtTssTables; UINTN GdtTableStepSize; @@ -1343,6 +1324,7 @@ InitializeMpServiceData ( (sizeof (SMM_CPU_DATA_BLOCK) + sizeof (BOOLEAN)) * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; mSmmMpSyncData = (SMM_DISPATCHER_MP_SYNC_DATA*) AllocatePages (EFI_SIZE_TO_PAGES (mSmmMpSyncDataSize)); ASSERT (mSmmMpSyncData != NULL); + mCpuSmmSyncMode = (SMM_CPU_SYNC_MODE)PcdGet8 (PcdCpuSmmSyncMode); InitializeMpSyncData (); // @@ -1361,24 +1343,16 @@ InitializeMpServiceData ( GdtTssTables = InitGdt (Cr3, &GdtTableStepSize); // - // Initialize PROCESSOR_SMM_DESCRIPTOR for each CPU + // Install SMI handler for each CPU // for (Index = 0; Index < mMaxNumberOfCpus; Index++) { - Psd = (PROCESSOR_SMM_DESCRIPTOR *)(VOID *)(UINTN)(mCpuHotPlugData.SmBase[Index] + SMM_PSD_OFFSET); - CopyMem (Psd, &gcPsd, sizeof (gcPsd)); - Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTableStepSize * Index); - Psd->SmmGdtSize = gcSmiGdtr.Limit + 1; - - // - // Install SMI handler - // InstallSmiHandler ( Index, (UINT32)mCpuHotPlugData.SmBase[Index], (VOID*)((UINTN)Stacks + (StackSize * Index)), StackSize, - (UINTN)Psd->SmmGdtPtr, - Psd->SmmGdtSize, + (UINTN)(GdtTssTables + GdtTableStepSize * Index), + gcSmiGdtr.Limit + 1, gcSmiIdtr.Base, gcSmiIdtr.Limit + 1, Cr3 @@ -1388,9 +1362,8 @@ InitializeMpServiceData ( // // Record current MTRR settings // - ZeroMem(gSmiMtrrs, sizeof (gSmiMtrrs)); - Mtrr = (MTRR_SETTINGS*)gSmiMtrrs; - MtrrGetAllMtrrs (Mtrr); + ZeroMem (&gSmiMtrrs, sizeof (gSmiMtrrs)); + MtrrGetAllMtrrs (&gSmiMtrrs); return Cr3; }