blob: 552713d2cdf63ccac7a6216b4d5a25c565807487 [file] [log] [blame]
/* $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;
}