summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c b/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c
new file mode 100644
index 0000000000..e3ba90244a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/CPU/Feature/cpuSrat.c
@@ -0,0 +1,565 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD SRAT, ACPI table related API functions.
+ *
+ * Contains code that Create the APCI SRAT Table after early reset.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 35658 $ @e \$Date: 2010-07-28 18:11:31 +0800 (Wed, 28 Jul 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "cpuServices.h"
+#include "OptionSrat.h"
+#include "heapManager.h"
+#include "cpuRegisters.h"
+#include "cpuLateInit.h"
+#include "Ids.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUSRAT_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+extern OPTION_SRAT_CONFIGURATION OptionSratConfiguration; // global user config record
+
+#define NodeID 0x60
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * All of the DATA should be defined in _CODE segment.
+ * Use ROMDATA to specify that it belongs to _CODE.
+ *----------------------------------------------------------------------------
+ */
+STATIC CPU_SRAT_HEADER ROMDATA CpuSratHdrStruct =
+{
+ 'S','R','A','T',
+ 0,
+ 2,
+ 0,
+ 'A','M','D',' ',' ',' ',
+ 'A','G','E','S','A',' ',' ',' ',
+ 1,
+ 'A','M','D',' ',
+ 1,
+ 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
+ *----------------------------------------------------------------------------------------
+ */
+UINT8
+STATIC
+*MakeApicEntry (
+ IN UINT8 ApicId,
+ IN UINT8 Domain,
+ IN UINT8 *BufferLocPtr
+ );
+
+UINT8
+STATIC
+*FillMemoryForCurrentNode (
+ IN UINT8 *PDomain,
+ IN OUT UINT8 *PDomainForBase640K,
+ IN UINT8 Node,
+ IN OUT UINT8 *BufferLocPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+UINT8
+STATIC
+*MakeMemEntry (
+ IN UINT8 PDomain,
+ IN UINT8 Node,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN UINT8 *BufferLocPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Static Resource Affinity Table
+ * i.e. SRAT 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[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+CreateAcpiSrat (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntrySrat, StdHeader);
+ return ((*(OptionSratConfiguration.SratFeature)) (StdHeader, SratPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the SRAT 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[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiSratStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Static Resource Affinity Table
+ * i.e. SRAT 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[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiSratMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ UINT8 *BufferPtr;
+ UINT8 NodeNum;
+ UINT8 NodeCount;
+ UINT8 PDomain;
+ UINT8 PDomainForBase640K;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 LowCore;
+ UINT32 HighCore;
+ UINT32 CoreNum;
+ UINT32 RegVal;
+ UINT32 tempVar_32;
+ AMD_APIC_PARAMS ApicParams;
+ PCI_ADDR PciAddress;
+ CPU_SRAT_HEADER *CpuSratHeaderStructPtr;
+ ALLOCATE_HEAP_PARAMS AllocParams;
+
+ // Get Node count
+ PciAddress.AddressValue = MAKE_SBDFO (0, 0, LOW_NODE_DEVICEID, FUNC_0, NodeID);
+ LibAmdPciRead (AccessWidth32 , PciAddress, &RegVal, StdHeader);
+ NodeCount = (UINT8) (((RegVal >> 4) & 0x7) + 1);
+
+ // The worst-case buffer size to request is for the SRAT table header, one
+ // entree for special region (base 640k block), two memory
+ // regions per node, and APIC entries for each core in the system.
+ tempVar_32 = (sizeof (CPU_SRAT_HEADER)) + (sizeof (CPU_SRAT_MEMORY_ENTRY))
+ + ((UINT32) NodeCount * (2 * (sizeof (CPU_SRAT_MEMORY_ENTRY))
+ + ((UINT32) GetActiveCoresInCurrentModule (StdHeader) * sizeof (CPU_SRAT_APIC_ENTRY))));
+
+ if (*SratPtr == NULL) {
+ //
+ // Allocate a buffer
+ //
+ AllocParams.RequestedBufferSize = tempVar_32;
+ AllocParams.BufferHandle = AMD_SRAT_INFO_BUFFER_HANDLE;
+ AllocParams.Persist = HEAP_SYSTEM_MEM;
+
+ AGESA_TESTPOINT (TpProcCpuBeforeAllocateSratBuffer, StdHeader);
+ if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpProcCpuAfterAllocateSratBuffer, StdHeader);
+
+ *SratPtr = AllocParams.BufferPtr;
+ }
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " SRAT is created\n");
+
+ CpuSratHeaderStructPtr = (CPU_SRAT_HEADER *) *SratPtr;
+ BufferPtr = (UINT8 *) *SratPtr;
+
+ // Copy acpiSRATHeader -> data buffer
+ LibAmdMemCopy (*SratPtr, (VOID *) &CpuSratHdrStruct, (UINTN) (sizeof (CPU_SRAT_HEADER)), StdHeader);
+
+ BufferPtr += sizeof (CPU_SRAT_HEADER);
+
+ // Place all memory and IO affinity entries
+ NodeNum = 0;
+ PDomain = 0;
+ PDomainForBase640K = 0xFF;
+ ApicParams.StdHeader = *StdHeader;
+ while (NodeNum < NodeCount) {
+ GetSocketModuleOfNode ((UINT32) NodeNum, &Socket, &Module, StdHeader);
+ GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader);
+ BufferPtr = FillMemoryForCurrentNode (&PDomain, &PDomainForBase640K, NodeNum, BufferPtr, StdHeader);
+ for (CoreNum = LowCore; CoreNum <= HighCore; CoreNum++) {
+ ApicParams.Socket = (UINT8) Socket;
+ ApicParams.Core = (UINT8) CoreNum;
+ AmdGetApicId (&ApicParams);
+ if (ApicParams.IsPresent) {
+ BufferPtr = MakeApicEntry (ApicParams.ApicAddress, PDomain, BufferPtr);
+ }
+ }
+
+ NodeNum++;
+ PDomain = NodeNum;
+ }
+
+ // Store size in table (current buffer offset - buffer start offset)
+ CpuSratHeaderStructPtr->TableLength = (UINT32) (BufferPtr - (UINT8 *) CpuSratHeaderStructPtr);
+
+ //Update SSDT header Checksum
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) CpuSratHeaderStructPtr, StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will build Memory entry for current node.
+ * Note that we only create a memory affinity entry if we find one
+ * that matches the current node. This makes an easier to read table
+ * though it is not necessary.
+ *
+ * @param[in] PDomain Proximity Domain
+ * @param[in, out] PDomainForBase640K The PDomain for Base 640K
+ * @param[in] Node The number of Node
+ * @param[in, out] BufferLocPtr Point to the address of buffer
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ * @retval UINT8 *(New buffer location ptr)
+ */
+UINT8
+STATIC
+*FillMemoryForCurrentNode (
+ IN UINT8 *PDomain,
+ IN OUT UINT8 *PDomainForBase640K,
+ IN UINT8 Node,
+ IN OUT UINT8 *BufferLocPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 ValueLimit;
+ UINT32 ValueTOM;
+ BOOLEAN isModified;
+ UINT8 Domain;
+ UINT32 RegVal;
+ UINT32 DramLeng;
+ UINT32 DramBase;
+ UINT32 DramLimit;
+ UINT32 OffsetRegs;
+ PCI_ADDR PciAddress;
+ UINT64 MsrValue;
+
+ Domain = *PDomain;
+
+ PciAddress.Address.Segment = 0;
+ PciAddress.Address.Bus = 0;
+ PciAddress.Address.Device = LOW_NODE_DEVICEID;
+ PciAddress.Address.Function = FUNC_1;
+
+ for (OffsetRegs = DRAMBase0; OffsetRegs < MMIOBase0; OffsetRegs += 8) {
+ isModified = FALSE; // FALSE means normal update procedure
+ // Get DRAM Base Address
+ PciAddress.Address.Register = OffsetRegs;
+ LibAmdPciRead (AccessWidth32, PciAddress, &RegVal, StdHeader);
+ if ((RegVal & 3) != 3) {
+ // 0:1 set if memory range enabled
+ // Not set, so we don't have an enabled range
+ continue; // Proceed to next Base register
+ }
+
+ // Get DRAM Limit
+ PciAddress.Address.Register = OffsetRegs + 4;
+ LibAmdPciRead (AccessWidth32, PciAddress, &DramLimit, StdHeader);
+ if (DramLimit == 0xFFFFFFFF) {
+ // Node not installed(all FF's)?
+ continue; // Proceed to next Base register
+ }
+
+ if ((DramLimit & 0xFF) != Node) {
+ // Check if Destination Node ID is current node
+ continue; // Proceed to next Base register
+ }
+
+ // We only add an entry now if detected range belongs to current node/PDomain
+ DramLimit >>= 16; // Get DRAM Limit addr [39:24]
+ DramLimit++; // Add 1 for potential length
+ DramLimit <<= 16; // Restore it to original location
+
+ // Get DRAM Base Address
+ PciAddress.Address.Register = OffsetRegs;
+ LibAmdPciRead (AccessWidth32, PciAddress, &DramBase, StdHeader);
+ DramBase &= 0xFFFF0000; // Keep only Base value [31:16]
+ DramLeng = DramLimit - DramBase; // Subtract base from limit to get length
+
+ // Leave hole for conventional memory (Less than 640K). It must be on CPU 0.
+ if (DramBase == 0) {
+ if (*PDomainForBase640K == 0xFF) {
+ // It is the first time that the range start at 0.
+ // If Yes, then Place 1MB memory gap and save Domain to PDomainForBase640K
+ BufferLocPtr = MakeMemEntry (
+ Domain,
+ Node,
+ 0, // Base = 0
+ 0xA0000 >> 8, // Put it into format used in DRAM regs..
+ BufferLocPtr
+ );
+ DramBase += 0x1000; // Add 1MB, so range = 1MB to Top of Region
+ DramLeng -= 0x1000; // Also subtract 1MB from the length
+ *PDomainForBase640K = Domain; // Save Domain number for memory Less than 640K
+ } 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.
+ *PDomain = *PDomainForBase640K;
+ return (BufferLocPtr);
+ }
+ }
+ LibAmdMsrRead (TOP_MEM, &MsrValue, StdHeader);
+ ValueTOM = (UINT32) MsrValue >> 8; // Save it in 39:24 format
+ ValueLimit = DramBase + DramLeng; // We need to know how large region is
+
+ // 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
+
+ if (((DramBase < ValueTOM) && (ValueLimit <= FOURGB) && (ValueLimit > ValueTOM))
+ || ((DramBase < ValueTOM) && (ValueLimit > FOURGB))) {
+ // TRUNCATE LOW!!! Shrink entry below TOM...
+ // Base = DramBase, Size = TOM - DramBase
+ BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, (ValueTOM - DramBase), BufferLocPtr);
+ isModified = TRUE;
+ }
+
+ if ((ValueLimit > FOURGB) && (DramBase < FOURGB)) {
+ // TRUNCATE HIGH!!! Shrink entry above 4GB...
+ // Size = Base + Size - 4GB, Base = 4GB
+ BufferLocPtr = MakeMemEntry (Domain, Node, FOURGB, (DramLeng + DramBase - FOURGB), BufferLocPtr);
+ isModified = TRUE;
+ }
+
+ if ((DramBase >= ValueTOM) && (ValueLimit <= FOURGB)) {
+ // IGNORE!!! Entry located entirely within memory hole
+ isModified = TRUE;
+ }
+
+ // If special range(isModified), we are done.
+ // If not, finally write the memory entry.
+ if (isModified == FALSE) {
+ // Finally write the memory entry.
+ BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, DramLeng, BufferLocPtr);
+ }
+
+ } // for ( OffsetRegs = DRAMBase0; ... )
+
+ return (BufferLocPtr);
+} // FillMemoryForCurrentNode()
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add APIC entry.
+ *
+ * @param[in] ApicId APIC ID number
+ * @param[in] Domain Domain number
+ * @param[in] BufferLocPtr Point to the address of buffer
+ *
+ * @retval UINT8 *(New buffer location ptr)
+ */
+UINT8
+STATIC
+*MakeApicEntry (
+ IN UINT8 ApicId,
+ IN UINT8 Domain,
+ IN UINT8 *BufferLocPtr
+ )
+{
+ CPU_SRAT_APIC_ENTRY *psSratApicEntry;
+ UINT8 ReservedBytes;
+
+ psSratApicEntry = (CPU_SRAT_APIC_ENTRY *)BufferLocPtr;
+
+ psSratApicEntry->Type = AE_APIC;
+ psSratApicEntry->Length = (UINT8)sizeof (CPU_SRAT_APIC_ENTRY);
+ psSratApicEntry->Domain = Domain;
+ psSratApicEntry->ApicId = ApicId;
+ psSratApicEntry->Flags = ENABLED;
+ psSratApicEntry->LSApicEid = 0;
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratApicEntry->Reserved); ReservedBytes++) {
+ psSratApicEntry->Reserved[ReservedBytes] = 0;
+ }
+ return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_APIC_ENTRY));
+} // MakeApicEntry
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will add Memory entry.
+ *
+ * Parameters:
+ * @param[in] PDomain Proximity Domain
+ * @param[in] Node The number of Node
+ * @param[in] Base Memory Base
+ * @param[in] Size Memory Size
+ * @param[in] BufferLocPtr Point to the address of buffer
+ *
+ * @retval UINT8 * (new buffer location ptr)
+ */
+UINT8
+STATIC
+*MakeMemEntry (
+ IN UINT8 PDomain,
+ IN UINT8 Node,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN UINT8 *BufferLocPtr
+ )
+{
+ CPU_SRAT_MEMORY_ENTRY *psSratMemEntry;
+ UINT8 ReservedBytes;
+
+ psSratMemEntry = (CPU_SRAT_MEMORY_ENTRY *)BufferLocPtr;
+
+ psSratMemEntry->Type = AE_MEMORY; // [0] = Memory Entry
+ psSratMemEntry->Length = (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY); // [1] = 40
+ psSratMemEntry->Domain = PDomain; // [2] = Proximity Domain
+
+ // [6-7] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved1); ReservedBytes++) {
+ psSratMemEntry->Reserved1[ReservedBytes] = 0;
+ }
+
+ // [8-11] = Keep 31:0 of address only -> Base Addr Low
+ psSratMemEntry->BaseAddrLow = Base << 8;
+
+ // [12-15] = Keep 39:32 of address only -> Base Addr High
+ psSratMemEntry->BaseAddrHigh = Base >> 24;
+
+ // [16-19] = Keep 31:0 of address only -> Length Low
+ psSratMemEntry->LengthAddrLow = Size << 8;
+
+ // [20-23] = Keep 39:32 of address only -> Length High
+ psSratMemEntry->LengthAddrHigh = Size >> 24;
+
+ // [24-27] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved2); ReservedBytes++) {
+ psSratMemEntry->Reserved2[ReservedBytes] = 0;
+ }
+
+ // [28-31] = Flags
+ psSratMemEntry->Flags = ENABLED;
+
+ // [32-40] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved3); ReservedBytes++) {
+ psSratMemEntry->Reserved3[ReservedBytes] = 0;
+ }
+ return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY));
+} // MakeMemEntry()
+