blob: dcd3d7126b2193e4b061a5cf50dc6b615db9934d [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * AMD SRAT, ACPI table related API functions.
6 *
7 * Contains code that Create the APCI SRAT Table after early reset.
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: CPU
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 */
15/*
16 ******************************************************************************
17 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080018 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
19 * All rights reserved.
zbao7d94cf92012-07-02 14:19:14 +080020 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080021 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
zbao7d94cf92012-07-02 14:19:14 +080031 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080032 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zbao7d94cf92012-07-02 14:19:14 +080042 ***************************************************************************/
43
44
45/*----------------------------------------------------------------------------
46 * This file provides functions, that will generate SRAT tables
47 *----------------------------------------------------------------------------
48 */
49
50/*----------------------------------------------------------------------------------------
51 * M O D U L E S U S E D
52 *----------------------------------------------------------------------------------------
53 */
54#include "AGESA.h"
55#include "amdlib.h"
56#include "cpuServices.h"
57#include "OptionSrat.h"
58#include "heapManager.h"
59#include "cpuRegisters.h"
60#include "cpuLateInit.h"
61#include "Ids.h"
62#include "Filecode.h"
63CODE_GROUP (G3_DXE)
64RDATA_GROUP (G3_DXE)
65
66#define FILECODE PROC_CPU_FEATURE_CPUSRAT_FILECODE
67/*----------------------------------------------------------------------------------------
68 * D E F I N I T I O N S A N D M A C R O S
69 *----------------------------------------------------------------------------------------
70 */
71extern OPTION_SRAT_CONFIGURATION OptionSratConfiguration; // global user config record
72
73#define NodeID 0x60
74#define FOURGB 0x010000ul
75
76/*----------------------------------------------------------------------------------------
77 * T Y P E D E F S A N D S T R U C T U R E S
78 *----------------------------------------------------------------------------------------
79 */
80AGESA_STATUS
81GetAcpiSratStub (
82 IN OUT AMD_CONFIG_PARAMS *StdHeader,
83 IN OUT VOID **SratPtr
84 );
85
86AGESA_STATUS
87GetAcpiSratMain (
88 IN OUT AMD_CONFIG_PARAMS *StdHeader,
89 IN OUT VOID **SratPtr
90 );
91
92/*----------------------------------------------------------------------------
93 * All of the DATA should be defined in _CODE segment.
94 * Use ROMDATA to specify that it belongs to _CODE.
95 *----------------------------------------------------------------------------
96 */
97STATIC CPU_SRAT_HEADER ROMDATA CpuSratHdrStruct =
98{
99 {'S','R','A','T'},
100 0,
101 2,
102 0,
103 {'A','M','D',' ',' ',' '},
104 {'A','G','E','S','A',' ',' ',' '},
105 1,
106 {'A','M','D',' '},
107 1,
108 1,
109 {0, 0, 0, 0, 0, 0, 0, 0}
110};
111
112/*----------------------------------------------------------------------------------------
113 * 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
114 *----------------------------------------------------------------------------------------
115 */
116UINT8
117STATIC
118*MakeApicEntry (
119 IN UINT8 ApicId,
120 IN UINT8 Domain,
121 IN UINT8 *BufferLocPtr
122 );
123
124UINT8
125STATIC
126*FillMemoryForCurrentNode (
127 IN UINT8 *PDomain,
128 IN OUT UINT8 *PDomainForBase640K,
129 IN UINT8 Node,
130 IN OUT UINT8 *BufferLocPtr,
131 IN OUT AMD_CONFIG_PARAMS *StdHeader
132 );
133
134UINT8
135STATIC
136*MakeMemEntry (
137 IN UINT8 PDomain,
138 IN UINT8 Node,
139 IN UINT32 Base,
140 IN UINT32 Size,
141 IN UINT8 *BufferLocPtr
142 );
143
144/*----------------------------------------------------------------------------------------
145 * E X P O R T E D F U N C T I O N S
146 *----------------------------------------------------------------------------------------
147 */
148/*---------------------------------------------------------------------------------------*/
149/**
150 *
151 * This function will generate a complete Static Resource Affinity Table
152 * i.e. SRAT into a memory buffer. After completion, this table must be set
153 * by the system BIOS into its internal ACPI name space.
154 *
155 * @param[in, out] StdHeader Standard Head Pointer
156 * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
157 *
158 * @retval AGESA_STATUS
159 */
160
161AGESA_STATUS
162CreateAcpiSrat (
163 IN OUT AMD_CONFIG_PARAMS *StdHeader,
164 IN OUT VOID **SratPtr
165 )
166{
167 AGESA_TESTPOINT (TpProcCpuEntrySrat, StdHeader);
168 return ((*(OptionSratConfiguration.SratFeature)) (StdHeader, SratPtr));
169}
170
171/*---------------------------------------------------------------------------------------*/
172/**
173 *
174 * This is the default routine for use when the SRAT option is NOT requested.
175 *
176 * The option install process will create and fill the transfer vector with
177 * the address of the proper routine (Main or Stub). The link optimizer will
178 * strip out of the .DLL the routine that is not used.
179 *
180 * @param[in, out] StdHeader Standard Head Pointer
181 * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
182 *
183 * @retval AGESA_STATUS
184 */
185
186AGESA_STATUS
187GetAcpiSratStub (
188 IN OUT AMD_CONFIG_PARAMS *StdHeader,
189 IN OUT VOID **SratPtr
190 )
191{
192 return AGESA_UNSUPPORTED;
193}
194/*---------------------------------------------------------------------------------------*/
195/**
196 *
197 * This function will generate a complete Static Resource Affinity Table
198 * i.e. SRAT into a memory buffer. After completion, this table must be set
199 * by the system BIOS into its internal ACPI name space.
200 *
201 * @param[in, out] StdHeader Standard Head Pointer
202 * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
203 *
204 * @retval AGESA_STATUS
205 */
206AGESA_STATUS
207GetAcpiSratMain (
208 IN OUT AMD_CONFIG_PARAMS *StdHeader,
209 IN OUT VOID **SratPtr
210 )
211{
212 UINT8 *BufferPtr;
213 UINT8 NodeNum;
214 UINT8 NodeCount;
215 UINT8 PDomain;
216 UINT8 PDomainForBase640K;
217 UINT32 Socket;
218 UINT32 Module;
219 UINT32 LowCore;
220 UINT32 HighCore;
221 UINT32 CoreNum;
222 UINT32 RegVal;
223 UINT32 tempVar_32;
224 AMD_APIC_PARAMS ApicParams;
225 PCI_ADDR PciAddress;
226 CPU_SRAT_HEADER *CpuSratHeaderStructPtr;
227 ALLOCATE_HEAP_PARAMS AllocParams;
228
229 // Get Node count
230 PciAddress.AddressValue = MAKE_SBDFO (0, 0, LOW_NODE_DEVICEID, FUNC_0, NodeID);
231 LibAmdPciRead (AccessWidth32 , PciAddress, &RegVal, StdHeader);
232 NodeCount = (UINT8) (((RegVal >> 4) & 0x7) + 1);
233
234 // The worst-case buffer size to request is for the SRAT table header, one
235 // entree for special region (base 640k block), two memory
236 // regions per node, and APIC entries for each core in the system.
237 tempVar_32 = (sizeof (CPU_SRAT_HEADER)) + (sizeof (CPU_SRAT_MEMORY_ENTRY))
238 + ((UINT32) NodeCount * (2 * (sizeof (CPU_SRAT_MEMORY_ENTRY))
239 + ((UINT32) GetActiveCoresInCurrentModule (StdHeader) * sizeof (CPU_SRAT_APIC_ENTRY))));
240
241 if (*SratPtr == NULL) {
242 //
243 // Allocate a buffer
244 //
245 AllocParams.RequestedBufferSize = tempVar_32;
246 AllocParams.BufferHandle = AMD_SRAT_INFO_BUFFER_HANDLE;
247 AllocParams.Persist = HEAP_SYSTEM_MEM;
248
249 AGESA_TESTPOINT (TpProcCpuBeforeAllocateSratBuffer, StdHeader);
250 if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) {
251 return AGESA_ERROR;
252 }
253 AGESA_TESTPOINT (TpProcCpuAfterAllocateSratBuffer, StdHeader);
254
255 *SratPtr = AllocParams.BufferPtr;
256 }
257
258 IDS_HDT_CONSOLE (CPU_TRACE, " SRAT is created\n");
259
260 CpuSratHeaderStructPtr = (CPU_SRAT_HEADER *) *SratPtr;
261 BufferPtr = (UINT8 *) *SratPtr;
262
263 // Copy acpiSRATHeader -> data buffer
264 LibAmdMemCopy (*SratPtr, (VOID *) &CpuSratHdrStruct, (UINTN) (sizeof (CPU_SRAT_HEADER)), StdHeader);
265
266 BufferPtr += sizeof (CPU_SRAT_HEADER);
267
268 // Place all memory and IO affinity entries
269 NodeNum = 0;
270 PDomain = 0;
271 PDomainForBase640K = 0xFF;
272 ApicParams.StdHeader = *StdHeader;
273 while (NodeNum < NodeCount) {
274 GetSocketModuleOfNode ((UINT32) NodeNum, &Socket, &Module, StdHeader);
275 GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader);
276 BufferPtr = FillMemoryForCurrentNode (&PDomain, &PDomainForBase640K, NodeNum, BufferPtr, StdHeader);
277 for (CoreNum = LowCore; CoreNum <= HighCore; CoreNum++) {
278 ApicParams.Socket = (UINT8) Socket;
279 ApicParams.Core = (UINT8) CoreNum;
280 AmdGetApicId (&ApicParams);
281 if (ApicParams.IsPresent) {
282 BufferPtr = MakeApicEntry (ApicParams.ApicAddress, PDomain, BufferPtr);
283 }
284 }
285
286 NodeNum++;
287 PDomain = NodeNum;
288 }
289
290 // Store size in table (current buffer offset - buffer start offset)
291 CpuSratHeaderStructPtr->TableLength = (UINT32) (BufferPtr - (UINT8 *) CpuSratHeaderStructPtr);
292
293 //Update SSDT header Checksum
294 ChecksumAcpiTable ((ACPI_TABLE_HEADER *) CpuSratHeaderStructPtr, StdHeader);
295
296 return AGESA_SUCCESS;
297}
298
299
300/*----------------------------------------------------------------------------------------
301 * L O C A L F U N C T I O N S
302 *----------------------------------------------------------------------------------------
303 */
304
305/*---------------------------------------------------------------------------------------*/
306/**
307 *
308 * This function will build Memory entry for current node.
309 * Note that we only create a memory affinity entry if we find one
310 * that matches the current node. This makes an easier to read table
311 * though it is not necessary.
312 *
313 * @param[in] PDomain Proximity Domain
314 * @param[in, out] PDomainForBase640K The PDomain for Base 640K
315 * @param[in] Node The number of Node
316 * @param[in, out] BufferLocPtr Point to the address of buffer
317 * @param[in, out] StdHeader Standard Head Pointer
318 *
319 * @retval UINT8 *(New buffer location ptr)
320 */
321UINT8
322STATIC
323*FillMemoryForCurrentNode (
324 IN UINT8 *PDomain,
325 IN OUT UINT8 *PDomainForBase640K,
326 IN UINT8 Node,
327 IN OUT UINT8 *BufferLocPtr,
328 IN OUT AMD_CONFIG_PARAMS *StdHeader
329 )
330{
331 UINT32 ValueLimit;
332 UINT32 ValueTOM;
333 BOOLEAN isModified;
334 UINT8 Domain;
335 UINT32 RegVal;
336 UINT32 DramLeng;
337 UINT32 DramBase;
338 UINT32 DramLimit;
339 UINT32 OffsetRegs;
340 PCI_ADDR PciAddress;
341 UINT64 MsrValue;
342 UINT32 TopOfMemoryAbove4Gb;
343
344 Domain = *PDomain;
345
346 PciAddress.Address.Segment = 0;
347 PciAddress.Address.Bus = 0;
348 PciAddress.Address.Device = LOW_NODE_DEVICEID;
349 PciAddress.Address.Function = FUNC_1;
350
351 for (OffsetRegs = DRAMBase0; OffsetRegs < MMIOBase0; OffsetRegs += 8) {
352 isModified = FALSE; // FALSE means normal update procedure
353 // Get DRAM Base Address
354 PciAddress.Address.Register = OffsetRegs;
355 LibAmdPciRead (AccessWidth32, PciAddress, &DramBase, StdHeader);
356 if ((DramBase & 3) != 3) {
357 // 0:1 set if memory range enabled
358 // Not set, so we don't have an enabled range
359 continue; // Proceed to next Base register
360 }
361
362 // Get DRAM Limit
363 PciAddress.Address.Register = OffsetRegs + 4;
364 LibAmdPciRead (AccessWidth32, PciAddress, &DramLimit, StdHeader);
365 if (DramLimit == 0xFFFFFFFF) {
366 // Node not installed(all FF's)?
367 continue; // Proceed to next Base register
368 }
369
370 if ((DramLimit & 0xFF) != Node) {
371 // Check if Destination Node ID is current node
372 continue; // Proceed to next Base register
373 }
374
375 // We only add an entry now if detected range belongs to current node/PDomain
376 PciAddress.Address.Register = OffsetRegs + 0x104;
377 LibAmdPciRead (AccessWidth32, PciAddress, &RegVal, StdHeader);
378
379 DramLimit = (((RegVal & 0xFF) << 16) | (DramLimit >> 16)); // Get DRAM Limit addr [47:24]
380 DramLimit++; // Add 1 for potential length
381 DramLimit <<= 8;
382
383 // Get DRAM Base Address
384 PciAddress.Address.Register = OffsetRegs + 0x100;
385 LibAmdPciRead (AccessWidth32, PciAddress, &RegVal, StdHeader);
386 DramBase = ((((RegVal & 0xFF) << 24) | (DramBase >> 8)) & 0xFFFFFF00); // Get DRAM Base Base value [47:24]
387 DramLeng = DramLimit - DramBase; // Subtract base from limit to get length
388
389 // Leave hole for conventional memory (Less than 640K). It must be on CPU 0.
390 if (DramBase == 0) {
391 if (*PDomainForBase640K == 0xFF) {
392 // It is the first time that the range start at 0.
393 // If Yes, then Place 1MB memory gap and save Domain to PDomainForBase640K
394 BufferLocPtr = MakeMemEntry (
395 Domain,
396 Node,
397 0, // Base = 0
398 0xA0000 >> 16, // Put it into format used in DRAM regs..
399 BufferLocPtr
400 );
401 DramBase += 0x10; // Add 1MB, so range = 1MB to Top of Region
402 DramLeng -= 0x10; // Also subtract 1MB from the length
403 *PDomainForBase640K = Domain; // Save Domain number for memory Less than 640K
404 } else {
405 // If No, there are more than one memory range less than 640K, it should that
406 // node interleaving is enabled. All nodes have the same memory ranges
407 // and all cores in these nodes belong to the same domain.
408 *PDomain = *PDomainForBase640K;
409 return (BufferLocPtr);
410 }
411 }
412 LibAmdMsrRead (TOP_MEM, &MsrValue, StdHeader);
413 ValueTOM = (UINT32) MsrValue >> 16; // Save it in 39:24 format
414 ValueLimit = DramBase + DramLeng; // We need to know how large region is
415
416 LibAmdMsrRead (SYS_CFG, &MsrValue, StdHeader);
417 if ((MsrValue & BIT21) != 0) {
418 LibAmdMsrRead (TOP_MEM2, &MsrValue, StdHeader);
419 TopOfMemoryAbove4Gb = (UINT32) (MsrValue >> 16); // Save it in 47:16 format
420 } else {
421 TopOfMemoryAbove4Gb = 0xFFFFFFFF;
422 }
423
424 // SPECIAL CASES:
425 //
426 // Several conditions require that we process the values of the memory range differently.
427 // Here are descriptions of the corner cases.
428 //
429 // 1. TRUNCATE LOW - Memory range starts below TOM, ends in TOM (memory hole). For this case,
430 // the range must be truncated to end at TOM.
431 // ******************************* *******************************
432 // * * * -> * *
433 // ******************************* *******************************
434 // 2 TOM 4 2 TOM
435 //
436 // 2. TRUNCATE HIGH - Memory range starts below 4GB, ends above 4GB. This is handled by changing the
437 // start base to 4GB.
438 // **************** **********
439 // * * * -> * *
440 // **************** **********
441 // TOM 3.8 4 6 TOM 3.8 4 6
442 //
443 // 3. Memory range starts below TOM, ends above 4GB. For this case, the range must be truncated
444 // to end at TOM. Note that this scenario creates two ranges, as the second comparison below
445 // will find that it ends above 4GB since base and limit have been restored after first truncation,
446 // and a second range will be written based at 4GB ending at original end address.
447 // ******************************* **************** **********
448 // * * * * -> * * * *
449 // ******************************* **************** **********
450 // 2 TOM 4 6 2 TOM 4 6
451 //
452 // 4. Memory range starts above TOM, ends below or equal to 4GB. This invalid range should simply
453 // be ignored.
454 // *******
455 // * * -> < NULL >
456 // *******
457 // TOM 3.8 4
458 //
459 // 5. Memory range starts below TOM2, and ends beyond TOM2. This range must be truncated to TOM2.
460 // ************************ *******************************
461 // * * * -> * *
462 // ************************ *******************************
463 // 768 TOM2 1024 768 TOM2
464 //
465 // 6. Memory range starts above TOM2. This invalid range should simply be ignored.
466 // ********************
467 // * * -> < NULL >
468 // ********************
469 // TOM2 1024 1280
470
471 if (((DramBase < ValueTOM) && (ValueLimit <= FOURGB) && (ValueLimit > ValueTOM))
472 || ((DramBase < ValueTOM) && (ValueLimit > FOURGB))) {
473 // TRUNCATE LOW!!! Shrink entry below TOM...
474 // Base = DramBase, Size = TOM - DramBase
475 BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, (ValueTOM - DramBase), BufferLocPtr);
476 isModified = TRUE;
477 }
478
479 if ((ValueLimit > FOURGB) && (DramBase < FOURGB)) {
480 // TRUNCATE HIGH!!! Shrink entry above 4GB...
481 // Size = Base + Size - 4GB, Base = 4GB
482 BufferLocPtr = MakeMemEntry (Domain, Node, FOURGB, (DramLeng + DramBase - FOURGB), BufferLocPtr);
483 isModified = TRUE;
484 }
485
486 if ((DramBase >= ValueTOM) && (ValueLimit <= FOURGB)) {
487 // IGNORE!!! Entry located entirely within memory hole
488 isModified = TRUE;
489 }
490
491 if ((DramBase < TopOfMemoryAbove4Gb) && (ValueLimit > TopOfMemoryAbove4Gb)) {
492 // Truncate to TOM2
493 // Base = DramBase, Size = TOM2 - DramBase
494 BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, (TopOfMemoryAbove4Gb - DramBase), BufferLocPtr);
495 isModified = TRUE;
496 }
497
498 if (DramBase >= TopOfMemoryAbove4Gb) {
499 // IGNORE!!! Entry located entirely above TOM2
500 isModified = TRUE;
501 }
502
503 // If special range(isModified), we are done.
504 // If not, finally write the memory entry.
505 if (isModified == FALSE) {
506 // Finally write the memory entry.
507 BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, DramLeng, BufferLocPtr);
508 }
509
510 } // for ( OffsetRegs = DRAMBase0; ... )
511
512 return (BufferLocPtr);
513} // FillMemoryForCurrentNode()
514
515
516/*---------------------------------------------------------------------------------------*/
517/**
518 * This function will add APIC entry.
519 *
520 * @param[in] ApicId APIC ID number
521 * @param[in] Domain Domain number
522 * @param[in] BufferLocPtr Point to the address of buffer
523 *
524 * @retval UINT8 *(New buffer location ptr)
525 */
526UINT8
527STATIC
528*MakeApicEntry (
529 IN UINT8 ApicId,
530 IN UINT8 Domain,
531 IN UINT8 *BufferLocPtr
532 )
533{
534 CPU_SRAT_APIC_ENTRY *psSratApicEntry;
535 UINT8 ReservedBytes;
536
537 psSratApicEntry = (CPU_SRAT_APIC_ENTRY *)BufferLocPtr;
538
539 psSratApicEntry->Type = AE_APIC;
540 psSratApicEntry->Length = (UINT8)sizeof (CPU_SRAT_APIC_ENTRY);
541 psSratApicEntry->Domain = Domain;
542 psSratApicEntry->ApicId = ApicId;
543 psSratApicEntry->Flags = ENABLED;
544 psSratApicEntry->LSApicEid = 0;
545 for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratApicEntry->Reserved); ReservedBytes++) {
546 psSratApicEntry->Reserved[ReservedBytes] = 0;
547 }
548 return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_APIC_ENTRY));
549} // MakeApicEntry
550
551
552/*---------------------------------------------------------------------------------------*/
553/**
554 *
555 * This function will add Memory entry.
556 *
557 * Parameters:
558 * @param[in] PDomain Proximity Domain
559 * @param[in] Node The number of Node
560 * @param[in] Base Memory Base
561 * @param[in] Size Memory Size
562 * @param[in] BufferLocPtr Point to the address of buffer
563 *
564 * @retval UINT8 * (new buffer location ptr)
565 */
566UINT8
567STATIC
568*MakeMemEntry (
569 IN UINT8 PDomain,
570 IN UINT8 Node,
571 IN UINT32 Base,
572 IN UINT32 Size,
573 IN UINT8 *BufferLocPtr
574 )
575{
576 CPU_SRAT_MEMORY_ENTRY *psSratMemEntry;
577 UINT8 ReservedBytes;
578
579 psSratMemEntry = (CPU_SRAT_MEMORY_ENTRY *)BufferLocPtr;
580
581 psSratMemEntry->Type = AE_MEMORY; // [0] = Memory Entry
582 psSratMemEntry->Length = (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY); // [1] = 40
583 psSratMemEntry->Domain = PDomain; // [2] = Proximity Domain
584
585 // [6-7] = Reserved
586 for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved1); ReservedBytes++) {
587 psSratMemEntry->Reserved1[ReservedBytes] = 0;
588 }
589
590 // [8-11] = Keep 31:0 of address only -> Base Addr Low
591 psSratMemEntry->BaseAddrLow = Base << 16;
592
593 // [12-15] = Keep 39:32 of address only -> Base Addr High
594 psSratMemEntry->BaseAddrHigh = Base >> 16;
595
596 // [16-19] = Keep 31:0 of address only -> Length Low
597 psSratMemEntry->LengthAddrLow = Size << 16;
598
599 // [20-23] = Keep 39:32 of address only -> Length High
600 psSratMemEntry->LengthAddrHigh = Size >> 16;
601
602 // [24-27] = Reserved
603 for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved2); ReservedBytes++) {
604 psSratMemEntry->Reserved2[ReservedBytes] = 0;
605 }
606
607 // [28-31] = Flags
608 psSratMemEntry->Flags = ENABLED;
609
610 // [32-40] = Reserved
611 for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved3); ReservedBytes++) {
612 psSratMemEntry->Reserved3[ReservedBytes] = 0;
613 }
614 return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY));
615} // MakeMemEntry()
616