Introduce ArmCcaLib library that implements helper functions to: - probe if the code is executing in a Realm context - configure the protection attribute in page tables for the memory regions shared with the host - get the IPA width of the Realm which was stored in the GUID HOB gArmCcaIpaWidthGuid.
Signed-off-by: Sami Mujawar <sami.muja...@arm.com> --- ArmVirtPkg/ArmVirtPkg.dec | 1 + ArmVirtPkg/Include/Library/ArmCcaLib.h | 114 ++++++++++++ ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c | 190 ++++++++++++++++++++ ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf | 34 ++++ 4 files changed, 339 insertions(+) diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec index c270d4a1ee268fb57a5338fd71487ed54699f496..c61ed9c492e97aa00ba9dbab1a5544354b6e7de7 100644 --- a/ArmVirtPkg/ArmVirtPkg.dec +++ b/ArmVirtPkg/ArmVirtPkg.dec @@ -27,6 +27,7 @@ [Includes.common] [LibraryClasses] ArmCcaInitPeiLib|Include/Library/ArmCcaInitPeiLib.h + ArmCcaLib|Include/Library/ArmCcaLib.h ArmCcaRsiLib|Include/Library/ArmCcaRsiLib.h ArmVirtMemInfoLib|Include/Library/ArmVirtMemInfoLib.h diff --git a/ArmVirtPkg/Include/Library/ArmCcaLib.h b/ArmVirtPkg/Include/Library/ArmCcaLib.h new file mode 100644 index 0000000000000000000000000000000000000000..a47e14b507f1bfd1feece636063eb2ba83357a5b --- /dev/null +++ b/ArmVirtPkg/Include/Library/ArmCcaLib.h @@ -0,0 +1,114 @@ +/** @file + Library that implements the Arm CCA helper functions. + + Copyright (c) 2022 - 2023, Arm Ltd. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + + - Rsi or RSI - Realm Service Interface + - IPA - Intermediate Physical Address + - RIPAS - Realm IPA state +**/ + +#ifndef ARM_CCA_LIB_ +#define ARM_CCA_LIB_ + +#include <Base.h> +#include <Uefi/UefiBaseType.h> + +/** + Check if running in a Realm. + + @retval TRUE The execution is within the context of a Realm. + @retval FALSE The execution is not within the context of a Realm. +**/ +BOOLEAN +EFIAPI +IsRealm ( + VOID + ); + +/** + Configure the protection attribute for the page tables + describing the memory region. + + The IPA space of a Realm is divided into two halves: + - Protected IPA space and + - Unprotected IPA space. + + Software in a Realm should treat the most significant bit of an + IPA as a protection attribute. + + A Protected IPA is an address in the lower half of a Realms IPA + space. The most significant bit of a Protected IPA is 0. + + An Unprotected IPA is an address in the upper half of a Realms + IPA space. The most significant bit of an Unprotected IPA is 1. + + Note: + - Configuring the memory region as Unprotected IPA enables the + Realm to share the memory region with the Host. + - This function updates the page table entries to reflect the + protection attribute. + - A separate call to transition the memory range using the Realm + Service Interface (RSI) RSI_IPA_STATE_SET command is additionally + required and is expected to be done outside this function. + + @param [in] BaseAddress Base address of the memory region. + @param [in] Length Length of the memory region. + @param [in] IpaWidth IPA width of the Realm. + @param [in] Share If TRUE, set the most significant + bit of the IPA to configure the memory + region as Unprotected IPA. + If FALSE, clear the most significant + bit of the IPA to configure the memory + region as Protected IPA. + + @retval RETURN_SUCCESS IPA protection attribute updated. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_UNSUPPORTED The request is not initiated in a + Realm. +**/ +RETURN_STATUS +EFIAPI +ArmCcaSetMemoryProtectAttribute ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 IpaWidth, + IN BOOLEAN Share + ); + +/** + Return the IPA width of the Realm. + + The IPA width of the Realm is used to configure the protection attribute + for memory regions, see ArmCcaSetMemoryProtectAttribute(). + + The IPA width of the Realm is present in the Realm config which is read + when the ArmCcaInitPeiLib library hook function ArmCcaInitialize () is + called in the PrePi phase. ArmCcaInitialize () stores the IPA width of + the Realm in a GUID HOB gArmCcaIpaWidthGuid. + + This function searches the GUID HOB gArmCcaIpaWidthGuid and returns the + IPA width value stored therein. + + Note: + - This function must only be called after ArmCcaInitialize () has setup + the GUID HOB gArmCcaIpaWidthGuid. + + @param [out] IpaWidth IPA width of the Realm. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_NOT_FOUND The GUID HOB gArmCcaIpaWidthGuid is not + found and could mean that this function + was called before ArmCcaInitialize () + has created and initialised the GUID + HOB gArmCcaIpaWidthGuid. +**/ +RETURN_STATUS +EFIAPI +GetIpaWidth ( + OUT UINT64 *IpaWidth + ); + +#endif // ARM_CCA_LIB_ diff --git a/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c new file mode 100644 index 0000000000000000000000000000000000000000..32cfcbcadea261d0fa616b0e0b75ede47bd0f747 --- /dev/null +++ b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c @@ -0,0 +1,190 @@ +/** @file + Library that implements the Arm CCA helper functions. + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Rsi or RSI - Realm Service Interface + - IPA - Intermediate Physical Address + - RIPAS - Realm IPA state +**/ +#include <Base.h> + +#include <Chipset/AArch64.h> +#include <Library/ArmCcaLib.h> +#include <Library/ArmCcaRsiLib.h> +#include <Library/ArmMmuLib.h> +#include <Library/BaseLib.h> + +#include <Uefi/UefiMultiPhase.h> +#include <Pi/PiBootMode.h> +#include <Pi/PiHob.h> +#include <Library/HobLib.h> + +/** + Check if running in a Realm. + + @retval TRUE The execution is within the context of a Realm. + @retval FALSE The execution is not within the context of a Realm. +**/ +BOOLEAN +EFIAPI +IsRealm ( + VOID + ) +{ + RETURN_STATUS Status; + UINT16 Major; + UINT16 Minor; + + if (ArmHasRme ()) { + Status = RsiGetVersion (&Major, &Minor); + if (!RETURN_ERROR (Status)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Configure the protection attribute for the page tables + describing the memory region. + + The IPA space of a Realm is divided into two halves: + - Protected IPA space and + - Unprotected IPA space. + + Software in a Realm should treat the most significant bit of an + IPA as a protection attribute. + + A Protected IPA is an address in the lower half of a Realms IPA + space. The most significant bit of a Protected IPA is 0. + + An Unprotected IPA is an address in the upper half of a Realms + IPA space. The most significant bit of an Unprotected IPA is 1. + + Note: + - Configuring the memory region as Unprotected IPA enables the + Realm to share the memory region with the Host. + - This function updates the page table entries to reflect the + protection attribute. + - A separate call to transition the memory range using the Realm + Service Interface (RSI) RSI_IPA_STATE_SET command is additionally + required and is expected to be done outside this function. + + @param [in] BaseAddress Base address of the memory region. + @param [in] Length Length of the memory region. + @param [in] IpaWidth IPA width of the Realm. + @param [in] Share If TRUE, set the most significant + bit of the IPA to configure the memory + region as Unprotected IPA. + If FALSE, clear the most significant + bit of the IPA to configure the memory + region as Protected IPA. + + @retval RETURN_SUCCESS IPA protection attribute updated. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_UNSUPPORTED The request is not initiated in a + Realm. +**/ +RETURN_STATUS +EFIAPI +ArmCcaSetMemoryProtectAttribute ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 IpaWidth, + IN BOOLEAN Share + ) +{ + UINT64 Val; + UINT64 Mask; + UINT64 ProtectionAttributeMask; + + if (!IsRealm ()) { + return RETURN_UNSUPPORTED; + } + + if (IpaWidth == 0) { + return RETURN_INVALID_PARAMETER; + } + + /* Software in a Realm should treat the most significant bit of an + IPA as a protection attribute. + */ + ProtectionAttributeMask = 1ULL << (IpaWidth - 1); + + if (Share) { + Val = ProtectionAttributeMask; + Mask = ~TT_ADDRESS_MASK_BLOCK_ENTRY; + } else { + Val = 0; + Mask = ~(TT_ADDRESS_MASK_BLOCK_ENTRY | ProtectionAttributeMask); + } + + return SetMemoryRegionAttribute ( + BaseAddress, + Length, + Val, + Mask + ); +} + +/** + Return the IPA width of the Realm. + + The IPA width of the Realm is used to configure the protection attribute + for memory regions, see ArmCcaSetMemoryProtectAttribute(). + + The IPA width of the Realm is present in the Realm config which is read + when the ArmCcaInitPeiLib library hook function ArmCcaInitialize () is + called in the PrePi phase. ArmCcaInitialize () stores the IPA width of + the Realm in a GUID HOB gArmCcaIpaWidthGuid. + + This function searches the GUID HOB gArmCcaIpaWidthGuid and returns the + IPA width value stored therein. + + Note: + - This function must only be called after ArmCcaInitialize () has setup + the GUID HOB gArmCcaIpaWidthGuid. + + @param [out] IpaWidth IPA width of the Realm. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_NOT_FOUND The GUID HOB gArmCcaIpaWidthGuid is not + found and could mean that this function + was called before ArmCcaInitialize () + has created and initialised the GUID + HOB gArmCcaIpaWidthGuid. +**/ +RETURN_STATUS +EFIAPI +GetIpaWidth ( + OUT UINT64 *IpaWidth + ) +{ + VOID *Hob; + UINT64 *CcaIpaWidth; + + if (IpaWidth == NULL) { + return RETURN_INVALID_PARAMETER; + } + + Hob = GetFirstGuidHob (&gArmCcaIpaWidthGuid); + if ((Hob == NULL) || + (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64))) + { + return RETURN_NOT_FOUND; + } + + CcaIpaWidth = GET_GUID_HOB_DATA (Hob); + if ((UINT64)*CcaIpaWidth == 0) { + return RETURN_NOT_FOUND; + } + + *IpaWidth = *CcaIpaWidth; + + return RETURN_SUCCESS; +} diff --git a/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..7d90b4535d69c12672af5de3d7cab63a3cd528a6 --- /dev/null +++ b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf @@ -0,0 +1,34 @@ +## @file +# Library that implements the Arm CCA helper functions. +# +# Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = ArmCcaLib + FILE_GUID = 11C18743-52F9-405E-B35B-D7BE91A26F9F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmCcaLib + +[Sources] + ArmCcaLib.c + +[Packages] + ArmPkg/ArmPkg.dec + ArmVirtPkg/ArmVirtPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmCcaRsiLib + ArmLib + ArmMmuLib + BaseLib + HobLib + +[Guids] + gArmCcaIpaWidthGuid -- 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103566): https://edk2.groups.io/g/devel/message/103566 Mute This Topic: https://groups.io/mt/98495975/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-