diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2024-06-07 18:39:43 +0200 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-06-10 08:44:48 +0000 |
commit | 059676e4faef29ebe50549ed9cd80b6f68a0d556 (patch) | |
tree | a561a81417f7003148b27c049599602b9fc42f86 /ArmVirtPkg | |
parent | 5bea69123349ef3c02e5d8a49ceaae971975ba90 (diff) | |
download | edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.tar.gz edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.tar.bz2 edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.zip |
ArmVirtPkg/ArmVirtQemu: Implement ArmMonitorLib for QEMU specifically
Whether SMCCC calls use HVC or SMC generally depends on the exception
level that the firmware executes at, but also on whether or not EL2 is
implemented.
This is almost always known at build time, which is why the default
ArmMonitorLib used to model this as a feature PCD. However, on QEMU,
things are not that simple.
However, SMCCC specifies that the conduit is the same as the one used
for PSCI calls (which has been retrofitted into SMCCC when it was
defined). Given that QEMU provides this information via the device tree,
let's use it to select the conduit, using a special ArmMonitorLib
implementation.
This also removes the need to set the associated PCD at runtime, given
that its updated value will no longer be used.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'ArmVirtPkg')
-rw-r--r-- | ArmVirtPkg/ArmVirtQemu.dsc | 2 | ||||
-rw-r--r-- | ArmVirtPkg/ArmVirtQemuKernel.dsc | 2 | ||||
-rw-r--r-- | ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c | 95 | ||||
-rw-r--r-- | ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf | 39 | ||||
-rw-r--r-- | ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c | 12 |
5 files changed, 138 insertions, 12 deletions
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.<BR>
+ Copyright (c) 2024, Google LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmHvcLib.h>
+#include <Library/ArmMonitorLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+
+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.<BR>
+# Copyright (c) 2024, Google LLC. All rights reserved.<BR>
+#
+# 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;
}
|