audk/ArmVirtPkg/Library/ArmVirtMonitorLib/ArmVirtMonitorLib.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

96 lines
2.2 KiB
C
Raw Normal View History

/** @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.<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
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));
}
}