从inf文件可以看到这是一个DXE_DRIVER,其入口函数是AcpiPlatformEntryPoint
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = AcpiPlatform
MODULE_UNI_FILE = AcpiPlatform.uni
FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = AcpiPlatformEntryPoint
在其入口函数AcpiPlatformEntryPoint中会调用PlatformUpdateTables 来更新APCI的SRAT表
EFI_STATUS
PlatformUpdateTables (
IN OUT EFI_ACPI_COMMON_HEADER **Table
)
{
EFI_STATUS Status;
EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
Status = EFI_SUCCESS;
//强转指针后,调用UpdateAcpiTable来更新SRAT
TableHeader = (EFI_ACPI_DESCRIPTION_HEADER*) (*Table);
UpdateAcpiTable(TableHeader, &Status);
return Status;
}
VOID
UpdateAcpiTable (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
IN OUT EFI_STATUS *CommonCodeReturnStatus
)
{
switch ((TableHeader)->Signature) {
case EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE:
*CommonCodeReturnStatus = UpdateSrat (TableHeader);
break;
case EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
*CommonCodeReturnStatus = UpdateSlit (TableHeader);
break;
}
return;
}
根据Signature 来决定更新是srat还是slit。这里以srat为例
STATIC
EFI_STATUS
UpdateSrat (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table
)
{
UINT8 Skt = 0;
UINT8 Ch = 0;
VOID* HobList;
GBL_DATA *Gbl_Data;
UINTN Base;
UINTN Size;
UINT8 NodeId;
UINT32 DieInterleaveEn;
UINT8 i;
DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT memory information!\n" ));
// 原来这里也是从HOB中拿到memory的信息,也就说在SEC 阶段就已经建立好memory的HOB信息,后续所以关于硬件的信息其实都是从HOB中的到的.
HobList = GetHobList();
Gbl_Data = (GBL_DATA*)GetNextGuidHob(&gHisiEfiMemoryMapGuid, HobList);
Gbl_Data = GET_GUID_HOB_DATA(Gbl_Data);
for(Skt = 0; Skt < MAX_SOCKET; Skt++){
for(Ch = 0; Ch < MAX_NUM_PER_TYPE; Ch++){
NodeId = Gbl_Data->NumaInfo[Skt][Ch].NodeId;
Base = Gbl_Data->NumaInfo[Skt][Ch].Base;
Size = Gbl_Data->NumaInfo[Skt][Ch].Length;
DieInterleaveEn = Gbl_Data->NumaInfo[Skt][Ch].DieInterleaveEn;
DEBUG((EFI_D_INFO,"Skt %d Ch: %d NodeId = %d, Base = 0x%lx, Size = 0x%lx, DieInterLeaveEn = %d\n",Skt,Ch,NodeId,Base,Size,DieInterleaveEn));
if (Size > 0)
{
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].ProximityDomain = NodeId;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseLow = Base;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseHigh = Base >> 32;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthLow = Size;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthHigh = Size >> 32;
MemoryNode = MemoryNode + 1;
}
}
}
//update gicc structure
if(DieInterleaveEn != 0)
{
DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT Gicc information!\n" ));
for (i = 0; i < 32; i ++)
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 0;
for (i = 32; i < 64; i ++)
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 2;
}
//remove invalid memory node
(VOID)RemoveInvalidMemoryNode (Table, MemoryNode);
return EFI_SUCCESS;
}
这样在kernel初始化阶段就可以看到从SRAT表中得到memory信息
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x00000000-0x3fffffff]
[ 0.000000] NUMA: Adding memblock [0x2000000000 - 0x2fffffffff] on node 1
[ 0.000000] ACPI: SRAT: Node 1 PXM 1 [mem 0x2000000000-0x2fffffffff]
[ 0.000000] NUMA: Adding memblock [0x1000000000 - 0x1fffffffff] on node 0
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x1000000000-0x1fffffffff]
[ 0.000000] NUMA: Adding memblock [0x40000000000 - 0x4003fffffff] on node 2
[ 0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x40000000000-0x4003fffffff]
[ 0.000000] NUMA: Adding memblock [0x42000000000 - 0x42fffffffff] on node 3
[ 0.000000] ACPI: SRAT: Node 3 PXM 3 [mem 0x42000000000-0x42fffffffff]
[ 0.000000] NUMA: Adding memblock [0x41000000000 - 0x41fffffffff] on node 2
[ 0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x41000000000-0x41fffffffff]
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = AcpiPlatform
MODULE_UNI_FILE = AcpiPlatform.uni
FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = AcpiPlatformEntryPoint
在其入口函数AcpiPlatformEntryPoint中会调用PlatformUpdateTables 来更新APCI的SRAT表
EFI_STATUS
PlatformUpdateTables (
IN OUT EFI_ACPI_COMMON_HEADER **Table
)
{
EFI_STATUS Status;
EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
Status = EFI_SUCCESS;
//强转指针后,调用UpdateAcpiTable来更新SRAT
TableHeader = (EFI_ACPI_DESCRIPTION_HEADER*) (*Table);
UpdateAcpiTable(TableHeader, &Status);
return Status;
}
VOID
UpdateAcpiTable (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
IN OUT EFI_STATUS *CommonCodeReturnStatus
)
{
switch ((TableHeader)->Signature) {
case EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE:
*CommonCodeReturnStatus = UpdateSrat (TableHeader);
break;
case EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
*CommonCodeReturnStatus = UpdateSlit (TableHeader);
break;
}
return;
}
根据Signature 来决定更新是srat还是slit。这里以srat为例
STATIC
EFI_STATUS
UpdateSrat (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table
)
{
UINT8 Skt = 0;
UINT8 Ch = 0;
VOID* HobList;
GBL_DATA *Gbl_Data;
UINTN Base;
UINTN Size;
UINT8 NodeId;
UINT32 DieInterleaveEn;
UINT8 i;
DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT memory information!\n" ));
// 原来这里也是从HOB中拿到memory的信息,也就说在SEC 阶段就已经建立好memory的HOB信息,后续所以关于硬件的信息其实都是从HOB中的到的.
HobList = GetHobList();
Gbl_Data = (GBL_DATA*)GetNextGuidHob(&gHisiEfiMemoryMapGuid, HobList);
Gbl_Data = GET_GUID_HOB_DATA(Gbl_Data);
for(Skt = 0; Skt < MAX_SOCKET; Skt++){
for(Ch = 0; Ch < MAX_NUM_PER_TYPE; Ch++){
NodeId = Gbl_Data->NumaInfo[Skt][Ch].NodeId;
Base = Gbl_Data->NumaInfo[Skt][Ch].Base;
Size = Gbl_Data->NumaInfo[Skt][Ch].Length;
DieInterleaveEn = Gbl_Data->NumaInfo[Skt][Ch].DieInterleaveEn;
DEBUG((EFI_D_INFO,"Skt %d Ch: %d NodeId = %d, Base = 0x%lx, Size = 0x%lx, DieInterLeaveEn = %d\n",Skt,Ch,NodeId,Base,Size,DieInterleaveEn));
if (Size > 0)
{
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].ProximityDomain = NodeId;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseLow = Base;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].AddressBaseHigh = Base >> 32;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthLow = Size;
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Memory[MemoryNode].LengthHigh = Size >> 32;
MemoryNode = MemoryNode + 1;
}
}
}
//update gicc structure
if(DieInterleaveEn != 0)
{
DEBUG(( EFI_D_ERROR, "\nSRAT: Updating SRAT Gicc information!\n" ));
for (i = 0; i < 32; i ++)
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 0;
for (i = 32; i < 64; i ++)
((EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE *) Table)->Gicc[i].ProximityDomain = 2;
}
//remove invalid memory node
(VOID)RemoveInvalidMemoryNode (Table, MemoryNode);
return EFI_SUCCESS;
}
这样在kernel初始化阶段就可以看到从SRAT表中得到memory信息
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x00000000-0x3fffffff]
[ 0.000000] NUMA: Adding memblock [0x2000000000 - 0x2fffffffff] on node 1
[ 0.000000] ACPI: SRAT: Node 1 PXM 1 [mem 0x2000000000-0x2fffffffff]
[ 0.000000] NUMA: Adding memblock [0x1000000000 - 0x1fffffffff] on node 0
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x1000000000-0x1fffffffff]
[ 0.000000] NUMA: Adding memblock [0x40000000000 - 0x4003fffffff] on node 2
[ 0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x40000000000-0x4003fffffff]
[ 0.000000] NUMA: Adding memblock [0x42000000000 - 0x42fffffffff] on node 3
[ 0.000000] ACPI: SRAT: Node 3 PXM 3 [mem 0x42000000000-0x42fffffffff]
[ 0.000000] NUMA: Adding memblock [0x41000000000 - 0x41fffffffff] on node 2
[ 0.000000] ACPI: SRAT: Node 2 PXM 2 [mem 0x41000000000-0x41fffffffff]