| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * AMD CRAT, ACPI table related API functions. |
| * |
| * Contains code that Create the APCI CRAT Table after early reset. |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: CPU/FEATURE |
| * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ |
| * |
| */ |
| /* |
| ****************************************************************************** |
| * |
| * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| ***************************************************************************/ |
| |
| |
| /*---------------------------------------------------------------------------- |
| * This file provides functions, that will generate CRAT tables |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "amdlib.h" |
| #include "cpuServices.h" |
| #include "OptionCrat.h" |
| #include "cpuCrat.h" |
| #include "mfCrat.h" |
| #include "heapManager.h" |
| #include "cpuRegisters.h" |
| #include "cpuFamilyTranslation.h" |
| #include "cpuLateInit.h" |
| #include "Ids.h" |
| #include "Filecode.h" |
| CODE_GROUP (G3_DXE) |
| RDATA_GROUP (G3_DXE) |
| |
| #define FILECODE PROC_CPU_FEATURE_CPUCRAT_FILECODE |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| extern OPTION_CRAT_CONFIGURATION OptionCratConfiguration; // global user config record |
| extern CPU_FAMILY_SUPPORT_TABLE CratFamilyServiceTable; |
| extern S_MAKE_CRAT_ENTRY MakeCratEntryTable[]; |
| |
| /*---------------------------------------------------------------------------------------- |
| * E X P O R T E D F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| AGESA_STATUS |
| GetAcpiCratStub ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader, |
| OUT VOID **CratPtr |
| ); |
| |
| AGESA_STATUS |
| GetAcpiCratMain ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader, |
| OUT VOID **CratPtr |
| ); |
| |
| /*---------------------------------------------------------------------------- |
| * All of the DATA should be defined in _CODE segment. |
| * Use ROMDATA to specify that it belongs to _CODE. |
| *---------------------------------------------------------------------------- |
| */ |
| CONST UINT8 ROMDATA L2L3Associativity[] = |
| { |
| 0, |
| 1, |
| 2, |
| 0, |
| 4, |
| 0, |
| 8, |
| 0, |
| 16, |
| 0, |
| 32, |
| 48, |
| 64, |
| 96, |
| 128, |
| 0xFF |
| }; |
| |
| STATIC CRAT_HEADER ROMDATA CratHeaderStruct = |
| { |
| {'C','R','A','T'}, |
| 0, |
| 1, |
| 0, |
| {0}, |
| {0}, |
| 1, |
| {'A','M','D',' '}, |
| 1, |
| 0, |
| 0, |
| {0, 0, 0, 0, 0, 0} |
| }; |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * E X P O R T E D F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * |
| * This function will generate a complete Component Resource Affinity Table |
| * i.e. CRAT into a memory buffer. After completion, this table must be set |
| * by the system BIOS into its internal ACPI name space. |
| * |
| * @param[in, out] StdHeader Standard Head Pointer |
| * @param[out] CratPtr Point to Crat Struct including buffer address and length |
| * |
| * @retval AGESA_STATUS |
| */ |
| |
| AGESA_STATUS |
| CreateAcpiCrat ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader, |
| OUT VOID **CratPtr |
| ) |
| { |
| AGESA_TESTPOINT (TpProcCpuEntryCrat, StdHeader); |
| return ((*(OptionCratConfiguration.CratFeature)) (StdHeader, CratPtr)); |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * |
| * This is the default routine for use when the CRAT option is NOT requested. |
| * |
| * The option install process will create and fill the transfer vector with |
| * the address of the proper routine (Main or Stub). The link optimizer will |
| * strip out of the .DLL the routine that is not used. |
| * |
| * @param[in, out] StdHeader Standard Head Pointer |
| * @param[out] CratPtr Point to Crat Struct including buffer address and length |
| * |
| * @retval AGESA_STATUS |
| */ |
| |
| AGESA_STATUS |
| GetAcpiCratStub ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader, |
| OUT VOID **CratPtr |
| ) |
| { |
| return AGESA_UNSUPPORTED; |
| } |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * |
| * This function will generate a complete Component Resource Affinity Table |
| * i.e. CRAT into a memory buffer. After completion, this table must be set |
| * by the system BIOS into its internal ACPI name space. |
| * |
| * @param[in, out] StdHeader Standard Head Pointer |
| * @param[out] CratPtr Point to Crat Struct including buffer address and length |
| * |
| * @retval AGESA_STATUS |
| */ |
| AGESA_STATUS |
| GetAcpiCratMain ( |
| IN OUT AMD_CONFIG_PARAMS *StdHeader, |
| OUT VOID **CratPtr |
| ) |
| { |
| UINT8 i; |
| UINT8 *TableEnd; |
| CRAT_HEADER *CratHeaderStructPtr; |
| ALLOCATE_HEAP_PARAMS AllocParams; |
| |
| // Allocate a buffer |
| AllocParams.RequestedBufferSize = CRAT_MAX_LENGTH; |
| AllocParams.BufferHandle = AMD_CRAT_INFO_BUFFER_HANDLE; |
| AllocParams.Persist = HEAP_SYSTEM_MEM; |
| |
| if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) { |
| return AGESA_ERROR; |
| } |
| *CratPtr = AllocParams.BufferPtr; |
| |
| |
| CratHeaderStructPtr = (CRAT_HEADER *) *CratPtr; |
| TableEnd = (UINT8 *) *CratPtr; |
| |
| // Copy CratHeaderStruct -> data buffer |
| LibAmdMemCopy ((VOID *) CratHeaderStructPtr, (VOID *) &CratHeaderStruct, (UINTN) (sizeof (CRAT_HEADER)), StdHeader); |
| // Update table OEM fields. |
| LibAmdMemCopy ((VOID *) &CratHeaderStructPtr->OemId, (VOID *) &OptionCratConfiguration.OemIdString, |
| sizeof (OptionCratConfiguration.OemIdString), StdHeader); |
| LibAmdMemCopy ((VOID *) &CratHeaderStructPtr->OemTableId, (VOID *) &OptionCratConfiguration.OemTableIdString, |
| sizeof (OptionCratConfiguration.OemTableIdString), StdHeader); |
| |
| TableEnd += sizeof (CRAT_HEADER); |
| |
| // Make all CRAT entries. |
| for (i = 0; MakeCratEntryTable[i].MakeCratEntry != NULL; i++) { |
| MakeCratEntryTable[i].MakeCratEntry (CratHeaderStructPtr, &TableEnd, StdHeader); |
| |
| } |
| |
| // Store size in table (current buffer offset - buffer start offset) |
| CratHeaderStructPtr->Length = (UINT32) (TableEnd - (UINT8 *) CratHeaderStructPtr); |
| |
| //Update SSDT header Checksum |
| ChecksumAcpiTable ((ACPI_TABLE_HEADER *) CratHeaderStructPtr, StdHeader); |
| IDS_HDT_CONSOLE (CPU_TRACE, " CRAT is created\n"); |
| return AGESA_SUCCESS; |
| } |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * This function will add HSA Processing Unit entry. |
| * |
| * @param[in] CratHeaderStructPtr CRAT header pointer |
| * @param[in, out] TableEnd The end of CRAT |
| * @param[in, out] StdHeader Standard Head Pointer |
| * |
| */ |
| VOID |
| MakeHSAProcUnitEntry ( |
| IN CRAT_HEADER *CratHeaderStructPtr, |
| IN OUT UINT8 **TableEnd, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 NodeNum; |
| UINT8 NodeCount; |
| UINT32 Socket; |
| UINT32 Module; |
| UINT32 LowCore; |
| UINT32 HighCore; |
| UINT32 RegVal; |
| CRAT_HSA_PROCESSING_UNIT *EntryPtr; |
| AMD_APIC_PARAMS ApicParams; |
| PCI_ADDR PciAddress; |
| |
| // Get Node count |
| PciAddress.AddressValue = MAKE_SBDFO (0, 0, LOW_NODE_DEVICEID, FUNC_0, 0x60); |
| LibAmdPciRead (AccessWidth32 , PciAddress, &RegVal, StdHeader); |
| NodeCount = (UINT8) (((RegVal >> 4) & 0x7) + 1); |
| |
| NodeNum = 0; |
| ApicParams.StdHeader = *StdHeader; |
| while (NodeNum < NodeCount) { |
| GetSocketModuleOfNode ((UINT32) NodeNum, &Socket, &Module, StdHeader); |
| GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader); |
| ApicParams.Socket = (UINT8) Socket; |
| ApicParams.Core = 0; |
| AmdGetApicId (&ApicParams); |
| if (ApicParams.IsPresent) { |
| // Adding one CRAT entry for every node |
| EntryPtr = (CRAT_HSA_PROCESSING_UNIT *) AddOneCratEntry (CRAT_TYPE_HSA_PROC_UNIT, CratHeaderStructPtr, TableEnd, StdHeader); |
| |
| EntryPtr->ProximityDomain = NodeNum; |
| EntryPtr->ProcessorIdLow = ApicParams.ApicAddress; |
| EntryPtr->NumCPUCores = (UINT16) (HighCore - LowCore + 1); |
| EntryPtr->Flags.Enabled = 1; |
| EntryPtr->Flags.CpuPresent = 1; |
| } |
| /// @todo SimdCount SimdWidth IoCount |
| CratHeaderStructPtr->NumDomains++; |
| NodeNum++; |
| } |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * This function will add memory entry. |
| * |
| * @param[in] CratHeaderStructPtr CRAT header pointer |
| * @param[in, out] TableEnd The end of CRAT |
| * @param[in, out] StdHeader Standard Head Pointer |
| * |
| */ |
| VOID |
| MakeMemoryEntry ( |
| IN CRAT_HEADER *CratHeaderStructPtr, |
| IN OUT UINT8 **TableEnd, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 EntryNum; |
| UINT8 NumOfMemAffinityInfoEntries; |
| UINT32 Width; |
| AGESA_STATUS AgesaStatus; |
| CRAT_MEMORY *EntryPtr; |
| LOCATE_HEAP_PTR LocateHeapParams; |
| CRAT_MEMORY_AFFINITY_INFO_HEADER *MemAffinityInfoHeaderPtr; |
| CRAT_MEMORY_AFFINITY_INFO_ENTRY *MemAffinityInfoEntryPtr; |
| |
| EntryNum = 0; |
| |
| // Get the CRAT memory affinity info from heap |
| LocateHeapParams.BufferHandle = AMD_MEM_CRAT_INFO_BUFFER_HANDLE; |
| AgesaStatus = HeapLocateBuffer (&LocateHeapParams, StdHeader); |
| if (AgesaStatus != AGESA_SUCCESS) { |
| ASSERT (FALSE); |
| } else { |
| MemAffinityInfoHeaderPtr = (CRAT_MEMORY_AFFINITY_INFO_HEADER *) (LocateHeapParams.BufferPtr); |
| MemAffinityInfoHeaderPtr ++; |
| MemAffinityInfoEntryPtr = (CRAT_MEMORY_AFFINITY_INFO_ENTRY *) MemAffinityInfoHeaderPtr; |
| MemAffinityInfoHeaderPtr --; |
| |
| // Get the number of CRAT memory affinity entries |
| NumOfMemAffinityInfoEntries = MemAffinityInfoHeaderPtr->NumOfMemAffinityInfoEntries; |
| Width = MemAffinityInfoHeaderPtr->MemoryWidth; |
| |
| // Create CRAT memory affinity entries |
| IDS_HDT_CONSOLE (MAIN_FLOW, " CRAT memory affinity entries\n"); |
| while (EntryNum < NumOfMemAffinityInfoEntries) { |
| // Add one CRAT memory entry |
| EntryPtr = (CRAT_MEMORY *) AddOneCratEntry (CRAT_TYPE_MEMORY, CratHeaderStructPtr, TableEnd, StdHeader); |
| EntryPtr->Flags.Enabled = 1; |
| EntryPtr->ProximityDomain = MemAffinityInfoEntryPtr->Domain; |
| EntryPtr->BaseAddressLow = MemAffinityInfoEntryPtr->BaseAddressLow; |
| EntryPtr->BaseAddressHigh = MemAffinityInfoEntryPtr->BaseAddressHigh; |
| EntryPtr->LengthLow = MemAffinityInfoEntryPtr->LengthLow; |
| EntryPtr->LengthHigh = MemAffinityInfoEntryPtr->LengthHigh; |
| EntryPtr->Width = Width; |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Entry #%d\n", EntryNum); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Type: 0x%08x\n", EntryPtr->Type); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Length: 0x%08x\n", EntryPtr->Length); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Flags: %s %s %s\n", (EntryPtr->Flags.Enabled == 1) ? "Enabled" : "", |
| (EntryPtr->Flags.HotPluggable == 1) ? "EnHotPluggableabled" : "", |
| (EntryPtr->Flags.NonVolatile == 1) ? "NonVolatile" : "" |
| ); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Proximity Domain: 0x%08x\n", EntryPtr->ProximityDomain); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Base Address Low: 0x%08x\n", EntryPtr->BaseAddressLow); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Base Address High: 0x%08x\n", EntryPtr->BaseAddressHigh); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Length Low: 0x%08x\n", EntryPtr->LengthLow); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Length High: 0x%08x\n", EntryPtr->LengthHigh); |
| IDS_HDT_CONSOLE (MAIN_FLOW, " Width: 0x%08x\n", EntryPtr->Width); |
| MemAffinityInfoEntryPtr ++; |
| EntryNum ++; |
| } |
| HeapDeallocateBuffer ((UINT32) AMD_MEM_CRAT_INFO_BUFFER_HANDLE, StdHeader); |
| } |
| |
| return; |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * This function will add cache entry. |
| * |
| * @param[in] CratHeaderStructPtr CRAT header pointer |
| * @param[in, out] TableEnd The end of CRAT |
| * @param[in, out] StdHeader Standard Head Pointer |
| * |
| */ |
| VOID |
| MakeCacheEntry ( |
| IN CRAT_HEADER *CratHeaderStructPtr, |
| IN OUT UINT8 **TableEnd, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| CRAT_FAMILY_SERVICES *CratFamilyServices; |
| |
| GetFeatureServicesOfSocket (&CratFamilyServiceTable, 0, (CONST VOID **)&CratFamilyServices, StdHeader); |
| CratFamilyServices->generateCratCacheEntry (CratHeaderStructPtr, TableEnd, StdHeader); |
| return; |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * This function will add TLB entry. |
| * |
| * @param[in] CratHeaderStructPtr CRAT header pointer |
| * @param[in, out] TableEnd The end of CRAT |
| * @param[in, out] StdHeader Standard Head Pointer |
| * |
| */ |
| VOID |
| MakeTLBEntry ( |
| IN CRAT_HEADER *CratHeaderStructPtr, |
| IN OUT UINT8 **TableEnd, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| CRAT_FAMILY_SERVICES *CratFamilyServices; |
| |
| GetFeatureServicesOfSocket (&CratFamilyServiceTable, 0, (CONST VOID **)&CratFamilyServices, StdHeader); |
| CratFamilyServices->generateCratTLBEntry (CratHeaderStructPtr, TableEnd, StdHeader); |
| return; |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * This function will add CRAT entry. |
| * |
| * @param[in] CratEntryType CRAT entry type |
| * @param[in] CratHeaderStructPtr CRAT header pointer |
| * @param[in, out] TableEnd The end of CRAT |
| * @param[in, out] StdHeader Standard Head Pointer |
| * |
| */ |
| UINT8 * |
| AddOneCratEntry ( |
| IN CRAT_ENTRY_TYPE CratEntryType, |
| IN CRAT_HEADER *CratHeaderStructPtr, |
| IN OUT UINT8 **TableEnd, |
| IN OUT AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 *CurrentEntry; |
| |
| CurrentEntry = *TableEnd; |
| CratHeaderStructPtr->TotalEntries++; |
| switch (CratEntryType) { |
| case CRAT_TYPE_HSA_PROC_UNIT: |
| *TableEnd += sizeof (CRAT_HSA_PROCESSING_UNIT); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_HSA_PROCESSING_UNIT); |
| ((CRAT_HSA_PROCESSING_UNIT *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_HSA_PROCESSING_UNIT *) CurrentEntry)->Length = sizeof (CRAT_HSA_PROCESSING_UNIT); |
| break; |
| case CRAT_TYPE_MEMORY: |
| *TableEnd += sizeof (CRAT_MEMORY); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_MEMORY); |
| ((CRAT_MEMORY *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_MEMORY *) CurrentEntry)->Length = sizeof (CRAT_MEMORY); |
| break; |
| case CRAT_TYPE_CACHE: |
| *TableEnd += sizeof (CRAT_CACHE); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_CACHE); |
| ((CRAT_CACHE *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_CACHE *) CurrentEntry)->Length = sizeof (CRAT_CACHE); |
| break; |
| case CRAT_TYPE_TLB: |
| *TableEnd += sizeof (CRAT_TLB); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_TLB); |
| ((CRAT_TLB *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_TLB *) CurrentEntry)->Length = sizeof (CRAT_TLB); |
| break; |
| case CRAT_TYPE_FPU: |
| *TableEnd += sizeof (CRAT_FPU); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_FPU); |
| ((CRAT_FPU *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_FPU *) CurrentEntry)->Length = sizeof (CRAT_FPU); |
| break; |
| case CRAT_TYPE_IO: |
| *TableEnd += sizeof (CRAT_IO); |
| ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH); |
| CratHeaderStructPtr->Length += sizeof (CRAT_IO); |
| ((CRAT_IO *) CurrentEntry)->Type = (UINT8) CratEntryType; |
| ((CRAT_IO *) CurrentEntry)->Length = sizeof (CRAT_IO); |
| break; |
| default: |
| ASSERT (FALSE); |
| break; |
| } |
| return CurrentEntry; |
| } |
| |