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 | |
parent | 5bea69123349ef3c02e5d8a49ceaae971975ba90 (diff) | |
download | edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.zip edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.tar.gz edk2-059676e4faef29ebe50549ed9cd80b6f68a0d556.tar.bz2 |
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>
-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 565b5c4..fa4f0ca 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 a8c3336..a1bafba 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 0000000..1c8b18d --- /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 0000000..e43ba21 --- /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 b8e9208..3c80f05 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;
}
|