/** @file
Arm Monitor Library that chooses the conduit based on the PSCI node in the
device tree provided by the VMM.
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
ArmVirtMonitorLibConstructor (
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));
}
}