diff --git a/ArmPkg/Include/Library/ArmMonitorLib.h b/ArmPkg/Include/Library/ArmMonitorLib.h index d6e13b61d6..1192ee2888 100644 --- a/ArmPkg/Include/Library/ArmMonitorLib.h +++ b/ArmPkg/Include/Library/ArmMonitorLib.h @@ -23,6 +23,18 @@ typedef struct { UINTN Arg5; UINTN Arg6; UINTN Arg7; + #ifdef MDE_CPU_AARCH64 + UINTN Arg8; + UINTN Arg9; + UINTN Arg10; + UINTN Arg11; + UINTN Arg12; + UINTN Arg13; + UINTN Arg14; + UINTN Arg15; + UINTN Arg16; + UINTN Arg17; + #endif } ARM_MONITOR_ARGS; /** Monitor call. diff --git a/ArmPkg/Library/ArmMonitorLib/AArch64/ArmMonitorLib.S b/ArmPkg/Library/ArmMonitorLib/AArch64/ArmMonitorLib.S new file mode 100644 index 0000000000..a99adf00ad --- /dev/null +++ b/ArmPkg/Library/ArmMonitorLib/AArch64/ArmMonitorLib.S @@ -0,0 +1,79 @@ +// +// Copyright (c) 2024, Google Llc. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +#include + +/** Monitor call. + + An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued + depending on the default conduit. PcdMonitorConduitHvc determines the type + of the call: if true, do an HVC. + + @param [in,out] Args Arguments for the HVC/SMC. +**/ +ASM_FUNC(ArmMonitorCall) + // Create a stack frame + stp x29, x30, [sp, #-16]! + mov x29, sp + + // Preserve X0 for later use + mov x30, x0 + + // Load the SMCCC arguments values into the appropriate registers + ldp x0, x1, [x30, #0] + ldp x2, x3, [x30, #16] + ldp x4, x5, [x30, #32] + ldp x6, x7, [x30, #48] + ldp x8, x9, [x30, #64] + ldp x10, x11, [x30, #80] + ldp x12, x13, [x30, #96] + ldp x14, x15, [x30, #112] + ldp x16, x17, [x30, #128] + +#if !defined(_PCD_VALUE_PcdMonitorConduitHvc) +#error +#elif _PCD_VALUE_PcdMonitorConduitHvc == 0 + smc #0 +#elif _PCD_VALUE_PcdMonitorConduitHvc == 1 + hvc #0 +#else +#error +#endif + + // A SMCCC SMC64/HVC64 call can return up to 18 values. + stp x0, x1, [x30, #0] + stp x2, x3, [x30, #16] + stp x4, x5, [x30, #32] + stp x6, x7, [x30, #48] + stp x8, x9, [x30, #64] + stp x10, x11, [x30, #80] + stp x12, x13, [x30, #96] + stp x14, x15, [x30, #112] + stp x16, x17, [x30, #128] + + // Clear return values from registers + mov x0, xzr + mov x1, xzr + mov x2, xzr + mov x3, xzr + mov x4, xzr + mov x5, xzr + mov x6, xzr + mov x7, xzr + mov x8, xzr + mov x9, xzr + mov x10, xzr + mov x11, xzr + mov x12, xzr + mov x13, xzr + mov x14, xzr + mov x15, xzr + mov x16, xzr + mov x17, xzr + + ldp x29, x30, [sp], #16 + ret diff --git a/ArmPkg/Library/ArmMonitorLib/Arm/ArmMonitorLib.S b/ArmPkg/Library/ArmMonitorLib/Arm/ArmMonitorLib.S new file mode 100644 index 0000000000..9029059cf4 --- /dev/null +++ b/ArmPkg/Library/ArmMonitorLib/Arm/ArmMonitorLib.S @@ -0,0 +1,49 @@ +// +// Copyright (c) 2024, Google Llc. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +#include + +/** Monitor call. + + An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued + depending on the default conduit. PcdMonitorConduitHvc determines the type + of the call: if true, do an HVC. + + @param [in,out] Args Arguments for the HVC/SMC. +**/ +ASM_FUNC(ArmMonitorCall) + push {r4-r7} + + // Preserve R0 for later use + mov ip, r0 + + // Load the SMCCC arguments values into the appropriate registers + ldm r0, {r0-r7} + +#if !defined(_PCD_VALUE_PcdMonitorConduitHvc) +#error +#elif _PCD_VALUE_PcdMonitorConduitHvc == 0 + .arch_extension sec + smc #0 +#elif _PCD_VALUE_PcdMonitorConduitHvc == 1 + .arch_extension virt + hvc #0 +#else +#error +#endif + + // A SMCCC SMC32/HVC32 call can return up to 8 values. + stm ip, {r0-r7} + + // Clear return values from registers + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + + pop {r4-r7} + bx lr diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c deleted file mode 100644 index 72f71296e5..0000000000 --- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c +++ /dev/null @@ -1,34 +0,0 @@ -/** @file - Arm Monitor Library. - - Copyright (c) 2022, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include - -/** Monitor call. - - An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued - depending on the default conduit. PcdMonitorConduitHvc determines the type - of the call: if true, do an HVC. - - @param [in,out] Args Arguments for the HVC/SMC. -**/ -VOID -EFIAPI -ArmMonitorCall ( - IN OUT ARM_MONITOR_ARGS *Args - ) -{ - if (FixedPcdGetBool (PcdMonitorConduitHvc)) { - ArmCallHvc ((ARM_HVC_ARGS *)Args); - } else { - ArmCallSmc ((ARM_SMC_ARGS *)Args); - } -} diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf index f504cb80f1..06fbab28b6 100644 --- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf +++ b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf @@ -14,16 +14,15 @@ VERSION_STRING = 1.0 LIBRARY_CLASS = ArmMonitorLib -[Sources] - ArmMonitorLib.c +[Sources.ARM] + Arm/ArmMonitorLib.S + +[Sources.AARCH64] + AArch64/ArmMonitorLib.S [Packages] ArmPkg/ArmPkg.dec MdePkg/MdePkg.dec -[LibraryClasses] - ArmHvcLib - ArmSmcLib - [Pcd] gArmTokenSpaceGuid.PcdMonitorConduitHvc