W dniu 13.12.2023 o 10:20, Xiong Yining pisze:
Add support to create SRAT(System resource affinity table) for sbsa platform at runtime.
Signed-off-by: Xiong Yining xiongyining1480@phytium.com.cn Signed-off-by: Chen Baozi chenbaozi@phytium.com.cn
.../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c | 91 +++++++++++++++++++ .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.h | 28 ++++++ .../SbsaQemu/Include/Library/QemuSbsaSmc.h | 10 ++ .../Library/SbsaQemuSmc/SbsaQemuSmc.c | 22 +++++ .../Library/SbsaQemuSmc/SbsaQemuSmc.inf | 3 + 5 files changed, 154 insertions(+)
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c index 89c4b797d2..abbf891514 100644 --- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c +++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c @@ -748,6 +748,90 @@ DisableXhciOnOlderPlatVer ( return Status; } +/*
- A function that adds the SRAT ACPI table.
- */
+EFI_STATUS +AddSratTable (
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
- )
+{
- EFI_STATUS Status;
- UINT8 *New;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINTN TableHandle;
- UINT32 TableSize;
- UINT32 Index;
- UINT32 NodeId;
- UINT32 NumMemNode;
NumMemNodeCount or NumMemNodes
- MemoryInfo MemInfo;
- UINT32 NumCores = PcdGet32 (PcdCoreCount);
- // Initialize MADT ACPI Header
s/MADT/SRAT/
- EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER Header = {
SBSAQEMU_ACPI_HEADER (EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,
EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER,
EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION),
1, 0 };
- NumMemNode = SbsaQemuGetMemNode();
- // Calculate the new table size based on the number of cores
- TableSize = sizeof (EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER) +
(sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE) * NumMemNode) +
(sizeof (EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE) * NumCores);
- Status = gBS->AllocatePages (
AllocateAnyPages,
EfiACPIReclaimMemory,
EFI_SIZE_TO_PAGES (TableSize),
&PageAddress
);
- if (EFI_ERROR(Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to allocate pages for SRAT table\n"));
- return EFI_OUT_OF_RESOURCES;
- }
- New = (UINT8 *)(UINTN) PageAddress;
- ZeroMem (New, TableSize);
- // Add the ACPI Description table header
- CopyMem (New, &Header, sizeof (EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER));
- ((EFI_ACPI_DESCRIPTION_HEADER*) New)->Length = TableSize;
- New += sizeof (EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER);
- // Add new memory structures
s/new//
- for (Index = 0; Index < NumMemNode; Index++) {
- MemInfo = SbsaQemuGetMemInfo (Index);
- EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE memory = SBSAQEMU_ACPI_MEMORY_AFFINITY_STRUCTURE_INIT (MemInfo.NodeId, MemInfo.AddressBase, MemInfo.AddressSize, 1);
- CopyMem (New, &memory, sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE));
- New += sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE);
- }
- // Add new professor structures for the Cores
s/professor/processor/ s/Cores/cores
- for (Index = 0; Index < NumCores; Index++) {
- NodeId = SbsaQemuGetCpuNumaNode(Index);
- EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE gicc = SBSAQEMU_ACPI_GICC_AFFINITY_STRUCTURE_INIT(NodeId, Index, 1, 0);
- CopyMem (New, &gicc, sizeof (EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE));
- New += sizeof (EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE);
- }
- // Perform Checksum
- AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
- Status = AcpiTable->InstallAcpiTable (
AcpiTable,
(EFI_ACPI_COMMON_HEADER *)PageAddress,
TableSize,
&TableHandle
);
- if (EFI_ERROR(Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to install SRAT table\n"));
- }
- return Status;
+} EFI_STATUS EFIAPI @@ -799,6 +883,13 @@ InitializeSbsaQemuAcpiDxe ( DEBUG ((DEBUG_ERROR, "Failed to add GTDT table\n")); }
- if (SbsaQemuGetNumNumaNode() > 1){
Can we put SRAT for 1 node system or is it against rules?
- Status = AddSratTable (AcpiTable);
- if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to add SRAT table\n"));
- }
- }
- Status = DisableXhciOnOlderPlatVer (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed to handle XHCI enablement\n"));
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.h b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.h index 7595df4c8a..1cf14952e5 100644 --- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.h +++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.h @@ -39,6 +39,34 @@ typedef struct { EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE mGwdt; } GENERIC_TIMER_DESCRIPTION_TABLES; +#define SBSAQEMU_ACPI_MEMORY_AFFINITY_STRUCTURE_INIT( \
ProximityDomain, Base, Length, Flags) \
- { \
- 1, /* Type */ \
- sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE), /* Length */ \
- ProximityDomain, /* Proximity Domain */ \
- 0, /* Reserved */ \
- (Base) & 0xffffffff, /* Base Address Low */ \
- ((Base) >> 32) & 0xffffffff , /* Base Address High */ \
- (Length) & 0xffffffff, /* Length Low */ \
- ((Length) >> 32) & 0xffffffff, /* Length High */ \
- 0, /* Reserved */ \
- Flags, /* Flags */ \
- 0 /* Reserved */ \
- }
+#define SBSAQEMU_ACPI_GICC_AFFINITY_STRUCTURE_INIT( \
ProximityDomain, ACPIProcessorUID, Flags, ClockDomain) \
- { \
- 3, /* Type */ \
- sizeof (EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE), /* Length */ \
- ProximityDomain, /* Proximity Domain */ \
- ACPIProcessorUID, /* ACPI Processor UID */ \
- Flags, /* Flags */ \
- ClockDomain /* Clock Domain */ \
- }
- #ifndef SYSTEM_TIMER_BASE_ADDRESS #define SYSTEM_TIMER_BASE_ADDRESS MAX_ADDRESS #endif
diff --git a/Silicon/Qemu/SbsaQemu/Include/Library/QemuSbsaSmc.h b/Silicon/Qemu/SbsaQemu/Include/Library/QemuSbsaSmc.h index 4d9b8b95e7..db55d7e407 100644 --- a/Silicon/Qemu/SbsaQemu/Include/Library/QemuSbsaSmc.h +++ b/Silicon/Qemu/SbsaQemu/Include/Library/QemuSbsaSmc.h @@ -61,4 +61,14 @@ SbsaQemuGetMemInfo ( IN UINTN MemNode ); +/**
- Get the number of numa node from device tree passed by Qemu.
- @retval the number of numa node.
+**/ +UINT64 +SbsaQemuGetNumNumaNode (
- VOID
- );
- #endif /* QEMU_SBSA_SMC_ */
diff --git a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.c b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.c index f7c5308a63..4c0a0af1e4 100644 --- a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.c +++ b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.c @@ -97,4 +97,26 @@ SbsaQemuGetMemInfo ( } return MemInfo; +}
+UINT64 +SbsaQemuGetNumNumaNode (
- VOID
+) +{
- UINT64 Arg;
- UINT32 Index;
- UINT32 NumNumaNodes;
- UINT32 NumCores = PcdGet32 (PcdCoreCount);
- NumNumaNodes = 1;
- for (Index = 0; Index < NumCores; Index ++){
For multiple numa nodes I use those qemu arguments:
-smp 4,sockets=4,maxcpus=4 -m 4G,slots=2,maxmem=5G -object memory-backend-ram,size=3G,id=m0 -object memory-backend-ram,size=1G,id=m1 -numa node,nodeid=0,cpus=0-1,memdev=m0 -numa node,nodeid=1,memdev=m1,initiator=0 -numa node,nodeid=2,cpus=2-3
("--numa" argument to my "boot-sbsa-ref.sh" script [1])
1. https://github.com/hrw/sbsa-ref-status/blob/main/boot-sbsa-ref.sh
Node 1 has no cpus. Will your code report 2 numa nodes or 3?
Or if I move memory only node to be last:
-numa node,nodeid=0,cpus=0-1,memdev=m0 -numa node,nodeid=1,cpus=2-3 -numa node,nodeid=2,memdev=m1,initiator=0
Then function will see node 0, node 1 and finish.
Maybe it should walk through cpu nodes and memory nodes and check numa node ids? (do we ignore no-cpu, no-memory numa nodes here?)
- Arg = SbsaQemuGetCpuNumaNode(Index);
- if (NumNumaNodes == 1 || NumNumaNodes < (Arg + 1)){
NumNumaNodes = Arg + 1;
- }
- }
- return NumNumaNodes; }
\ No newline at end of file diff --git a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.inf b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.inf index 3eae73650e..95302b6895 100644 --- a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.inf +++ b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuSmc/SbsaQemuSmc.inf @@ -26,3 +26,6 @@ ArmSmcLib BaseMemoryLib DebugLib
+[Pcd]
- gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdCoreCount