From a674eea1c47a6aa0170b2beb07d4f2bbefc798e0 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 19:41:14 +0800 Subject: BroxtonSiPkg: Add Cpu Include file and Library Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h | 229 +++++++ .../Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c | 753 +++++++++++++++++++++ .../Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h | 45 ++ .../Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc | 49 ++ .../Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S | 210 ++++++ .../Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm | 206 ++++++ .../Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf | 59 ++ 7 files changed, 1551 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib') diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h new file mode 100644 index 0000000000..3ab1813b75 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h @@ -0,0 +1,229 @@ +/** @file + Definitions for S3 Resume. + + Copyright (c) 2014 - 2016, 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. + +**/ + +#ifndef _CPU_S3_ +#define _CPU_S3_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CpuAccess.h" + +#define VacantFlag 0x00 +#define NotVacantFlag 0xff + +#define MICROSECOND 10 + +#define MAXIMUM_CPU_NUMBER 0x40 +#define STACK_SIZE_PER_PROC 0x8000 + +#define MAXIMUM_CPU_S3_TABLE_SIZE 0x1000 + +#define IO_APIC_INDEX_REGISTER 0xFEC00000 +#define IO_APIC_DATA_REGISTER 0xFEC00010 + +extern UINTN FixedMtrrNumber; +extern UINTN MtrrDefTypeNumber; + +typedef struct { + UINT16 Index; + UINT64 Value; +} EFI_MTRR_VALUES; + +typedef struct { + UINT32 ApicId; + UINT32 MsrIndex; + UINT64 MsrValue; +} MP_CPU_S3_SCRIPT_DATA; + +typedef struct { + UINT32 S3BootScriptTable; + UINT32 S3BspMtrrTable; + UINT32 VirtualWireMode; +} MP_CPU_S3_DATA_POINTER; + +typedef struct { + UINT32 Lock; + UINT32 StackStart; + UINT32 StackSize; + UINT32 ApFunction; + IA32_DESCRIPTOR GdtrProfile; + IA32_DESCRIPTOR IdtrProfile; + UINT32 BufferStart; + UINT32 PmodeOffset; + UINT32 AcpiCpuDataAddress; + UINT32 MtrrValuesAddress; + UINT32 FinishedCount; + UINT32 WakeupCount; + UINT32 SerializeLock; + MP_CPU_S3_SCRIPT_DATA *S3BootScriptTable; + UINT32 StartState; + UINT32 VirtualWireMode; + VOID (*SemaphoreCheck)(UINT32 *SemaphoreAddress); + UINT32 McuLoadCount; + IN CONST EFI_PEI_SERVICES **PeiServices; + UINT64 CpuPerfCtrlValue; + SI_CPU_POLICY_PPI *SiCpuPolicyPpi; +} MP_CPU_EXCHANGE_INFO; + +/** + Get protected mode code offset + + @retval Offset of protected mode code + +**/ +VOID * +S3AsmGetPmodeOffset ( + VOID + ); + +/** + Get code offset of SemaphoreCheck + + @retval Offset of SemaphoreCheck + +**/ +UINT32 +S3AsmGetSemaphoreCheckOffset ( + VOID + ); + +/** + Read MTRR settings + + @param[in] MtrrValues Buffer to store MTRR settings + +**/ +VOID +ReadMtrrRegisters ( + UINT64 *MtrrValues + ); + +/** + Syncup MTRR settings between all processors + + @param[in] MtrrValues Buffer to store MTRR settings + +**/ +VOID +MpMtrrSynchUp ( + UINT64 *MtrrValues + ); + +/** + Set MTRR registers + + @param[in] MtrrArray Buffer with MTRR settings + +**/ +VOID +SetMtrrRegisters ( + IN EFI_MTRR_VALUES *MtrrArray + ); + +#ifdef EFI_DEBUG +/** + Print MTRR settings in debug build BIOS + + @param[in] MtrrArray Buffer with MTRR settings + +**/ +VOID +ShowMtrrRegisters ( + IN EFI_MTRR_VALUES *MtrrArray + ); +#endif + +/** + This will check if the microcode address is valid for this processor, and if so, it will + load it to the processor. + + @param[in] ExchangeInfo Pointer to the exchange info buffer for output. + @param[in] MicrocodeAddress The address of the microcode update binary (in memory). + @param[out] FailedRevision The microcode revision that fails to be loaded. + + @retval EFI_SUCCESS A new microcode update is loaded. + @retval Other Due to some reason, no new microcode update is loaded. + +**/ +EFI_STATUS +InitializeMicrocode ( + IN MP_CPU_EXCHANGE_INFO *ExchangeInfo, + IN CPU_MICROCODE_HEADER *MicrocodeAddress, + OUT UINT32 *FailedRevision + ); + +/// +/// Functions shared in MP/HT drivers +/// +/** + Send interrupt to CPU + + @param[in] BroadcastMode Interrupt broadcast mode + @param[in] ApicID APIC ID for sending interrupt + @param[in] VectorNumber Vector number + @param[in] DeliveryMode Interrupt delivery mode + @param[in] TriggerMode Interrupt trigger mode + @param[in] Assert Interrupt pin polarity + + @retval EFI_INVALID_PARAMETER Input parameter not correct + @retval EFI_NOT_READY There was a pending interrupt + @retval EFI_SUCCESS Interrupt sent successfully + +**/ +EFI_STATUS +SendInterrupt ( + IN UINT32 BroadcastMode, + IN UINT32 ApicID, + IN UINT32 VectorNumber, + IN UINT32 DeliveryMode, + IN UINT32 TriggerMode, + IN BOOLEAN Assert + ); + +/** + Programs Local APIC registers for virtual wire mode. + + @param[in] BSP Is this BSP? + +**/ +VOID +ProgramXApic ( + BOOLEAN BSP + ); + +/** + Get address map of S3RendezvousFunnelProc. + + @retval AddressMap Output buffer for address map information + +**/ +VOID * +S3AsmGetAddressMap ( + VOID + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c new file mode 100644 index 0000000000..8c4c8f34ee --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c @@ -0,0 +1,753 @@ +/** @file + Cpu S3 library running on S3 resume paths. + + Copyright (c) 2014 - 2016, 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. + +**/ + +#include +#include "CpuS3.h" +#include +#include + +extern EFI_GUID gSmramCpuDataHeaderGuid; +extern EFI_GUID gPeiAcpiCpuDataGuid; + +typedef VOID (*S3_AP_PROCEDURE) ( + MP_CPU_EXCHANGE_INFO *ExchangeInfo, + UINT64 *MtrrValues + ); + +/** + This function handles CPU S3 resume task at the end of PEI + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDesc Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi Pointer to the PPI data associated with this function. + + @retval EFI_STATUS Always return EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +CpuS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ); + + +STATIC EFI_PEI_NOTIFY_DESCRIPTOR mCpuS3ResumeNotifyDesc = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + CpuS3ResumeAtEndOfPei +}; + + +/** + Restore all MSR settings + + @param[in] ScriptTable Contain the MSR settings that will be restored. + +**/ +VOID +InitializeFeatures ( + IN MP_CPU_S3_SCRIPT_DATA *ScriptTable + ) +{ + EFI_CPUID_REGISTER CpuidRegisters; + UINT32 ApicId; + UINT8 SkipMsr; + + // + // Restore all the MSRs for processor + // + AsmCpuid ( + CPUID_VERSION_INFO, + &CpuidRegisters.RegEax, + &CpuidRegisters.RegEbx, + &CpuidRegisters.RegEcx, + &CpuidRegisters.RegEdx + ); + ApicId = (CpuidRegisters.RegEbx >> 24); + + while (ScriptTable->MsrIndex != 0) { + if (ApicId == ScriptTable->ApicId) { + SkipMsr = 0; + if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) { + SkipMsr = 1; + } + if ((ScriptTable->MsrIndex == MSR_IA32_FEATURE_CONTROL) && (AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL) & B_MSR_IA32_FEATURE_CONTROL_LOCK)) { + SkipMsr = 1; + } + if (SkipMsr == 0) { + AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue); + } + } + ScriptTable++; + } +} + + +/** + Restore all MSR settings with debug message output + + @param[in] ScriptTable Script table contain all MSR settings that will be restored + +**/ +VOID +InitializeFeaturesLog ( + IN MP_CPU_S3_SCRIPT_DATA *ScriptTable + ) +{ + EFI_CPUID_REGISTER CpuidRegisters; + UINT32 ApicId; + BOOLEAN SkipMsr; + + PostCode (0xC41); + + // + // Restore all the MSRs for processor + // + AsmCpuid ( + CPUID_VERSION_INFO, + &CpuidRegisters.RegEax, + &CpuidRegisters.RegEbx, + &CpuidRegisters.RegEcx, + &CpuidRegisters.RegEdx + ); + ApicId = (CpuidRegisters.RegEbx >> 24); + + while (ScriptTable->MsrIndex != 0) { + if (ApicId == ScriptTable->ApicId) { + DEBUG ((DEBUG_INFO, "MSR Index - %x, MSR value - %x\n", ScriptTable->MsrIndex, ScriptTable->MsrValue)); + SkipMsr = FALSE; + if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) { + SkipMsr = TRUE; + } + if ((ScriptTable->MsrIndex == MSR_IA32_FEATURE_CONTROL) && (AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL) & B_MSR_IA32_FEATURE_CONTROL_LOCK)) { + SkipMsr = TRUE; + } + if (ScriptTable->MsrIndex == MSR_IA32_DEBUG_INTERFACE) { + // + // Debug interface is supported if CPUID (EAX=1): ECX[11] = 1 + // + if ((CpuidRegisters.RegEcx & BIT11) && (AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE) & B_DEBUG_INTERFACE_LOCK)) { + SkipMsr = TRUE; + } + } + if (!SkipMsr) { + AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue); + } + } + ScriptTable++; + } + PostCode (0xC44); +} + + +/** + AP initialization + + @param[in] ExchangeInfo Pointer to the exchange info buffer for output. + @param[in] MtrrValues Buffer contains MTRR settings + +**/ +VOID +MPRendezvousProcedure ( + MP_CPU_EXCHANGE_INFO *ExchangeInfo, + UINT64 *MtrrValues + ) +{ + EFI_STATUS Status; + UINT32 FailedRevision; + ACPI_CPU_DATA *AcpiCpuData; + MP_CPU_S3_DATA_POINTER *CpuS3DataPtr; + EFI_CPUID_REGISTER CpuidRegisters; + CPU_CONFIG *CpuConfig; + + Status = GetConfigBlock ((CONFIG_BLOCK_TABLE_HEADER *) ExchangeInfo->SiCpuPolicyPpi, &gCpuConfigGuid , (VOID *) &CpuConfig); + ASSERT_EFI_ERROR (Status); + + AsmCpuid ( + CPUID_VERSION_INFO, + &CpuidRegisters.RegEax, + &CpuidRegisters.RegEbx, + &CpuidRegisters.RegEcx, + &CpuidRegisters.RegEdx + ); + + // + // Init XMM support on all APs + // + XmmInit (); + + // + // Switch AP speed to BSP speed + // + if ((CpuidRegisters.RegEcx & B_CPUID_VERSION_INFO_ECX_EIST) != 0) { + AsmWriteMsr64 (MSR_IA32_PERF_CTRL, ExchangeInfo->CpuPerfCtrlValue); + } + + AcpiCpuData = (ACPI_CPU_DATA *) (ExchangeInfo->AcpiCpuDataAddress); + + ProgramXApic (FALSE); + + InitializeFeatures (ExchangeInfo->S3BootScriptTable); + + InterlockedIncrement (&(ExchangeInfo->SerializeLock)); + while (ExchangeInfo->SerializeLock < AcpiCpuData->NumberOfCpus) { + CpuPause (); + } + + InitializeMicrocode ( + ExchangeInfo, + (CPU_MICROCODE_HEADER *) (UINTN) CpuConfig->MicrocodePatchAddress, + &FailedRevision + ); + + ProcessorsPrefetcherInitialization ( + CpuConfig->MlcStreamerPrefetcher, + CpuConfig->MlcSpatialPrefetcher + ); + + // + // wait till all CPUs done the Microcode Load + // + while (ExchangeInfo->McuLoadCount < AcpiCpuData->NumberOfCpus) { + CpuPause (); + } + + MpMtrrSynchUp (MtrrValues); + + InterlockedIncrement (&(ExchangeInfo->FinishedCount)); + + // + // Sempahore check loop executed in memory + // + (*ExchangeInfo->SemaphoreCheck) (&ExchangeInfo->FinishedCount); + + InterlockedIncrement (&(ExchangeInfo->WakeupCount)); + + // + // Restore the MTRR programmed before OS boot + // + CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData; + SetMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable); + + while (ExchangeInfo->WakeupCount < AcpiCpuData->NumberOfCpus - 1) { + CpuPause (); + } + + InterlockedIncrement (&(ExchangeInfo->FinishedCount)); +} + + +/** + Wake up all the application processors + + @param[in] PeiServices Indirect reference to the PEI Services Table + @param[in] AcpiCpuData Pointer to ACPI_CPU_DATA structure + @param[in] MtrrValues Pointer to a buffer which stored MTRR settings + + @retval EFI_SUCCESS APs are successfully waked up + +**/ +EFI_STATUS +S3WakeUpAps ( + IN CONST EFI_PEI_SERVICES **PeiServices, + ACPI_CPU_DATA *AcpiCpuData, + UINT64 *MtrrValues, + S3_AP_PROCEDURE Function + ) +{ + EFI_PHYSICAL_ADDRESS WakeUpBuffer; + MP_CPU_EXCHANGE_INFO *ExchangeInfo; + MP_CPU_S3_DATA_POINTER *CpuS3DataPtr; + + PostCode (0xC45); + WakeUpBuffer = AcpiCpuData->WakeUpBuffer; + CopyMem ((VOID *) (UINTN) WakeUpBuffer, S3AsmGetAddressMap (), 0x1000 - 0x200); + + ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200)); + + ExchangeInfo->Lock = 0; + ExchangeInfo->StackStart = (UINTN) AcpiCpuData->StackAddress; + ExchangeInfo->StackSize = STACK_SIZE_PER_PROC; + ExchangeInfo->ApFunction = (UINT32) Function; + ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer; + ExchangeInfo->PmodeOffset = (UINT32) (S3AsmGetPmodeOffset ()); + ExchangeInfo->SemaphoreCheck = (VOID (*)(UINT32 *)) (S3AsmGetSemaphoreCheckOffset () + (UINT32) WakeUpBuffer); + ExchangeInfo->AcpiCpuDataAddress = (UINT32) AcpiCpuData; + ExchangeInfo->MtrrValuesAddress = (UINT32) MtrrValues; + ExchangeInfo->FinishedCount = (UINT32) 0; + ExchangeInfo->SerializeLock = (UINT32) 0; + ExchangeInfo->StartState = (UINT32) 0; + + CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData; + ExchangeInfo->S3BootScriptTable = (MP_CPU_S3_SCRIPT_DATA *) (UINTN) CpuS3DataPtr->S3BootScriptTable; + ExchangeInfo->VirtualWireMode = CpuS3DataPtr->VirtualWireMode; + ExchangeInfo->PeiServices = PeiServices; + ExchangeInfo->CpuPerfCtrlValue = AsmReadMsr64 (MSR_IA32_PERF_CTRL); + + ExchangeInfo->SiCpuPolicyPpi = NULL; + PeiServicesLocatePpi ( + &gSiCpuPolicyPpiGuid, + 0, + NULL, + (VOID **) &(ExchangeInfo->SiCpuPolicyPpi) + ); + + CopyMem ( + (VOID *) (UINTN) &ExchangeInfo->GdtrProfile, + (VOID *) (UINTN) AcpiCpuData->GdtrProfile, + sizeof (IA32_DESCRIPTOR) + ); + CopyMem ( + (VOID *) (UINTN) &ExchangeInfo->IdtrProfile, + (VOID *) (UINTN) AcpiCpuData->IdtrProfile, + sizeof (IA32_DESCRIPTOR) + ); + + DEBUG ((DEBUG_INFO, "Cpu S3 Bootscript at %08X\n", (UINT32) ExchangeInfo->S3BootScriptTable)); + + // + // Don't touch MPCPU private data + // Here we use ExchangeInfo instead + // + // + // Send INIT IPI - SIPI to all APs + // + SendInterrupt ( + BROADCAST_MODE_ALL_EXCLUDING_SELF, + 0, + 0, + DELIVERY_MODE_INIT, + TRIGGER_MODE_EDGE, + TRUE + ); + + MicroSecondDelay (10 * STALL_ONE_MILLI_SECOND); //< 10ms + + SendInterrupt ( + BROADCAST_MODE_ALL_EXCLUDING_SELF, + 0, + (UINT32) RShiftU64 (WakeUpBuffer, 12), + DELIVERY_MODE_SIPI, + TRIGGER_MODE_EDGE, + TRUE + ); + + MicroSecondDelay (200 * STALL_ONE_MICRO_SECOND); //< 200us + + SendInterrupt ( + BROADCAST_MODE_ALL_EXCLUDING_SELF, + 0, + (UINT32) RShiftU64 (WakeUpBuffer, 12), + DELIVERY_MODE_SIPI, + TRIGGER_MODE_EDGE, + TRUE + ); + + MicroSecondDelay (200 * STALL_ONE_MICRO_SECOND); //< 200us + PostCode (0xC48); + + return EFI_SUCCESS; +} + + +/** + This routine is used to search SMRAM and get SmramCpuData point. + + @param[in] PeiServices PEI services global pointer + @param[in] SmmAccessPpi SmmAccess PPI instance + + @retval SmramCpuData The pointer of CPU information in SMRAM. + +**/ +STATIC +SMRAM_CPU_DATA * +GetSmmCpuData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *SmmAccessPpi + ) +{ + EFI_SMRAM_DESCRIPTOR *SmramRanges; + UINTN SmramRangeCount; + UINTN Size; + EFI_STATUS Status; + UINT32 Address; + SMRAM_CPU_DATA *SmramCpuData; + + // + // Get all SMRAM range + // + Size = 0; + Status = SmmAccessPpi->GetCapabilities ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + Status = PeiServicesAllocatePool ( + Size, + (VOID **) &SmramRanges + ); + ASSERT_EFI_ERROR (Status); + + Status = SmmAccessPpi->GetCapabilities ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, &Size, SmramRanges); + ASSERT_EFI_ERROR (Status); + + Size /= sizeof (*SmramRanges); + SmramRangeCount = Size; + + // + // We assume TSEG is the last range of SMRAM in SmramRanges + // + SmramRanges += SmramRangeCount - 1; + + DEBUG ((DEBUG_INFO, "TsegBase - %x\n", SmramRanges->CpuStart)); + DEBUG ((DEBUG_INFO, "TsegTop - %x\n", SmramRanges->CpuStart + SmramRanges->PhysicalSize)); + + // + // Search SMRAM on page alignment for the SMMNVS signature + // + for (Address = (UINT32) (SmramRanges->CpuStart + SmramRanges->PhysicalSize - EFI_PAGE_SIZE); + Address >= (UINT32) SmramRanges->CpuStart; + Address -= EFI_PAGE_SIZE + ) { + SmramCpuData = (SMRAM_CPU_DATA *) (UINTN) Address; + if (CompareGuid (&SmramCpuData->HeaderGuid, &gSmramCpuDataHeaderGuid)) { + return SmramCpuData; + } + } + + ASSERT (FALSE); + + return NULL; +} + +/** + This routine is restore the CPU information from SMRAM to original reserved memory region. + + @param[in] PeiServices PEI services global pointer + + @retval AcpiCpuData The pointer of CPU information in reserved memory. + +**/ +ACPI_CPU_DATA * +RestoreSmramCpuData ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + PEI_SMM_ACCESS_PPI *SmmAccessPpi; + SMRAM_CPU_DATA *SmramCpuData; + EFI_STATUS Status; + ACPI_CPU_DATA *AcpiCpuData; + MP_CPU_S3_DATA_POINTER *CpuS3DataPtr; + IA32_DESCRIPTOR *Idtr; + IA32_DESCRIPTOR *Gdtr; + UINTN Index; + + Status = PeiServicesLocatePpi ( + &gPeiSmmAccessPpiGuid, + 0, + NULL, + (VOID **) &SmmAccessPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Open all SMM regions + // + Index = 0; + do { + Status = SmmAccessPpi->Open ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, Index); + Index++; + } while (!EFI_ERROR (Status)); + + SmramCpuData = GetSmmCpuData ((CONST EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi); + if (SmramCpuData == NULL) { + ASSERT (FALSE); + return NULL; + } + DEBUG ((DEBUG_INFO, "CpuS3 SmramCpuData - 0x%x \n", SmramCpuData)); + DEBUG ((DEBUG_INFO, "SmramCpuData->GdtrProfileSize - %x\n", SmramCpuData->GdtrProfileSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->GdtSize - %x\n", SmramCpuData->GdtSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->IdtrProfileSize - %x\n", SmramCpuData->IdtrProfileSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->IdtSize - %x\n", SmramCpuData->IdtSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->CpuPrivateDataSize - %x\n", SmramCpuData->CpuPrivateDataSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->S3BootScriptTableSize - %x\n", SmramCpuData->S3BootScriptTableSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->S3BspMtrrTableSize - %x\n", SmramCpuData->S3BspMtrrTableSize)); + DEBUG ((DEBUG_INFO, "SmramCpuData->GdtrProfileOffset - %x\n", SmramCpuData->GdtrProfileOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->GdtOffset - %x\n", SmramCpuData->GdtOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->IdtrProfileOffset - %x\n", SmramCpuData->IdtrProfileOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->IdtOffset - %x\n", SmramCpuData->IdtOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->CpuPrivateDataOffset - %x\n", SmramCpuData->CpuPrivateDataOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->S3BootScriptTableOffset - %x\n", SmramCpuData->S3BootScriptTableOffset)); + DEBUG ((DEBUG_INFO, "SmramCpuData->S3BspMtrrTableOffset - %x\n", SmramCpuData->S3BspMtrrTableOffset)); + + // + // Start restore data to NVS + // + AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) SmramCpuData->AcpiCpuPointer; + CopyMem (AcpiCpuData, &SmramCpuData->AcpiCpuData, sizeof (ACPI_CPU_DATA)); + + CopyMem ( + (VOID *) (UINTN) AcpiCpuData->GdtrProfile, + (UINT8 *) SmramCpuData + SmramCpuData->GdtrProfileOffset, + SmramCpuData->GdtrProfileSize + ); + Gdtr = (IA32_DESCRIPTOR *) (UINTN) AcpiCpuData->GdtrProfile; + CopyMem ( + (VOID *) (UINTN) Gdtr->Base, + (UINT8 *) SmramCpuData + SmramCpuData->GdtOffset, + SmramCpuData->GdtSize + ); + CopyMem ( + (VOID *) (UINTN) AcpiCpuData->IdtrProfile, + (UINT8 *) SmramCpuData + SmramCpuData->IdtrProfileOffset, + SmramCpuData->IdtrProfileSize + ); + Idtr = (IA32_DESCRIPTOR *) (UINTN) AcpiCpuData->IdtrProfile; + CopyMem ( + (VOID *) (UINTN) Idtr->Base, + (UINT8 *) SmramCpuData + SmramCpuData->IdtOffset, + SmramCpuData->IdtSize + ); + CopyMem ( + (VOID *) (UINTN) AcpiCpuData->CpuPrivateData, + (UINT8 *) SmramCpuData + SmramCpuData->CpuPrivateDataOffset, + SmramCpuData->CpuPrivateDataSize + ); + CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData; + CopyMem ( + (VOID *) (UINTN) CpuS3DataPtr->S3BootScriptTable, + (UINT8 *) SmramCpuData + SmramCpuData->S3BootScriptTableOffset, + SmramCpuData->S3BootScriptTableSize + ); + CopyMem ( + (VOID *) (UINTN) CpuS3DataPtr->S3BspMtrrTable, + (UINT8 *) SmramCpuData + SmramCpuData->S3BspMtrrTableOffset, + SmramCpuData->S3BspMtrrTableSize + ); + // + // Close all SMM regions + // + Index = 0; + do { + Status = SmmAccessPpi->Close ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, Index); + Index++; + } while (!EFI_ERROR (Status)); + + return AcpiCpuData; +} + + +/** + Cpu initialization called during S3 resume to take care + of CPU related activities in PEI phase + + @param[in] PeiServices Indirect reference to the PEI Services Table + + @retval EFI_SUCCESS Multiple processors are intialized successfully. + +**/ +EFI_STATUS +S3InitializeCpu ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + ACPI_CPU_DATA *AcpiCpuData; + UINT64 *MtrrValues; + MP_CPU_S3_DATA_POINTER *CpuS3DataPtr; + UINTN VariableMtrrNumber; + EFI_PHYSICAL_ADDRESS WakeUpBuffer; + MP_CPU_EXCHANGE_INFO *ExchangeInfo; + UINT32 FailedRevision; + VOID *Hob; + EFI_BOOT_MODE BootMode; + CPU_CONFIG *CpuConfig; + + Status = PeiServicesGetBootMode (&BootMode); + DEBUG ((DEBUG_INFO, "CPU: BootMode = %X\n", BootMode)); + if ((Status == EFI_SUCCESS) && (BootMode != BOOT_ON_S3_RESUME)) { + DEBUG ((DEBUG_INFO,"CPU: Normal Boot\n")); + return EFI_SUCCESS; + } + + DEBUG((DEBUG_INFO, "S3InitializeCpu Start \n")); + PostCode (0xC40); + + // + // Restore ACPI Nvs data from SMRAM + // + AcpiCpuData = RestoreSmramCpuData ((CONST EFI_PEI_SERVICES **) PeiServices); + if (AcpiCpuData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((DEBUG_INFO, "CpuS3 RestoreSmramCpuData - 0x%x \n", AcpiCpuData)); + + AcpiCpuData->S3BootPath = TRUE; + + CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData; + + VariableMtrrNumber = (UINTN) ((UINT64) AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT) * 2; + Status = PeiServicesAllocatePool ( + (FixedMtrrNumber + MtrrDefTypeNumber + VariableMtrrNumber) * sizeof (UINT64), + (VOID **) &MtrrValues + ); + ASSERT_EFI_ERROR (Status); + ReadMtrrRegisters (MtrrValues); + + WakeUpBuffer = AcpiCpuData->WakeUpBuffer; + ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200)); + ExchangeInfo->WakeupCount = (UINT32) 0; + ExchangeInfo->FinishedCount = (UINT32) 0; + ExchangeInfo->SerializeLock = (UINT32) 0; + + // + // Restore features for BSP + // + InitializeFeaturesLog ((MP_CPU_S3_SCRIPT_DATA *) CpuS3DataPtr->S3BootScriptTable); + + // + // Restore AP configuration + // + S3WakeUpAps ((CONST EFI_PEI_SERVICES **)PeiServices, AcpiCpuData, MtrrValues, MPRendezvousProcedure); + + // + // Program XApic register + // + ProgramXApic ( + TRUE + ); + + InterlockedIncrement (&(ExchangeInfo->SerializeLock)); + while (ExchangeInfo->SerializeLock < AcpiCpuData->NumberOfCpus) { + CpuPause (); + } + + Status = GetConfigBlock ((CONFIG_BLOCK_TABLE_HEADER *) ExchangeInfo->SiCpuPolicyPpi, &gCpuConfigGuid , (VOID *) &CpuConfig); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "Initialize Microcode Start \n")); + PostCode (0xC49); + InitializeMicrocode ( + ExchangeInfo, + (CPU_MICROCODE_HEADER *) (UINTN) CpuConfig->MicrocodePatchAddress, + &FailedRevision + ); + + DEBUG ((DEBUG_INFO, "BuildGuid Data Hob Start \n")); + PostCode (0xC4D); + // + // Save acpi cpu data into one hob, it will be used by a callback when End of Pei Signal installed. + // + Hob = BuildGuidDataHob ( + &gPeiAcpiCpuDataGuid, + (VOID *) (UINTN) AcpiCpuData, + (UINTN) sizeof (ACPI_CPU_DATA) + ); + ASSERT (Hob != NULL); + DEBUG ((DEBUG_INFO, "CPU S3: Register notification to be trigerred at End of Pei event\n")); + Status = PeiServicesNotifyPpi (&mCpuS3ResumeNotifyDesc); + ASSERT_EFI_ERROR (Status); + + // + // Wait for all APs to complete + // + while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) { + CpuPause (); + } + + DEBUG ((DEBUG_INFO, "S3InitializeCpu Done \n")); + PostCode (0xC5F); + + return EFI_SUCCESS; +} + + +/** + This function handles CPU S3 resume task at the end of PEI + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDesc Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi Pointer to the PPI data associated with this function. + + @retval EFI_STATUS Always return EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +CpuS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ) +{ + ACPI_CPU_DATA *AcpiCpuData; + EFI_PHYSICAL_ADDRESS WakeUpBuffer; + MP_CPU_S3_DATA_POINTER *CpuS3DataPtr; + MP_CPU_EXCHANGE_INFO *ExchangeInfo; + VOID *Hob; + + DEBUG ((DEBUG_INFO, "Cpu S3 callback Entry\n")); + + PostCode (0xC51); + + // + // Find the saved acpi cpu data from HOB. + // + AcpiCpuData = NULL; + Hob = GetFirstGuidHob (&gPeiAcpiCpuDataGuid); + if (Hob != NULL) { + AcpiCpuData = (ACPI_CPU_DATA *) ((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE)); + ASSERT (AcpiCpuData != NULL); + if (AcpiCpuData == NULL) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + + WakeUpBuffer = AcpiCpuData->WakeUpBuffer; + ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200)); + + // + // Have APs to continue the task - Restore S3BspMtrrTable + // + ExchangeInfo->WakeupCount = (UINT32) 0; + ExchangeInfo->FinishedCount = (UINT32) 0; + + // + // Set MTRR to the final values + // Do not do it too early so as to avoid performance penalty + // + CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData; + +#ifdef EFI_DEBUG + ShowMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable); +#endif + + SetMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable); + + MicroSecondDelay (1 * STALL_ONE_MILLI_SECOND); //< 1ms + + while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) { + CpuPause (); + } + PostCode (0xC54); + + return EFI_SUCCESS; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h new file mode 100644 index 0000000000..d8ec879d1e --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h @@ -0,0 +1,45 @@ +/** @file + This is the equates file for HT (Hyper-threading) support. + + Copyright (c) 1999 - 2016, 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. + +**/ + +#define VacantFlag 0x00 +#define NotVacantFlag 0xff + +#define LockLocation (0x1000 - 0x0200) +#define StackStartAddressLocation (LockLocation + 0x04) +#define StackSizeLocation (LockLocation + 0x08) +#define CProcedureLocation (LockLocation + 0x0C) +#define GdtrLocation (LockLocation + 0x10) +#define IdtrLocation (LockLocation + 0x16) +#define BufferStartLocation (LockLocation + 0x1C) +#define PmodeOffsetLocation (LockLocation + 0x20) +#define AcpiCpuDataAddressLocation (LockLocation + 0x24) +#define MtrrValuesAddressLocation (LockLocation + 0x28) +#define FinishedCountAddressLocation (LockLocation + 0x2C) +#define WakeupCountAddressLocation (LockLocation + 0x30) +#define SerializeLockAddressLocation (LockLocation + 0x34) +#define MicrocodeAddressLocation (LockLocation + 0x38) +#define BootScriptAddressLocation (LockLocation + 0x3C) +#define StartStateLocation (LockLocation + 0x40) +#define VirtualWireMode (LockLocation + 0x44) +#define SemaphoreCheck (LockLocation + 0x48) +#define PeiServices (LockLocation + 0x4C) +#define PeiStall (LockLocation + 0x50) +#define CpuPerfCtrlValue (LockLocation + 0x54) +#define SiCpuPolicyPpi (LockLocation + 0x5C) +#define MpSystemDataAddressLocation (LockLocation + 0x64) +#define MpServicePpiAddressLocation (LockLocation + 0x68) +#define CArgumentLocation (LockLocation + 0x6C) +#define BistBufferLocation (LockLocation + 0x70) + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc new file mode 100644 index 0000000000..8fa3dc30a9 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc @@ -0,0 +1,49 @@ +;; @file +; This is the equates file used in MpFuncs.asm, for MP support. +; +; Copyright (c) 1999 - 2016, 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 +; +;; + +VacantFlag Equ 00h +NotVacantFlag Equ 0ffh + +LockLocation equ 1000h - 0200h +StackStartAddressLocation equ LockLocation + 04h +StackSizeLocation equ LockLocation + 08h +CProcedureLocation equ LockLocation + 0Ch +GdtrLocation equ LockLocation + 10h +IdtrLocation equ LockLocation + 16h +BufferStartLocation equ LockLocation + 1Ch +PmodeOffsetLocation equ LockLocation + 20h +AcpiCpuDataAddressLocation equ LockLocation + 24h +MtrrValuesAddressLocation equ LockLocation + 28h +FinishedCountAddressLocation equ LockLocation + 2Ch +WakeupCountAddressLocation equ LockLocation + 30h +SerializeLockAddressLocation equ LockLocation + 34h +MicrocodeAddressLocation equ LockLocation + 38h +BootScriptAddressLocation equ LockLocation + 3Ch +StartStateLocation equ LockLocation + 40h +VirtualWireMode equ LockLocation + 44h +SemaphoreCheck equ LockLocation + 48h +PeiServices equ LockLocation + 4Ch +PeiStall equ LockLocation + 50h +CpuPerfCtrlValue equ LockLocation + 54h +SiCpuPolicyPpi equ LockLocation + 5Ch +MpSystemDataAddressLocation equ LockLocation + 64h +MpServicePpiAddressLocation equ LockLocation + 68h +CArgumentLocation equ LockLocation + 6Ch +BistBufferLocation equ LockLocation + 70h + +PAUSE32 MACRO + DB 0F3h + DB 090h + ENDM diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S new file mode 100644 index 0000000000..8127ec30f8 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S @@ -0,0 +1,210 @@ +## @file +# This is the assembly code for MP support. +# +# Copyright (c) 1999 - 2016, 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 +# +## + +#include "MpEqu.h" + + .text + ASM_FUNCTION_REMOVE_IF_UNREFERENCED + +//------------------------------------------------------------------------------------- +//S3RendezvousFunnelProc procedure follows. All APs execute their procedure. This +//procedure serializes all the AP processors through an Init sequence. It must be +//noted that APs arrive here very raw...ie: real mode, no stack. +//ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC +//IS IN MACHINE CODE. +//------------------------------------------------------------------------------------- +//S3RendezvousFunnelProc (&WakeUpBuffer,MemAddress); + +.globl ASM_PFX(S3RendezvousFunnelProc) +ASM_PFX(S3RendezvousFunnelProc): +L_S3RendezvousFunnelProcStart: + + .code16 + +// At this point CS = 0x(vv00) and ip= 0x0. + mov %eax, %ebp + mov %cs, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + xor %ax, %ax + mov %ax, %fs + mov %ax, %gs + +// Get APIC ID + mov $1, %eax + cpuid + shr $24, %ebx + and $0xff, %ebx // EBX is APIC ID + +// If it is the first time AP wakes up, just record AP's BIST +// Otherwise, switch to protected mode. + + mov $StartStateLocation, %si + cmpl $0, (%si) + jnz L_SkipRecordBist + +// Record BIST information +// + mov $8, %al + mul %bl + mov $BistBufferLocation, %si + add %ax, %si + + movl $1, (%si) // Set Valid Flag + mov %ebp, 4(%si) // Store BIST value + +L_SkipRecordBist: +// Switch to flat mode. + + mov $BufferStartLocation, %si + mov (%si), %ebx + + mov $PmodeOffsetLocation, %di + mov (%di), %eax + mov %ax, %di + sub $6, %di + add %ebx, %eax + mov %eax, (%di) + + mov $0, %esi + mov $GdtrLocation, %si + lgdtl %cs:(%esi) + + xor %ax, %ax + mov %ax, %ds + + mov %cr0, %eax + or $0x00000003, %eax + mov %eax, %cr0 + + .byte 0x66, 0x67, 0xea // far jump + .long 0x00 // 32-bit offset + .short 0x20 // 16-bit selector + + .code32 +L_NemInit: // protected mode entry point + mov $0x18, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + + mov %ebx, %esi + + mov %esi, %edi + add $StartStateLocation, %edi + mov $1, %eax + movl %eax, (%edi) + + mov %esi, %edi + add $LockLocation, %edi + mov $NotVacantFlag, %eax +L_TestLock: + xchg %eax, (%edi) + cmp $NotVacantFlag, %eax + jz L_TestLock + +L_ProgramStack: + + mov %esi, %edi + add $StackSizeLocation, %edi + mov (%edi), %eax + mov %esi, %edi + add $StackStartAddressLocation, %edi + add (%edi), %eax + mov %eax, %esp + movl %eax, (%edi) + +L_Releaselock: + + mov $VacantFlag, %eax + mov %esi, %edi + add $LockLocation, %edi + xchg %eax, (%edi) + +L_CProcedureInvoke: + + mov %esi, %edi + add $CArgumentLocation, %edi + mov (%edi), %eax + push %eax + + mov %esi, %edi + add $CProcedureLocation, %edi + mov (%edi), %eax + + call *%eax + add $4, %esp + +L_InterlockedIncrementFinishedCount: + mov %esi, %edi + add $FinishedCountAddressLocation, %edi + lock incl (%edi) + +1: + cli + + hlt + jmp 1b + + +//------------------------------------------------------------------------------------- +// S3SemaphoreStartAddress +//------------------------------------------------------------------------------------- + +L_S3SemaphoreStartAddress: + push %ebp + mov %esp, %ebp + mov 0x8(%ebp), %eax +1: + cmpl $0, (%eax) + jz 1f + + pause + jmp 1b + +1: + pop %ebp + ret + +//------------------------------------------------------------------------------- +// S3AsmGetAddressMap +//------------------------------------------------------------------------------------- +.set L_NemInitOffset, L_NemInit - L_S3RendezvousFunnelProcStart +.set L_SemaphoreOffset, L_S3SemaphoreStartAddress - L_S3RendezvousFunnelProcStart + +.globl ASM_PFX(S3AsmGetAddressMap) +ASM_PFX(S3AsmGetAddressMap): + mov $L_S3RendezvousFunnelProcStart, %eax + ret + + +//------------------------------------------------------------------------------- +// S3AsmGetPmodeOffset +//------------------------------------------------------------------------------------- +.globl ASM_PFX(S3AsmGetPmodeOffset) +ASM_PFX(S3AsmGetPmodeOffset): + mov $L_NemInitOffset, %eax + ret + +//------------------------------------------------------------------------------- +// S3AsmGetSemaphoreCheckOffset +//------------------------------------------------------------------------------------- +.globl ASM_PFX(S3AsmGetSemaphoreCheckOffset) +ASM_PFX(S3AsmGetSemaphoreCheckOffset): + mov $L_SemaphoreOffset, %eax + ret \ No newline at end of file diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm new file mode 100644 index 0000000000..9e3450d0d3 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm @@ -0,0 +1,206 @@ +;; @file +; This is the assembly code for MP support. +; +; Copyright (c) 2005 - 2016, 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 +; +;; + +include MpEqu.inc + +;------------------------------------------------------------------------------------- +;S3RendezvousFunnelProc procedure follows. All APs execute their procedure. This +;procedure serializes all the AP processors through an Init sequence. It must be +;noted that APs arrive here very raw...ie: real mode, no stack. +;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC +;IS IN MACHINE CODE. +;------------------------------------------------------------------------------------- +;S3RendezvousFunnelProc (&WakeUpBuffer,MemAddress); + +.686p +.model flat +.code + +PAUSE32 MACRO + DB 0F3h + DB 090h + ENDM + +S3RendezvousFunnelProc PROC PUBLIC +S3RendezvousFunnelProcStart:: + +;Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0. + + db 8ch,0c8h ; mov ax,cs + db 8eh,0d8h ; mov ds,ax + db 8eh,0c0h ; mov es,ax + db 8eh,0d0h ; mov ss,ax + db 33h,0c0h ; xor ax,ax + db 8eh,0e0h ; mov fs,ax + db 8eh,0e8h ; mov gs,ax + + db 0BEh ; opcode of mov si, mem16 + dw BufferStartLocation ; mov si, BufferStartLocation + db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si] + + db 0BFh ; opcode of mov di, mem16 + dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation + db 66h, 8Bh, 05h ; mov eax,dword ptr [di] + db 8Bh, 0F8h ; mov di, ax + db 83h, 0EFh,06h ; sub di, 06h + db 66h, 03h, 0C3h ; add eax, ebx + db 66h, 89h, 05h ; mov dword ptr [di],eax + + db 0BEh ; opcode of mov si, mem16 + dw GdtrLocation ; mov si, GdtrLocation + db 66h ; db 66h + db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si] + + db 0BEh ; opcode of mov si, mem16 + dw IdtrLocation ; mov si, IdtrProfile + db 66h ; db 66h + db 2Eh, 0Fh, 01h, 1Ch ; lidt fword ptr cs:[si] + + db 33h, 0C0h ; xor ax, ax + db 8Eh, 0D8h ; mov ds, ax + + db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0 + db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP + db 0Fh, 22h, 0C0h ; mov cr0, eax + + db 66h, 67h, 0EAh ; far jump + dd 0h ; 32-bit offset + dw 20h ; 16-bit selector + +NemInit:: ; protected mode entry point + + db 66h, 0B8h, 18h, 00h ; mov ax, 18h + db 66h, 8Eh, 0D8h ; mov ds, ax + db 66h, 8Eh, 0C0h ; mov es, ax + db 66h, 8Eh, 0E0h ; mov fs, ax + db 66h, 8Eh, 0E8h ; mov gs, ax + db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup. + + mov esi, ebx + + mov edi, esi + add edi, StartStateLocation + mov eax, 1 + mov dword ptr [edi], eax + + mov edi, esi + add edi, LockLocation + mov eax, NotVacantFlag +TestLock:: + xchg dword ptr [edi], eax + cmp eax, NotVacantFlag + jz TestLock + +ProgramStack:: + + mov edi, esi + add edi, StackSizeLocation + mov eax, dword ptr [edi] + mov edi, esi + add edi, StackStartAddressLocation + add eax, dword ptr [edi] + mov esp, eax + mov dword ptr [edi], eax + +Releaselock:: + + mov eax, VacantFlag + mov edi, esi + add edi, LockLocation + xchg dword ptr [edi], eax + +CProcedureInvoke:: + + mov edi, esi + add edi, MtrrValuesAddressLocation + mov eax, dword ptr [edi] + push eax + + mov eax, esi + add eax, LockLocation + push eax + + mov edi, esi + add edi, CProcedureLocation + mov eax, dword ptr [edi] + +; +; itp.threads[n].msr(0x121, 0x2FBA2E2500010408) +; WA for ACPI PM1 timer BXT 0 and 1 +; + push ecx + push eax + push edx + + mov ecx, 0121h + rdmsr + test eax, eax + jnz SkipAcpiTimerWA + mov eax, 00010408h ; Bit 16 is enable and 15:0 address + mov edx, 2FBA2E25h + wrmsr +SkipAcpiTimerWA: + pop edx + pop eax + pop ecx + + call eax + add esp, 8 + + cli + hlt + jmp $-2 + +S3RendezvousFunnelProc ENDP + +S3SemaphoreStartAddress PROC C, SemaphoreAddress:PTR DWORD + mov eax, SemaphoreAddress +@@: + cmp dword ptr [eax], 0 + jz @F + + PAUSE32 + jmp @B +@@: + ret +S3SemaphoreStartAddress ENDP + +S3RendezvousFunnelProcEnd:: + + +;------------------------------------------------------------------------------------- +; S3AsmGetAddressMap (&AddressMap); +;------------------------------------------------------------------------------------- +S3AsmGetAddressMap PROC near C PUBLIC + + mov eax, S3RendezvousFunnelProcStart + ret + +S3AsmGetAddressMap ENDP + +S3AsmGetPmodeOffset PROC near C PUBLIC + + mov eax, NemInit - S3RendezvousFunnelProcStart + ret + +S3AsmGetPmodeOffset ENDP + +S3AsmGetSemaphoreCheckOffset PROC near C PUBLIC + mov eax, S3SemaphoreStartAddress - S3RendezvousFunnelProcStart + ret +S3AsmGetSemaphoreCheckOffset ENDP + +END + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf new file mode 100644 index 0000000000..749dd98ad7 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf @@ -0,0 +1,59 @@ +## @file +# Component information file for CPU S3 module. +# +# Copyright (c) 2014 - 2016, 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. +# +## + +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = PeiCpuS3Lib + FILE_GUID = 6351F303-B76A-44F9-9171-026BDDCA8654 + VERSION_STRING = 1.0 + MODULE_TYPE = PEIM + LIBRARY_CLASS = CpuS3Lib + +[LibraryClasses] + CpuPlatformLib + DebugLib + BaseLib + PeiServicesLib + BaseMemoryLib + SynchronizationLib + HobLib + ReportStatusCodeLib + MemoryAllocationLib + IoLib + TimerLib + CpuCommonLib + PostCodeLib + MpServiceLib + +[Packages] + MdePkg/MdePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[Sources] + CpuS3Lib.c + +[Sources.IA32] + Ia32/MpFuncs.S | GCC + Ia32/MpFuncs.asm | MSFT + +[Ppis] + gSiCpuPolicyPpiGuid ## CONSUMES + gPeiSmmAccessPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## NOTIFY + +[Guids] + gSmramCpuDataHeaderGuid ## UNDEFINED + gPeiAcpiCpuDataGuid ## UNDEFINED -- cgit v1.2.3