summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c')
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c412
1 files changed, 412 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c
new file mode 100644
index 0000000000..90f15b4652
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Feat/CRAT/mfCrat.c
@@ -0,0 +1,412 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mfCrat.c
+ *
+ * Feature CRAT table support
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/Main)
+ * @e \$Revision: 64574 $ @e \$Date: 2012-01-25 01:01:51 -0600 (Wed, 25 Jan 2012) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+ *
+ * AMD is granting you permission to use this software (the Materials)
+ * pursuant to the terms and conditions of your Software License Agreement
+ * with AMD. This header does *NOT* give you permission to use the Materials
+ * or any rights under AMD's intellectual property. Your use of any portion
+ * of these Materials shall constitute your acceptance of those terms and
+ * conditions. If you do not agree to the terms and conditions of the Software
+ * License Agreement, please do not use any portion of these Materials.
+ *
+ * CONFIDENTIALITY: The Materials and all other information, identified as
+ * confidential and provided to you by AMD shall be kept confidential in
+ * accordance with the terms and conditions of the Software License Agreement.
+ *
+ * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+ * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+ * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+ * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+ * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+ * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+ * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+ * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+ * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+ * THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+ *
+ * AMD does not assume any responsibility for any errors which may appear in
+ * the Materials or any other related information provided to you by AMD, or
+ * result from use of the Materials or any related information.
+ *
+ * You agree that you will not reverse engineer or decompile the Materials.
+ *
+ * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+ * further information, software, technical information, know-how, or show-how
+ * available to you. Additionally, AMD retains the right to modify the
+ * Materials at any time, without notice, and is not obligated to provide such
+ * modified Materials to you.
+ *
+ * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+ * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+ * subject to the restrictions as set forth in FAR 52.227-14 and
+ * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+ * Government constitutes acknowledgement of AMD's proprietary rights in them.
+ *
+ * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+ * direct product thereof will be exported directly or indirectly, into any
+ * country prohibited by the United States Export Administration Act and the
+ * regulations thereunder, without the required authorization from the U.S.
+ * government nor will be used for any purpose prohibited by the same.
+ * ***************************************************************************
+ *
+ */
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "heapManager.h"
+#include "cpuServices.h"
+#include "mm.h"
+#include "mn.h"
+#include "mu.h"
+#include "mfCrat.h"
+#include "GeneralServices.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE (0xF095)
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define FOURGB 0x010000ul
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+CRAT_MEMORY_AFFINITY_INFO_ENTRY
+STATIC
+*MakeMemAffinityInfoEntry (
+ IN UINT8 Domain,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN CRAT_MEMORY_AFFINITY_INFO_ENTRY *BufferLocPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemFCratSupport (
+ IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
+ );
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets CRAT memory affinity info and stores the info into heap
+ *
+ * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
+ *
+ */
+BOOLEAN
+MemFCratSupport (
+ IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
+ )
+{
+ UINT8 Node;
+ UINT32 DramLeng;
+ UINT32 DramBase;
+ UINT32 DramLimit;
+ UINT8 DramRngRE;
+ UINT8 DramRngWE;
+ UINT8 Domain;
+ UINT8 DomainForBase640K;
+ UINT32 ValueLimit;
+ UINT32 ValueTOM;
+ UINT64 MsrValue;
+ BOOLEAN isModified;
+ UINT8 MaxNumOfMemAffinityInfoEntries;
+ UINT8 NumOfMemAffinityInfoEntries;
+ UINT32 TopOfMemoryAbove4Gb;
+ CRAT_MEMORY_AFFINITY_INFO_HEADER *MemAffinityInfoHeaderPtr;
+ CRAT_MEMORY_AFFINITY_INFO_ENTRY *MemAffinityInfoEntryPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ MEM_NB_BLOCK *NBPtr;
+ MEM_DATA_STRUCT *MemPtr;
+ DIE_STRUCT *MCTPtr;
+ MEM_SHARED_DATA *SharedPtr;
+
+ NBPtr = MemMainPtr->NBPtr;
+ MemPtr = MemMainPtr->MemPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ SharedPtr = NBPtr->SharedPtr;
+
+ // The maximum number of entries take the following two factors into consideration
+ // 1. The entry for conventional memory less than 640k
+ // 2. The memory hole below 4G may divide the memory range across the hole into two
+ MaxNumOfMemAffinityInfoEntries = NBPtr->NodeCount + 2;
+
+ // Allocate heap for CRAT memory affinity info entry
+ AllocHeapParams.RequestedBufferSize = MaxNumOfMemAffinityInfoEntries * sizeof (CRAT_MEMORY_AFFINITY_INFO_ENTRY) +
+ sizeof (CRAT_MEMORY_AFFINITY_INFO_HEADER);
+ AllocHeapParams.BufferHandle = AMD_MEM_CRAT_INFO_BUFFER_HANDLE;
+ AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
+ if (AGESA_SUCCESS != HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader)) {
+ // Could not allocate heap for CRAT memory affinity info
+ PutEventLog (AGESA_CRITICAL, MEM_ERROR_HEAP_ALLOCATE_FOR_CRAT_MEM_AFFINITY, NBPtr->Node, 0, 0, 0, &MemPtr->StdHeader);
+ SetMemError (AGESA_CRITICAL, MCTPtr);
+ ASSERT (FALSE);
+ return FALSE;
+ }
+
+ MemAffinityInfoHeaderPtr = (CRAT_MEMORY_AFFINITY_INFO_HEADER *) ((UINT8 *) (AllocHeapParams.BufferPtr));
+ MemAffinityInfoHeaderPtr ++;
+ MemAffinityInfoEntryPtr = (CRAT_MEMORY_AFFINITY_INFO_ENTRY *) MemAffinityInfoHeaderPtr;
+ MemAffinityInfoHeaderPtr --;
+
+ NumOfMemAffinityInfoEntries = 0;
+ DomainForBase640K = 0xFF;
+
+ for (Node = 0; Node < NBPtr->NodeCount; Node++) {
+ // FALSE means normal update procedure
+ isModified = FALSE;
+ // Get DRAM Base Address
+ DramBase = MemNGetBitFieldNb (NBPtr, BFDramBaseReg0 + Node);
+ DramRngRE = (UINT8) MemNGetBitFieldNb (NBPtr, BFDramRngRE0 + Node);
+ DramRngWE = (UINT8) MemNGetBitFieldNb (NBPtr, BFDramRngWE0 + Node);
+ if ((DramRngRE == 0) || (DramRngWE == 0)) {
+ // 0:1 set if memory range enabled
+ // Not set, so we don't have an enabled range
+ // Proceed to next Base register
+ continue;
+ }
+
+ // Get DRAM Limit
+ DramLimit = MemNGetBitFieldNb (NBPtr, BFDramLimitReg0 + Node);
+ if (DramLimit == 0xFFFFFFFF) {
+ // Node not installed(all FF's)?
+ // Proceed to next Base register
+ continue;
+ }
+
+ // Node ID is assigned to Domain
+ Domain = (UINT8) MemNGetBitFieldNb (NBPtr, BFDramRngDstNode0 + Node);
+ // Get DRAM Limit addr [47:24]
+ DramLimit = ((((MemNGetBitFieldNb (NBPtr, BFDramLimitHiReg0 + Node) & 0xFF) << 16) | DramLimit >> 16));
+ // Add 1 for potential length
+ DramLimit++;
+ DramLimit <<= 8;
+
+ // Get DRAM Base Address
+ // Get DRAM Base Base value [47:24]
+ DramBase = (((MemNGetBitFieldNb (NBPtr, BFDramBaseHiReg0 + Node) & 0xFF) << 24) | (DramBase >> 8) & 0xFFFFFF00);
+ // Subtract base from limit to get length
+ DramLeng = DramLimit - DramBase;
+
+ // Leave hole for conventional memory (Less than 640K). It must be on CPU 0.
+ if (DramBase == 0) {
+ if (DomainForBase640K == 0xFF) {
+ // It is the first time that the range start at 0.
+ // If Yes, then Place 1MB memory gap and save Domain to PDomainForBase640K
+ MemAffinityInfoEntryPtr = MakeMemAffinityInfoEntry (
+ Domain,
+ 0, // Base = 0
+ 0xA0000 >> 16, // Put it into format used in DRAM regs..
+ MemAffinityInfoEntryPtr
+ );
+ NumOfMemAffinityInfoEntries ++;
+
+ // Add 1MB, so range = 1MB to Top of Region
+ DramBase += 0x10;
+ // Also subtract 1MB from the length
+ DramLeng -= 0x10;
+ // Save Domain number for memory Less than 640K
+ DomainForBase640K = Domain;
+ } else {
+ // If No, there are more than one memory range less than 640K, it should that
+ // node interleaving is enabled. All nodes have the same memory ranges
+ // and all cores in these nodes belong to the same domain.
+ Domain = DomainForBase640K;
+ break;
+ }
+ }
+ LibAmdMsrRead (TOP_MEM, &MsrValue, &MemPtr->StdHeader);
+ // Save it in 39:24 format
+ ValueTOM = (UINT32) MsrValue >> 16;
+ // We need to know how large region is
+ ValueLimit = DramBase + DramLeng;
+
+ LibAmdMsrRead (SYS_CFG, &MsrValue, &MemPtr->StdHeader);
+ if ((MsrValue & BIT21) != 0) {
+ LibAmdMsrRead (TOP_MEM2, &MsrValue, &MemPtr->StdHeader);
+ // Save it in 47:16 format
+ TopOfMemoryAbove4Gb = (UINT32) (MsrValue >> 16);
+ } else {
+ TopOfMemoryAbove4Gb = 0xFFFFFFFF;
+ }
+
+ // SPECIAL CASES:
+ //
+ // Several conditions require that we process the values of the memory range differently.
+ // Here are descriptions of the corner cases.
+ //
+ // 1. TRUNCATE LOW - Memory range starts below TOM, ends in TOM (memory hole). For this case,
+ // the range must be truncated to end at TOM.
+ // ******************************* *******************************
+ // * * * -> * *
+ // ******************************* *******************************
+ // 2 TOM 4 2 TOM
+ //
+ // 2. TRUNCATE HIGH - Memory range starts below 4GB, ends above 4GB. This is handled by changing the
+ // start base to 4GB.
+ // **************** **********
+ // * * * -> * *
+ // **************** **********
+ // TOM 3.8 4 6 TOM 3.8 4 6
+ //
+ // 3. Memory range starts below TOM, ends above 4GB. For this case, the range must be truncated
+ // to end at TOM. Note that this scenario creates two ranges, as the second comparison below
+ // will find that it ends above 4GB since base and limit have been restored after first truncation,
+ // and a second range will be written based at 4GB ending at original end address.
+ // ******************************* **************** **********
+ // * * * * -> * * * *
+ // ******************************* **************** **********
+ // 2 TOM 4 6 2 TOM 4 6
+ //
+ // 4. Memory range starts above TOM, ends below or equal to 4GB. This invalid range should simply
+ // be ignored.
+ // *******
+ // * * -> < NULL >
+ // *******
+ // TOM 3.8 4
+ //
+ // 5. Memory range starts below TOM2, and ends beyond TOM2. This range must be truncated to TOM2.
+ // ************************ *******************************
+ // * * * -> * *
+ // ************************ *******************************
+ // 768 TOM2 1024 768 TOM2
+ //
+ // 6. Memory range starts above TOM2. This invalid range should simply be ignored.
+ // ********************
+ // * * -> < NULL >
+ // ********************
+ // TOM2 1024 1280
+
+ if (((DramBase < ValueTOM) && (ValueLimit <= FOURGB) && (ValueLimit > ValueTOM))
+ || ((DramBase < ValueTOM) && (ValueLimit > FOURGB))) {
+ // TRUNCATE LOW!!! Shrink entry below TOM...
+ // Base = DramBase, Size = TOM - DramBase
+ MemAffinityInfoEntryPtr = MakeMemAffinityInfoEntry (Domain, DramBase, (ValueTOM - DramBase), MemAffinityInfoEntryPtr);
+ NumOfMemAffinityInfoEntries ++;
+ isModified = TRUE;
+ }
+
+ if ((ValueLimit > FOURGB) && (DramBase < FOURGB)) {
+ // TRUNCATE HIGH!!! Shrink entry above 4GB...
+ // Size = Base + Size - 4GB, Base = 4GB
+ MemAffinityInfoEntryPtr = MakeMemAffinityInfoEntry (Domain, FOURGB, (DramLeng + DramBase - FOURGB), MemAffinityInfoEntryPtr);
+ NumOfMemAffinityInfoEntries ++;
+ isModified = TRUE;
+ }
+
+ if ((DramBase >= ValueTOM) && (ValueLimit <= FOURGB)) {
+ // IGNORE!!! Entry located entirely within memory hole
+ isModified = TRUE;
+ }
+
+ if ((DramBase < TopOfMemoryAbove4Gb) && (ValueLimit > TopOfMemoryAbove4Gb)) {
+ // Truncate to TOM2
+ // Base = DramBase, Size = TOM2 - DramBase
+ MemAffinityInfoEntryPtr = MakeMemAffinityInfoEntry (Domain, DramBase, (TopOfMemoryAbove4Gb - DramBase), MemAffinityInfoEntryPtr);
+ NumOfMemAffinityInfoEntries ++;
+ isModified = TRUE;
+ }
+
+ if (DramBase >= TopOfMemoryAbove4Gb) {
+ // IGNORE!!! Entry located entirely above TOM2
+ isModified = TRUE;
+ }
+
+ // If special range(isModified), we are done.
+ // If not, finally write the memory entry.
+ if (isModified == FALSE) {
+ // Finally write the memory entry.
+ MemAffinityInfoEntryPtr = MakeMemAffinityInfoEntry (Domain, DramBase, DramLeng, MemAffinityInfoEntryPtr);
+ NumOfMemAffinityInfoEntries ++;
+ }
+ }
+
+ MemAffinityInfoHeaderPtr->NumOfMemAffinityInfoEntries = NumOfMemAffinityInfoEntries;
+ MemAffinityInfoHeaderPtr->MemoryWidth = NBPtr->MemNGetMemoryWidth (NBPtr);
+
+ return TRUE;
+}
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will add Memory entry.
+ *
+ * Parameters:
+ * @param[in] Domain Proximity Domain
+ * @param[in] Base Memory Base
+ * @param[in] Size Memory Size
+ * @param[in] BufferLocPtr Point to the address of buffer
+ *
+ * @retval CRAT_MEMORY_AFFINITY_INFO_ENTRY * (new buffer location ptr)
+ */
+CRAT_MEMORY_AFFINITY_INFO_ENTRY
+STATIC
+*MakeMemAffinityInfoEntry (
+ IN UINT8 Domain,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN CRAT_MEMORY_AFFINITY_INFO_ENTRY *BufferLocPtr
+ )
+{
+ BufferLocPtr->Domain = Domain;
+ BufferLocPtr->BaseAddressLow = Base << 16;
+ BufferLocPtr->BaseAddressHigh = Base >> 16;
+ BufferLocPtr->LengthLow = Size << 16;
+ BufferLocPtr->LengthHigh = Size >> 16;
+ BufferLocPtr ++;
+
+ return BufferLocPtr;
+} \ No newline at end of file