X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FCpuS3.c;h=2cfc61b2c66c3b8ff49b7fc59f7d0e0c9b9054f5;hp=94e5ab2c0ee22398fb846ac720ada8a3535be9e4;hb=0acd869796ded1266e69487dff717cd69d6031f9;hpb=c9b094f61029efff45c8d555d3eff6b061f77b8a diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c index 94e5ab2c0e..2cfc61b2c6 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c @@ -1,19 +1,14 @@ /** @file Code for Processor S3 restoration -Copyright (c) 2006 - 2017, Intel Corporation. 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 -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "PiSmmCpuDxeSmm.h" +#pragma pack(1) typedef struct { UINTN Lock; VOID *StackStart; @@ -23,7 +18,9 @@ typedef struct { IA32_DESCRIPTOR IdtrProfile; UINT32 BufferStart; UINT32 Cr3; + UINTN InitializeFloatingPointUnitsAddress; } MP_CPU_EXCHANGE_INFO; +#pragma pack() typedef struct { UINT8 *RendezvousFunnelAddress; @@ -35,9 +32,16 @@ typedef struct { } MP_ASSEMBLY_ADDRESS_MAP; // -// Spin lock used to serialize MemoryMapped operation +// Flags used when program the register. // -SPIN_LOCK *mMemoryMappedLock = NULL; +typedef struct { + volatile UINTN ConsoleLogLock; // Spinlock used to control console. + volatile UINTN MemoryMappedLock; // Spinlock used to program mmio + volatile UINT32 *CoreSemaphoreCount; // Semaphore container used to program + // core level semaphore. + volatile UINT32 *PackageSemaphoreCount; // Semaphore container used to program + // package level semaphore. +} PROGRAM_CPU_REGISTER_FLAGS; // // Signal that SMM BASE relocation is complete. @@ -59,16 +63,11 @@ AsmGetAddressMap ( #define LEGACY_REGION_SIZE (2 * 0x1000) #define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE) +PROGRAM_CPU_REGISTER_FLAGS mCpuFlags; ACPI_CPU_DATA mAcpiCpuData; volatile UINT32 mNumberToFinish; MP_CPU_EXCHANGE_INFO *mExchangeInfo; BOOLEAN mRestoreSmmConfigurationInS3 = FALSE; -VOID *mGdtForAp = NULL; -VOID *mIdtForAp = NULL; -VOID *mMachineCheckHandlerForAp = NULL; -MP_MSR_LOCK *mMsrSpinLocks = NULL; -UINTN mMsrSpinLockCount; -UINTN mMsrCount = 0; // // S3 boot flag @@ -91,88 +90,7 @@ UINT8 mApHltLoopCodeTemplate[] = { 0xEB, 0xFC // jmp $-2 }; -/** - Get MSR spin lock by MSR index. - - @param MsrIndex MSR index value. - - @return Pointer to MSR spin lock. - -**/ -SPIN_LOCK * -GetMsrSpinLockByIndex ( - IN UINT32 MsrIndex - ) -{ - UINTN Index; - for (Index = 0; Index < mMsrCount; Index++) { - if (MsrIndex == mMsrSpinLocks[Index].MsrIndex) { - return mMsrSpinLocks[Index].SpinLock; - } - } - return NULL; -} - -/** - Initialize MSR spin lock by MSR index. - - @param MsrIndex MSR index value. - -**/ -VOID -InitMsrSpinLockByIndex ( - IN UINT32 MsrIndex - ) -{ - UINTN MsrSpinLockCount; - UINTN NewMsrSpinLockCount; - UINTN Index; - UINTN AddedSize; - - if (mMsrSpinLocks == NULL) { - MsrSpinLockCount = mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter; - mMsrSpinLocks = (MP_MSR_LOCK *) AllocatePool (sizeof (MP_MSR_LOCK) * MsrSpinLockCount); - ASSERT (mMsrSpinLocks != NULL); - for (Index = 0; Index < MsrSpinLockCount; Index++) { - mMsrSpinLocks[Index].SpinLock = - (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreMsr.Msr + Index * mSemaphoreSize); - mMsrSpinLocks[Index].MsrIndex = (UINT32)-1; - } - mMsrSpinLockCount = MsrSpinLockCount; - mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter = 0; - } - if (GetMsrSpinLockByIndex (MsrIndex) == NULL) { - // - // Initialize spin lock for MSR programming - // - mMsrSpinLocks[mMsrCount].MsrIndex = MsrIndex; - InitializeSpinLock (mMsrSpinLocks[mMsrCount].SpinLock); - mMsrCount ++; - if (mMsrCount == mMsrSpinLockCount) { - // - // If MSR spin lock buffer is full, enlarge it - // - AddedSize = SIZE_4KB; - mSmmCpuSemaphores.SemaphoreMsr.Msr = - AllocatePages (EFI_SIZE_TO_PAGES(AddedSize)); - ASSERT (mSmmCpuSemaphores.SemaphoreMsr.Msr != NULL); - NewMsrSpinLockCount = mMsrSpinLockCount + AddedSize / mSemaphoreSize; - mMsrSpinLocks = ReallocatePool ( - sizeof (MP_MSR_LOCK) * mMsrSpinLockCount, - sizeof (MP_MSR_LOCK) * NewMsrSpinLockCount, - mMsrSpinLocks - ); - ASSERT (mMsrSpinLocks != NULL); - mMsrSpinLockCount = NewMsrSpinLockCount; - for (Index = mMsrCount; Index < mMsrSpinLockCount; Index++) { - mMsrSpinLocks[Index].SpinLock = - (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreMsr.Msr + - (Index - mMsrCount) * mSemaphoreSize); - mMsrSpinLocks[Index].MsrIndex = (UINT32)-1; - } - } - } -} +CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" }; /** Sync up the MTRR values for all processors. @@ -204,42 +122,103 @@ Returns: } /** - Programs registers for the calling processor. + Increment semaphore by 1. + + @param Sem IN: 32-bit unsigned integer + +**/ +VOID +S3ReleaseSemaphore ( + IN OUT volatile UINT32 *Sem + ) +{ + InterlockedIncrement (Sem); +} + +/** + Decrement the semaphore by 1 if it is not zero. + + Performs an atomic decrement operation for semaphore. + The compare exchange operation must be performed using + MP safe mechanisms. + + @param Sem IN: 32-bit unsigned integer + +**/ +VOID +S3WaitForSemaphore ( + IN OUT volatile UINT32 *Sem + ) +{ + UINT32 Value; + + do { + Value = *Sem; + } while (Value == 0 || + InterlockedCompareExchange32 ( + Sem, + Value, + Value - 1 + ) != Value); +} - This function programs registers for the calling processor. +/** + Initialize the CPU registers from a register table. - @param RegisterTables Pointer to register table of the running processor. - @param RegisterTableCount Register table count. + @param[in] RegisterTable The register table for this AP. + @param[in] ApLocation AP location info for this ap. + @param[in] CpuStatus CPU status info for this CPU. + @param[in] CpuFlags Flags data structure used when program the register. + @note This service could be called by BSP/APs. **/ VOID -SetProcessorRegister ( - IN CPU_REGISTER_TABLE *RegisterTables, - IN UINTN RegisterTableCount +ProgramProcessorRegister ( + IN CPU_REGISTER_TABLE *RegisterTable, + IN EFI_CPU_PHYSICAL_LOCATION *ApLocation, + IN CPU_STATUS_INFORMATION *CpuStatus, + IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags ) { CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry; UINTN Index; UINTN Value; - SPIN_LOCK *MsrSpinLock; - UINT32 InitApicId; - CPU_REGISTER_TABLE *RegisterTable; - - InitApicId = GetInitialApicId (); - RegisterTable = NULL; - for (Index = 0; Index < RegisterTableCount; Index++) { - if (RegisterTables[Index].InitialApicId == InitApicId) { - RegisterTable = &RegisterTables[Index]; - break; - } - } - ASSERT (RegisterTable != NULL); + CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead; + volatile UINT32 *SemaphorePtr; + UINT32 FirstThread; + UINT32 PackageThreadsCount; + UINT32 CurrentThread; + UINTN ProcessorIndex; + UINTN ThreadIndex; + UINTN ValidThreadCount; + UINT32 *ValidCoreCountPerPackage; // // Traverse Register Table of this logical processor // - RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry; - for (Index = 0; Index < RegisterTable->TableLength; Index++, RegisterTableEntry++) { + RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry; + + for (Index = 0; Index < RegisterTable->TableLength; Index++) { + + RegisterTableEntry = &RegisterTableEntryHead[Index]; + + DEBUG_CODE_BEGIN (); + if (ApLocation != NULL) { + AcquireSpinLock (&CpuFlags->ConsoleLogLock); + ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount + + ApLocation->Core * CpuStatus->MaxThreadCount + + ApLocation->Thread; + DEBUG (( + DEBUG_INFO, + "Processor = %lu, Entry Index %lu, Type = %s!\n", + (UINT64)ThreadIndex, + (UINT64)Index, + mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)] + )); + ReleaseSpinLock (&CpuFlags->ConsoleLogLock); + } + DEBUG_CODE_END (); + // // Check the type of specified register // @@ -310,12 +289,6 @@ SetProcessorRegister ( RegisterTableEntry->Value ); } else { - // - // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode - // to make sure MSR read/write operation is atomic. - // - MsrSpinLock = GetMsrSpinLockByIndex (RegisterTableEntry->Index); - AcquireSpinLock (MsrSpinLock); // // Set the bit section according to bit start and length // @@ -325,21 +298,20 @@ SetProcessorRegister ( RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1, RegisterTableEntry->Value ); - ReleaseSpinLock (MsrSpinLock); } break; // // MemoryMapped operations // case MemoryMapped: - AcquireSpinLock (mMemoryMappedLock); + AcquireSpinLock (&CpuFlags->MemoryMappedLock); MmioBitFieldWrite32 ( (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)), RegisterTableEntry->ValidBitStart, RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1, (UINT32)RegisterTableEntry->Value ); - ReleaseSpinLock (mMemoryMappedLock); + ReleaseSpinLock (&CpuFlags->MemoryMappedLock); break; // // Enable or disable cache @@ -355,12 +327,156 @@ SetProcessorRegister ( } break; + case Semaphore: + // Semaphore works logic like below: + // + // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]); + // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]); + // + // All threads (T0...Tn) waits in P() line and continues running + // together. + // + // + // T0 T1 ... Tn + // + // V(0...n) V(0...n) ... V(0...n) + // n * P(0) n * P(1) ... n * P(n) + // + ASSERT ( + (ApLocation != NULL) && + (CpuStatus->ValidCoreCountPerPackage != 0) && + (CpuFlags->CoreSemaphoreCount != NULL) && + (CpuFlags->PackageSemaphoreCount != NULL) + ); + switch (RegisterTableEntry->Value) { + case CoreDepType: + SemaphorePtr = CpuFlags->CoreSemaphoreCount; + // + // Get Offset info for the first thread in the core which current thread belongs to. + // + FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount; + CurrentThread = FirstThread + ApLocation->Thread; + // + // First Notify all threads in current Core that this thread has ready. + // + for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) { + S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]); + } + // + // Second, check whether all valid threads in current core have ready. + // + for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) { + S3WaitForSemaphore (&SemaphorePtr[CurrentThread]); + } + break; + + case PackageDepType: + SemaphorePtr = CpuFlags->PackageSemaphoreCount; + ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage; + // + // Get Offset info for the first thread in the package which current thread belongs to. + // + FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount; + // + // Get the possible threads count for current package. + // + PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; + CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread; + // + // Get the valid thread count for current package. + // + ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package]; + + // + // Different packages may have different valid cores in them. If driver maintail clearly + // cores number in different packages, the logic will be much complicated. + // Here driver just simply records the max core number in all packages and use it as expect + // core number for all packages. + // In below two steps logic, first current thread will Release semaphore for each thread + // in current package. Maybe some threads are not valid in this package, but driver don't + // care. Second, driver will let current thread wait semaphore for all valid threads in + // current package. Because only the valid threads will do release semaphore for this + // thread, driver here only need to wait the valid thread count. + // + + // + // First Notify all threads in current package that this thread has ready. + // + for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) { + S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]); + } + // + // Second, check whether all valid threads in current package have ready. + // + for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) { + S3WaitForSemaphore (&SemaphorePtr[CurrentThread]); + } + break; + + default: + break; + } + break; + default: break; } } } +/** + + Set Processor register for one AP. + + @param PreSmmRegisterTable Use pre Smm register table or register table. + +**/ +VOID +SetRegister ( + IN BOOLEAN PreSmmRegisterTable + ) +{ + CPU_REGISTER_TABLE *RegisterTable; + CPU_REGISTER_TABLE *RegisterTables; + UINT32 InitApicId; + UINTN ProcIndex; + UINTN Index; + + if (PreSmmRegisterTable) { + RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable; + } else { + RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable; + } + + InitApicId = GetInitialApicId (); + RegisterTable = NULL; + ProcIndex = (UINTN)-1; + for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { + if (RegisterTables[Index].InitialApicId == InitApicId) { + RegisterTable = &RegisterTables[Index]; + ProcIndex = Index; + break; + } + } + ASSERT (RegisterTable != NULL); + + if (mAcpiCpuData.ApLocation != 0) { + ProgramProcessorRegister ( + RegisterTable, + (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)mAcpiCpuData.ApLocation + ProcIndex, + &mAcpiCpuData.CpuStatus, + &mCpuFlags + ); + } else { + ProgramProcessorRegister ( + RegisterTable, + NULL, + &mAcpiCpuData.CpuStatus, + &mCpuFlags + ); + } +} + /** AP initialization before then after SMBASE relocation in the S3 boot path. **/ @@ -374,7 +490,7 @@ InitializeAp ( LoadMtrrData (mAcpiCpuData.MtrrTable); - SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus); + SetRegister (TRUE); // // Count down the number with lock mechanism. @@ -391,7 +507,7 @@ InitializeAp ( ProgramVirtualWireMode (); DisableLvtInterrupts (); - SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable, mAcpiCpuData.NumberOfCpus); + SetRegister (FALSE); // // Place AP into the safe code, count down the number with lock mechanism in the safe code. @@ -445,17 +561,11 @@ PrepareApStartupVector ( CopyMem ((VOID *) (UINTN) &mExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR)); CopyMem ((VOID *) (UINTN) &mExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR)); - // - // Copy AP's GDT, IDT and Machine Check handler from SMRAM to ACPI NVS memory - // - CopyMem ((VOID *) mExchangeInfo->GdtrProfile.Base, mGdtForAp, mExchangeInfo->GdtrProfile.Limit + 1); - CopyMem ((VOID *) mExchangeInfo->IdtrProfile.Base, mIdtForAp, mExchangeInfo->IdtrProfile.Limit + 1); - CopyMem ((VOID *)(UINTN) mAcpiCpuData.ApMachineCheckHandlerBase, mMachineCheckHandlerForAp, mAcpiCpuData.ApMachineCheckHandlerSize); - mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress; mExchangeInfo->StackSize = mAcpiCpuData.StackSize; mExchangeInfo->BufferStart = (UINT32) StartupVector; mExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ()); + mExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits; } /** @@ -472,7 +582,7 @@ InitializeCpuBeforeRebase ( { LoadMtrrData (mAcpiCpuData.MtrrTable); - SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus); + SetRegister (TRUE); ProgramVirtualWireMode (); @@ -508,15 +618,24 @@ InitializeCpuAfterRebase ( VOID ) { - SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable, mAcpiCpuData.NumberOfCpus); - mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; // - // Signal that SMM base relocation is complete and to continue initialization. + // Signal that SMM base relocation is complete and to continue initialization for all APs. // mInitApsAfterSmmBaseReloc = TRUE; + // + // Must begin set register after all APs have continue their initialization. + // This is a requirement to support semaphore mechanism in register table. + // Because if semaphore's dependence type is package type, semaphore will wait + // for all Aps in one package finishing their tasks before set next register + // for all APs. If the Aps not begin its task during BSP doing its task, the + // BSP thread will hang because it is waiting for other Aps in the same + // package finishing their task. + // + SetRegister (FALSE); + while (mNumberToFinish > 0) { CpuPause (); } @@ -580,8 +699,6 @@ SmmRestoreCpu ( mSmmS3Flag = TRUE; - InitializeSpinLock (mMemoryMappedLock); - // // See if there is enough context to resume PEI Phase // @@ -720,7 +837,15 @@ InitSmmS3ResumeState ( } GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid); - if (GuidHob != NULL) { + if (GuidHob == NULL) { + DEBUG (( + DEBUG_ERROR, + "ERROR:%a(): HOB(gEfiAcpiVariableGuid=%g) needed by S3 resume doesn't exist!\n", + __FUNCTION__, + &gEfiAcpiVariableGuid + )); + CpuDeadLoop (); + } else { SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob); DEBUG ((EFI_D_INFO, "SMM S3 SMRAM Structure = %x\n", SmramDescriptor)); @@ -740,9 +865,9 @@ InitSmmS3ResumeState ( SmmS3ResumeState->SmmS3StackSize = 0; } - SmmS3ResumeState->SmmS3Cr0 = gSmmCr0; + SmmS3ResumeState->SmmS3Cr0 = mSmmCr0; SmmS3ResumeState->SmmS3Cr3 = Cr3; - SmmS3ResumeState->SmmS3Cr4 = gSmmCr4; + SmmS3ResumeState->SmmS3Cr4 = mSmmCr4; if (sizeof (UINTN) == sizeof (UINT64)) { SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_64; @@ -750,12 +875,12 @@ InitSmmS3ResumeState ( if (sizeof (UINTN) == sizeof (UINT32)) { SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_32; } - } - // - // Patch SmmS3ResumeState->SmmS3Cr3 - // - InitSmmS3Cr3 (); + // + // Patch SmmS3ResumeState->SmmS3Cr3 + // + InitSmmS3Cr3 (); + } // // Allocate safe memory in ACPI NVS for AP to execute hlt loop in @@ -788,7 +913,6 @@ CopyRegisterTable ( ) { UINTN Index; - UINTN Index1; CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry; CopyMem (DestinationRegisterTableList, SourceRegisterTableList, NumberOfCpus * sizeof (CPU_REGISTER_TABLE)); @@ -800,17 +924,6 @@ CopyRegisterTable ( ); ASSERT (RegisterTableEntry != NULL); DestinationRegisterTableList[Index].RegisterTableEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTableEntry; - // - // Go though all MSRs in register table to initialize MSR spin lock - // - for (Index1 = 0; Index1 < DestinationRegisterTableList[Index].TableLength; Index1++, RegisterTableEntry++) { - if ((RegisterTableEntry->RegisterType == Msr) && (RegisterTableEntry->ValidBitLength < 64)) { - // - // Initialize MSR spin lock only for those MSRs need bit field writing - // - InitMsrSpinLockByIndex (RegisterTableEntry->Index); - } - } } } } @@ -827,6 +940,10 @@ GetAcpiCpuData ( ACPI_CPU_DATA *AcpiCpuData; IA32_DESCRIPTOR *Gdtr; IA32_DESCRIPTOR *Idtr; + VOID *GdtForAp; + VOID *IdtForAp; + VOID *MachineCheckHandlerForAp; + CPU_STATUS_INFORMATION *CpuStatus; if (!mAcpiS3Enable) { return; @@ -889,14 +1006,49 @@ GetAcpiCpuData ( Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile; Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile; - mGdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize); - ASSERT (mGdtForAp != NULL); - mIdtForAp = (VOID *) ((UINTN)mGdtForAp + (Gdtr->Limit + 1)); - mMachineCheckHandlerForAp = (VOID *) ((UINTN)mIdtForAp + (Idtr->Limit + 1)); - - CopyMem (mGdtForAp, (VOID *)Gdtr->Base, Gdtr->Limit + 1); - CopyMem (mIdtForAp, (VOID *)Idtr->Base, Idtr->Limit + 1); - CopyMem (mMachineCheckHandlerForAp, (VOID *)(UINTN)mAcpiCpuData.ApMachineCheckHandlerBase, mAcpiCpuData.ApMachineCheckHandlerSize); + GdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize); + ASSERT (GdtForAp != NULL); + IdtForAp = (VOID *) ((UINTN)GdtForAp + (Gdtr->Limit + 1)); + MachineCheckHandlerForAp = (VOID *) ((UINTN)IdtForAp + (Idtr->Limit + 1)); + + CopyMem (GdtForAp, (VOID *)Gdtr->Base, Gdtr->Limit + 1); + CopyMem (IdtForAp, (VOID *)Idtr->Base, Idtr->Limit + 1); + CopyMem (MachineCheckHandlerForAp, (VOID *)(UINTN)mAcpiCpuData.ApMachineCheckHandlerBase, mAcpiCpuData.ApMachineCheckHandlerSize); + + Gdtr->Base = (UINTN)GdtForAp; + Idtr->Base = (UINTN)IdtForAp; + mAcpiCpuData.ApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MachineCheckHandlerForAp; + + CpuStatus = &mAcpiCpuData.CpuStatus; + CopyMem (CpuStatus, &AcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION)); + if (AcpiCpuData->CpuStatus.ValidCoreCountPerPackage != 0) { + CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool ( + sizeof (UINT32) * CpuStatus->PackageCount, + (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ValidCoreCountPerPackage + ); + ASSERT (CpuStatus->ValidCoreCountPerPackage != 0); + } + if (AcpiCpuData->ApLocation != 0) { + mAcpiCpuData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool ( + mAcpiCpuData.NumberOfCpus * sizeof (EFI_CPU_PHYSICAL_LOCATION), + (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ); + ASSERT (mAcpiCpuData.ApLocation != 0); + } + if (CpuStatus->PackageCount != 0) { + mCpuFlags.CoreSemaphoreCount = AllocateZeroPool ( + sizeof (UINT32) * CpuStatus->PackageCount * + CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount + ); + ASSERT (mCpuFlags.CoreSemaphoreCount != NULL); + mCpuFlags.PackageSemaphoreCount = AllocateZeroPool ( + sizeof (UINT32) * CpuStatus->PackageCount * + CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount + ); + ASSERT (mCpuFlags.PackageSemaphoreCount != NULL); + } + InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock); + InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.ConsoleLogLock); } /**