Hi Nishant, Please find my response inline marked [SAMI]. Regards, Sami Mujawar On 17/06/2022 07:07 am, Nishant Sharma wrote: Isolated CPUs are those that are not to be used on the platform for various reasons. The isolated CPU list is an array of MPID values of [SAMI] Can you explain the use-case/reason, please? the CPUs that have to be isolated. This list is supplied via the NT_FW_CONFIG dtb. Add support to search for isolated CPUs MPID list and, if present, update the MADT table to disable the corresponding CPUs. Signed-off-by: Nishant Sharma --- Platform/ARM/SgiPkg/AcpiTables/RdN2Cfg1AcpiTables.inf | 1 - Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPei.inf | 8 +- Platform/ARM/SgiPkg/Include/SgiPlatform.h | 7 ++ Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.c | 131 +++++++++++++++++++- Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPeim.c | 45 ++++++- 5 files changed, 186 insertions(+), 6 deletions(-) diff --git a/Platform/ARM/SgiPkg/AcpiTables/RdN2Cfg1AcpiTables.inf b/Platform/ARM/SgiPkg/AcpiTables/RdN2Cfg1AcpiTables.inf index 4b36c3e5ceb2..e13c2f08ce6e 100644 --- a/Platform/ARM/SgiPkg/AcpiTables/RdN2Cfg1AcpiTables.inf +++ b/Platform/ARM/SgiPkg/AcpiTables/RdN2Cfg1AcpiTables.inf @@ -18,7 +18,6 @@ Dbg2.aslc Fadt.aslc Gtdt.aslc - Iort.aslc [SAMI] Why is IORT table being removed here? Mcfg.aslc RdN2Cfg1/Dsdt.asl RdN2Cfg1/Madt.aslc diff --git a/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPei.inf b/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPei.inf index 407160c07563..fbf061ad3bdb 100644 --- a/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPei.inf +++ b/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPei.inf @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, ARM Limited. All rights reserved. +# Copyright (c) 2018-2022, ARM Limited. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -13,6 +13,7 @@ ENTRY_POINT = SgiPlatformPeim [Packages] + ArmPlatformPkg/ArmPlatformPkg.dec EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec Platform/ARM/SgiPkg/SgiPlatform.dec @@ -21,6 +22,11 @@ FdtLib PeimEntryPoint +[FixedPcd] + gArmSgiTokenSpaceGuid.PcdChipCount + gArmPlatformTokenSpaceGuid.PcdCoreCount + gArmPlatformTokenSpaceGuid.PcdClusterCount + [Sources] SgiPlatformPeim.c diff --git a/Platform/ARM/SgiPkg/Include/SgiPlatform.h b/Platform/ARM/SgiPkg/Include/SgiPlatform.h index dddb58832d73..311286ce5337 100644 --- a/Platform/ARM/SgiPkg/Include/SgiPlatform.h +++ b/Platform/ARM/SgiPkg/Include/SgiPlatform.h @@ -65,11 +65,18 @@ #define DRAM_BLOCK2_BASE_REMOTE(ChipId) \ (SGI_REMOTE_CHIP_MEM_OFFSET (ChipId) + FixedPcdGet64 (PcdDramBlock2Base)) +// List of isolated CPUs MPID +typedef struct { + UINT64 Count; // Number of elements present in the list + UINT64 Mpid[]; // List containing isolated CPU MPIDs +} SGI_ISOLATED_CPU_LIST; + // ARM platform description data. typedef struct { UINTN PlatformId; UINTN ConfigId; UINTN MultiChipMode; + SGI_ISOLATED_CPU_LIST IsolatedCpuList; } SGI_PLATFORM_DESCRIPTOR; // Arm SGI/RD Product IDs diff --git a/Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.c b/Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.c index 2f72e7152ff3..80190120ff32 100644 --- a/Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.c +++ b/Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.c @@ -1,14 +1,17 @@ /** @file * -* Copyright (c) 2018, ARM Limited. All rights reserved. +* Copyright (c) 2018 - 2022, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ +#include + #include #include #include +#include #include VOID @@ -16,6 +19,127 @@ InitVirtioDevices ( VOID ); +/** + Search for a MPID in a list + + Performs a linear search for a specified MPID on the given linear + list of MPIDs. + + @param[in] MpidList Pointer to list. + @param[in] Count Number of the elements in the list. + @param[in] Mpid Target MPID. + + @retval TRUE MPID is present. + @retval FALSE MPID is not present. +**/ +STATIC +BOOLEAN +CheckIfMpidIsPresent ( + IN UINT64 *MpidList, + IN UINT64 Count, + IN UINT64 Mpid + ) +{ + UINT64 Idx; + + for (Idx = 0; Idx < Count; Idx++) { + if (MpidList[Idx] == Mpid) { + return TRUE; + } + } + + return FALSE; +} + +/** + Disables isolated CPUs in the MADT table + + Parse the IsolatedCpuInfo from the Hob list and updates the MADT table to [SAMI] Nit. updates -> update + disable cpu's which are not available on the platfrom. + + @param[in] AcpiHeader Points to the Madt table. + @param[in] HobData Points to the unusable cpuinfo in hoblist. +**/ +STATIC +VOID +UpdateMadtTable ( + IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader, + IN SGI_PLATFORM_DESCRIPTOR *HobData + ) +{ + UINT8 *StructureListHead; + UINT8 *StructureListTail; + EFI_ACPI_6_4_GIC_STRUCTURE *GicStructure; + BOOLEAN MpidPresent; + + if (HobData->IsolatedCpuList.Count == 0) { + return; + } + + StructureListHead = + ((UINT8 *)AcpiHeader) + + sizeof(EFI_ACPI_6_4_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER); + StructureListTail = (UINT8 *)AcpiHeader + AcpiHeader->Length; + + // Locate ACPI GICC structure in the MADT table. + while (StructureListHead < StructureListTail) { + if (StructureListHead[0] == EFI_ACPI_6_4_GIC) { [SAMI] This is definitely not the way to parse an ACPI table. Please dont do this. Also, why are you not using DynamicTables framework? It is designed to handle such cases. [/SAMI] + GicStructure = (EFI_ACPI_6_4_GIC_STRUCTURE *)StructureListHead; + // Disable the CPU if its MPID is present in the list. + MpidPresent = CheckIfMpidIsPresent( + HobData->IsolatedCpuList.Mpid, + HobData->IsolatedCpuList.Count, + GicStructure->MPIDR + ); + if (MpidPresent == TRUE) { + DEBUG (( + DEBUG_INFO, + "Disabling Core: %lu, MPID: 0x%llx in MADT\n", + GicStructure->AcpiProcessorUid, + GicStructure->MPIDR + )); + GicStructure->Flags = 0; + } + } + + // Second element in the structure component header is length + StructureListHead += StructureListHead[1]; + } +} + +/** + Callback to validate and/or update ACPI table. + + On finding a MADT table, disable the isolated CPUs in the MADT table. The + list of isolated CPUs are obtained from the HOB data. + + @param[in] AcpiHeader Target ACPI table. + + @retval TURE Table validated/updated successfully. + @retval FALSE Error in Table validation/updation. +**/ +STATIC +BOOLEAN +CheckAndUpdateAcpiTable ( + IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader + ) +{ + VOID *SystemIdHob; + SGI_PLATFORM_DESCRIPTOR *HobData; + + // This check updates the MADT table to disable isolated CPUs present on the + // platform. + if (AcpiHeader->Signature == EFI_ACPI_1_0_APIC_SIGNATURE) { [SAMI] Why EFI_ACPI_6_4_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE is not used here? + SystemIdHob = GetFirstGuidHob (&gArmSgiPlatformIdDescriptorGuid); + if (SystemIdHob != NULL) { + HobData = (SGI_PLATFORM_DESCRIPTOR *)GET_GUID_HOB_DATA (SystemIdHob); + UpdateMadtTable (AcpiHeader, HobData); + } + } + + return TRUE; +} + EFI_STATUS EFIAPI ArmSgiPkgEntryPoint ( @@ -25,7 +149,10 @@ ArmSgiPkgEntryPoint ( { EFI_STATUS Status; - Status = LocateAndInstallAcpiFromFv (&gArmSgiAcpiTablesGuid); + Status = LocateAndInstallAcpiFromFvConditional ( + &gArmSgiAcpiTablesGuid, + &CheckAndUpdateAcpiTable + ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Failed to install ACPI tables\n", __FUNCTION__)); return Status; diff --git a/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPeim.c b/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPeim.c index 7df52cc4fd7c..f778dc8ac7c1 100644 --- a/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPeim.c +++ b/Platform/ARM/SgiPkg/Library/SgiPlatformPei/SgiPlatformPeim.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2018, ARM Limited. All rights reserved. +* Copyright (c) 2018-2022, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * @@ -38,6 +38,8 @@ GetSgiSystemId ( CONST VOID *NtFwCfgDtBlob; SGI_NT_FW_CONFIG_INFO_PPI *NtFwConfigInfoPpi; EFI_STATUS Status; + UINT64 IsolatedCpuCount; + UINT64 CoreCount; Status = PeiServicesLocatePpi (&gNtFwConfigDtInfoPpiGuid, 0, NULL, (VOID**)&NtFwConfigInfoPpi); @@ -83,6 +85,32 @@ GetSgiSystemId ( HobData->MultiChipMode = fdt32_to_cpu (*Property); } + Property = fdt_getprop (NtFwCfgDtBlob, Offset, "isolated-cpu-list", NULL); + if (Property == NULL) { + DEBUG ((DEBUG_INFO, "%s property not found\n", "isolated-cpu-list")); + HobData->IsolatedCpuList.Count = 0; + } else { + CopyMem (&IsolatedCpuCount, Property, sizeof (IsolatedCpuCount)); + CoreCount = + FixedPcdGet32 (PcdChipCount) * + FixedPcdGet32 (PcdClusterCount) * + FixedPcdGet32 (PcdCoreCount); + if (IsolatedCpuCount > CoreCount) { + DEBUG (( + DEBUG_ERROR, + "IsolatedCpuCount(%u) is higher than CoreCount(%u)\n", + IsolatedCpuCount, + CoreCount + )); + return EFI_SUCCESS; [SAMI] Is the status code returned here correct? Should this be EFI_INVALID_PARAMETER? Also the function name GetSgiSystemId() seems to no longer reflect what the function does. Hace you considered renaming it. + } + CopyMem ( + &HobData->IsolatedCpuList, + Property, + sizeof(HobData->IsolatedCpuList) + (CoreCount * sizeof(UINT64)) [SAMI] Coding convention is not followed here and at other places. Can you fix, please? + ); + } + return EFI_SUCCESS; } @@ -104,11 +132,24 @@ SgiPlatformPeim ( { SGI_PLATFORM_DESCRIPTOR *HobData; EFI_STATUS Status; + UINT64 CoreCount; + UINTN HobSize; + CoreCount = + FixedPcdGet32 (PcdChipCount) * + FixedPcdGet32 (PcdClusterCount) * + FixedPcdGet32 (PcdCoreCount); + + // Additional size for SGI_ISOLATED_CPU_LIST. + // Size = (MPID register size in bytes * CoreCount) + + // sizeof(SGI_PLATFORM_DESCRIPTOR) + HobSize = + sizeof (SGI_PLATFORM_DESCRIPTOR) + + (CoreCount * sizeof(UINT64)); // Create platform descriptor HOB HobData = (SGI_PLATFORM_DESCRIPTOR *)BuildGuidHob ( &gArmSgiPlatformIdDescriptorGuid, - sizeof (SGI_PLATFORM_DESCRIPTOR)); + HobSize); // Get the system id from the platform specific nt_fw_config device tree if (HobData == NULL) { IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.