diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index 565b5c494f..fa4f0ca853 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -92,6 +92,8 @@ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf !endif + ArmMonitorLib|ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf + [LibraryClasses.AARCH64] ArmPlatformLib|ArmVirtPkg/Library/ArmPlatformLibQemu/ArmPlatformLibQemu.inf diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc index a8c3336eb8..a1bafbaba1 100644 --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc @@ -82,6 +82,8 @@ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf + ArmMonitorLib|ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf + [LibraryClasses.common.DXE_DRIVER] AcpiPlatformLib|OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf diff --git a/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c new file mode 100644 index 0000000000..1c8b18d5e5 --- /dev/null +++ b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c @@ -0,0 +1,95 @@ +/** @file + Arm Monitor Library that chooses the conduit based on the PSCI node in the + device tree provided by QEMU + + Copyright (c) 2022, Arm Limited. All rights reserved.
+ Copyright (c) 2024, Google LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +STATIC UINT32 mArmSmcccMethod; + +/** Library constructor. + + Assign the global variable mArmSmcccMethod based on the PSCI node in the + device tree. +**/ +RETURN_STATUS +EFIAPI +ArmVirtQemuMonitorLibConstructor ( + VOID + ) +{ + EFI_STATUS Status; + FDT_CLIENT_PROTOCOL *FdtClient; + CONST VOID *Prop; + + Status = gBS->LocateProtocol ( + &gFdtClientProtocolGuid, + NULL, + (VOID **)&FdtClient + ); + ASSERT_EFI_ERROR (Status); + + Status = FdtClient->FindCompatibleNodeProperty ( + FdtClient, + "arm,psci-0.2", + "method", + &Prop, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (AsciiStrnCmp (Prop, "hvc", 3) == 0) { + mArmSmcccMethod = 1; + } else if (AsciiStrnCmp (Prop, "smc", 3) == 0) { + mArmSmcccMethod = 2; + } else { + DEBUG (( + DEBUG_ERROR, + "%a: Unknown SMCCC method \"%a\"\n", + __func__, + Prop + )); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** Monitor call. + + An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued + depending on the default conduit. + + @param [in,out] Args Arguments for the HVC/SMC. +**/ +VOID +EFIAPI +ArmMonitorCall ( + IN OUT ARM_MONITOR_ARGS *Args + ) +{ + if (mArmSmcccMethod == 1) { + ArmCallHvc ((ARM_HVC_ARGS *)Args); + } else if (mArmSmcccMethod == 2) { + ArmCallSmc ((ARM_SMC_ARGS *)Args); + } else { + ASSERT ((mArmSmcccMethod == 1) || (mArmSmcccMethod == 2)); + } +} diff --git a/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf new file mode 100644 index 0000000000..e43ba215c2 --- /dev/null +++ b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf @@ -0,0 +1,39 @@ +## @file +# Arm Monitor Library that chooses the conduit based on the PSCI node in the +# device tree provided by QEMU +# +# Copyright (c) 2022, Arm Limited. All rights reserved.
+# Copyright (c) 2024, Google LLC. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.29 + BASE_NAME = ArmVirtQemuMonitorLib + FILE_GUID = 09f50ee5-2aa2-42b9-a2a0-090faeefed2b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmMonitorLib|DXE_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = ArmVirtQemuMonitorLibConstructor + +[Sources] + ArmVirtQemuMonitorLib.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmHvcLib + ArmSmcLib + BaseLib + DebugLib + UefiBootServicesTableLib + +[Protocols] + gFdtClientProtocolGuid ## CONSUMES + +[Depex] + gFdtClientProtocolGuid diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c index b8e9208301..3c80f05984 100644 --- a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -226,17 +226,5 @@ PlatformPeim ( BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize)); - #ifdef MDE_CPU_AARCH64 - // - // Set the SMCCC conduit to SMC if executing at EL2, which is typically the - // exception level that services HVCs rather than the one that invokes them. - // - if (ArmReadCurrentEL () == AARCH64_EL2) { - Status = PcdSetBoolS (PcdMonitorConduitHvc, FALSE); - ASSERT_EFI_ERROR (Status); - } - - #endif - return EFI_SUCCESS; }