ArmMonitorLib provides an abstraction for invoking monitor calls using a SMC or HVC conduit based on the value configured in the PCD PcdMonitorConduitHvc.
The monitor call conduit is fixed for a platform firmware in most scenarios. For a normal virtual machine guest firmware, the default conduit is HVC. However, for Arm CCA the Realm code must use SMC as the conduit. To have a common code base for Guest/Virtual firmware to be used by both normal VMs and Realm VMs, the firmware must dynamically detect the conduit to be used. Some VMMs like kvmtool setup the PSCI conduit to be used in the device tree it hands off to the firmware. Therefore, introduce an ArmVirt instance of ArmMontorLib that parses this device tree to read the PSCI conduit value and issues monitor calls using the appropriate conduit. Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> Cc: Leif Lindholm <quic_llind...@quicinc.com> Cc: Gerd Hoffmann <kra...@redhat.com> Signed-off-by: Sami Mujawar <sami.muja...@arm.com> --- ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.c | 119 ++++++++++++++++++++ ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.inf | 37 ++++++ 2 files changed, 156 insertions(+) diff --git a/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.c b/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.c new file mode 100644 index 0000000000000000000000000000000000000000..a13bec36b3537a2348e7883c29c5beb6e55dc64b --- /dev/null +++ b/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.c @@ -0,0 +1,119 @@ +/** @file + Arm Monitor Library. + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> + +#include <Library/ArmHvcLib.h> +#include <Library/ArmMonitorLib.h> +#include <Library/ArmSmcLib.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Protocol/FdtClient.h> + +/** + An enum representing the PSCI conduits for issuing monitor calls. +*/ +typedef enum PsciConduit { + PsciConduitHvc, // < HVC conduit + PsciConduitSmc, // < SMC conduit + PsciConduitMax +} PSCI_CONDUIT; + +/** + A variable that stores the PSCI conduit to be used. +*/ +STATIC PSCI_CONDUIT mArmPsciConduit = PsciConduitMax; + +/** Monitor call. + + An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued + depending on the conduit. The library constructor for ArmVirtMonitorLib + determines the conduit by parsing the Device Tree handed off by the VMM + and initialising mArmPsciConduit. + + @param [in,out] Args Arguments for the HVC/SMC. +**/ +VOID +EFIAPI +ArmMonitorCall ( + IN OUT ARM_MONITOR_ARGS *Args + ) +{ + switch (mArmPsciConduit) { + case PsciConduitHvc: + ArmCallHvc ((ARM_HVC_ARGS *)Args); + break; + case PsciConduitSmc: + ArmCallSmc ((ARM_SMC_ARGS *)Args); + break; + default: + ASSERT (0); + CpuDeadLoop (); + } +} + +/** Constructor for ArmVirtMonitorLib. + + The library constructor for ArmVirtMonitorLib determines the conduit + by parsing the Device Tree handed off by the VMM and initialising + mArmPsciConduit, which can then be used to select the appropriate + conduit for invoking the monitor call. + + @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS. + @retval RETURN_NOT_FOUND An entry for the PSCI conduit was not found in + the platform device tree. +**/ +RETURN_STATUS +EFIAPI +ArmVirtMonitorLibConstructor ( + VOID + ) +{ + RETURN_STATUS Status; + FDT_CLIENT_PROTOCOL *FdtClient; + CONST VOID *Prop; + + Status = gBS->LocateProtocol ( + &gFdtClientProtocolGuid, + NULL, + (VOID **)&FdtClient + ); + if (RETURN_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = FdtClient->FindCompatibleNodeProperty ( + FdtClient, + "arm,psci-0.2", + "method", + &Prop, + NULL + ); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (AsciiStrnCmp (Prop, "hvc", 3) == 0) { + mArmPsciConduit = PsciConduitHvc; + } else if (AsciiStrnCmp (Prop, "smc", 3) == 0) { + mArmPsciConduit = PsciConduitSmc; + } else { + DEBUG (( + DEBUG_ERROR, + "%a: Unknown PSCI method \"%a\"\n", + __func__, + Prop + )); + return RETURN_NOT_FOUND; + } + + return RETURN_SUCCESS; +} diff --git a/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.inf b/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..d90f92d5faff96de9cd0433c1de18b0168b42592 --- /dev/null +++ b/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.inf @@ -0,0 +1,37 @@ +## @file +# Arm Virt Monitor Library +# +# Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.29 + BASE_NAME = ArmVirtMonitorLib + FILE_GUID = 3E464134-890D-4C3F-A559-D0FE2803E332 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmMonitorLib|DXE_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = ArmVirtMonitorLibConstructor + +[Sources] + ArmVirtMonitorLib.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmHvcLib + ArmSmcLib + DebugLib + UefiBootServicesTableLib + +[Protocols] + gFdtClientProtocolGuid ## CONSUMES + +[Depex] + gFdtClientProtocolGuid + -- 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#117678): https://edk2.groups.io/g/devel/message/117678 Mute This Topic: https://groups.io/mt/105483416/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-