Merge changes from topic "qemu_tests"
* changes:
fix(test): compile error in test_irq_spurious_gicv2.c
feat(timer): support PPI timer interrupts
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..1946491
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "ext/mbedtls"]
+ path = ext/mbedtls
+ url = https://github.com/Mbed-TLS/mbedtls.git
diff --git a/Makefile b/Makefile
index e7efa2e..4936ff7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
#
-# Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# TFTF Version
VERSION_MAJOR := 2
-VERSION_MINOR := 11
+VERSION_MINOR := 12
MAKE_HELPERS_DIRECTORY := make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
@@ -134,8 +134,8 @@
# List of secure partitions present.
SECURE_PARTITIONS :=
-# Only platform fvp supports cactus_mm
-ifeq (${ARCH}-${PLAT},aarch64-fvp)
+# Only platform fvp and rdv3 supports cactus_mm
+ifeq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-rdv3))
include spm/cactus_mm/cactus_mm.mk
include realm/realm.mk
endif
@@ -432,7 +432,7 @@
@exit 1
endif
-ifneq (${ARCH}-${PLAT},aarch64-fvp)
+ifneq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-rdv3))
.PHONY: cactus_mm
cactus_mm:
@echo "ERROR: $@ is supported only on AArch64 FVP."
@@ -440,7 +440,7 @@
.PHONY: realm
realm:
- @echo "ERROR: $@ is supported only on AArch64 FVP."
+ @echo "ERROR: $@ is supported only on AArch64 FVP and RD-V3."
@exit 1
endif
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 89d9c10..0f22ded 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -7,6 +7,139 @@
Tests are not guaranteed to be compatible. This also means that a version
upgrade on the TF-A-Tests side might not necessarily introduce any new feature.
+Version 2.12
+------------
+
+New features
+^^^^^^^^^^^^
+
+- More tests are made available in this release to help validate the
+ functionalities in the following areas:
+
+ - FF-A
+ - Realm Management Extension
+ - EL3 Runtime
+ - New Platform ports
+
+TFTF
+^^^^
+
+- SPM/FF-A Testing:
+
+ - Added tests to attest SPMC handles GPF in memory sharing ABIs:
+
+ - FFA_MEM_RETRIEVE_REQ
+ - FFA_MEM_FRAG_RX/TX
+ - FFA_MEM_RELINQUISH
+
+ - Added tests using the SMC64 ABI version for the FF-A memory management
+ interfaces.
+ - Tests to attest the SPMC is doing the necessary context management
+ of SME registers.
+ - Check that SRI delay flag use from normal world results in an error.
+ - FF-A Setup and discovery interfaces:
+
+ - FFA_VERSION called restricted to be used until first FF-A call,
+ from a given endpoint is handled.
+ - FFA_FEATURES tests changed to cater for feature return based on
+ EL of the FF-A endpoint, and the security state it relates to.
+ - FFA_PARTITION_INFO_GET changed to report support of indirect
+ messaging.
+
+ - New tests
+
+ - Added AMU counter restriction (RAZ) test.
+ - Added test to validate EL1 and EL2 registers during context switch.
+ - Added PCIe DOE library and tests.
+ - Added tests for newly supported features FEAT_FGT2, LS64_ACCDATA,
+ FEAT_Debugv8p9.
+ - Added test for 64-byte load/store instructions introduced by LS64.
+ - Added asymmetric feature testing for FEAT_SPE, FEAT_TRBE, and FEAT_TCR2.
+ - Added a new test suite supported by EL3 SPMC.
+ - Added SDEI tests for attempting to bind too many events.
+ - Added test suite to exercise SIMD context management with Cactus SP
+ (supported by EL3 SPMC).
+
+- Platforms
+
+ - Corstone-1000:
+
+ - Updated test skip list.
+
+ - FVP:
+
+ - Added PCIe support.
+
+ - Neoverse-RD:
+
+ - Defined naming convention for CSS macros.
+ - Introduced flash and ROS macros.
+ - Introduced timer and watchdog macros.
+ - Refactored header files for first gen platforms.
+ - refactored header files for second gen platforms.
+ - Removed deprecated header files.
+
+ - Versal-2:
+
+ - Added support for AMD Versal Gen 2 platform.
+ - Added AMD Versal Gen 2 documentation.
+
+- Miscellaneous:
+
+ - Added skeleton for asymmetric feature testing capability.
+ - Added asymmetric tests to skip when features are not present on a core.
+ - Added test to ensure arch timer in NWd is honored across world switch.
+ - Added test to confirm errata 2938996/2726228 workaround by checking
+ trbe_el1 access.
+ - Fixed GICD_ITARGETSR assertion to relax check on unicore systems.
+ - Fixed expect to print file and line number on failure for easier debugging.
+ - Fixed TRBE extension test to skip on Cortex-A520 and Cortex-X4 due to errata.
+ - Refactored to register undef_injection_handler only during register accesses
+ for better control over exceptions.
+ - Fixed firmware handoff register convention value to match updated spec.
+ - Updated toolchain requirements.
+
+Realm Management Extension
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ - Set number of num_bps and num_wps.
+ - Updated rsi_ipa_state_get() function.
+ - Increased maximum number of RECs.
+ - Use random start REC.
+ - Added specific tests for FEAT_LPA2 on RMI tests.
+ - Added support for FEAT_LPA2 to the Realm Extension tests.
+ - Added test for rtt_fold unassigned.
+ - Added test for rtt_fold assigned.
+ - Unified SIMD test cases.
+ - Fixed pauth exception test.
+ - Fix(realm): cater for removal of SH from rtte.
+ - Fixed RMI and RSI definitions to match RMM Specification 1.0-rel0-rc1.
+ - Fixed RMI commands arguments descriptions.
+ - Fixed calculation of Realm's REC index.
+ - Fixed host_realm_init_ipa_state()'s retry path.
+ - Fixed realm initialisation code.
+ - Separated pool creation from Realm creation helpers.
+ - Fixed tests passing with TRP but not with RMM.
+
+Cactus (Secure-EL1 FF-A test partition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - Added support for Cactus SP to boot on EL3 SPMC.
+ - Added fix to skip computing linear core id.
+ - Fixed cactus_mm verbosity on some tests.
+
+Issues resolved since last release
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ - Added "build" directory dependency to ensure correct ordering
+ on slow systems.
+ - Fixed race condition in tests_list generation by using grouped target.
+ - Fixed virtual timer enablement by moving it to command handler.
+ - Fixed test case test_smccc_callee_preserved.
+ - Updated definitions for sysregs on older toolchains.
+ - Fixed undef_injection_handler to clarify it catches both undef injections
+ and EL2 register traps.
+
Version 2.11
------------
diff --git a/docs/getting_started/obtain.rst b/docs/getting_started/obtain.rst
index cffab2d..68b4072 100644
--- a/docs/getting_started/obtain.rst
+++ b/docs/getting_started/obtain.rst
@@ -5,7 +5,9 @@
::
- git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+ git clone --recursive https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+
+Note that TF-A-Tests will also fetch the MbedTLS repo as a git submodule.
--------------
diff --git a/docs/getting_started/requirements.rst b/docs/getting_started/requirements.rst
index 553975f..14e4458 100644
--- a/docs/getting_started/requirements.rst
+++ b/docs/getting_started/requirements.rst
@@ -16,6 +16,18 @@
distributions should also work fine, provided that the tools and libraries
can be installed.
+Dependencies
+------------
+
+This section lists the dependencies for TF-A-Tests which are added as
+as a git submodule.
+
+======================== =====================
+ Name Version
+======================== =====================
+Mbed TLS 3.6.2
+======================== =====================
+
Toolchain
---------
diff --git a/docs/porting/optional-mods.rst b/docs/porting/optional-mods.rst
index a88d682..7fc3813 100644
--- a/docs/porting/optional-mods.rst
+++ b/docs/porting/optional-mods.rst
@@ -50,6 +50,18 @@
generate a watchdog timeout interrupt. This interrupt remains deliberately
unserviced, which eventually asserts the reset signal.
+Function : plat_pcie_get_info_table()
+----------------------------
+
+::
+
+ Argument : void
+ Return : struct pcie_info_table *
+
+This function returns the pointer to `pcie_info_table` structure
+correponding to the platform. This needs to be implemented
+only if the platform want to run PCIe related tests.
+
--------------
*Copyright (c) 2019, Arm Limited. All rights reserved.*
diff --git a/ext/mbedtls b/ext/mbedtls
new file mode 160000
index 0000000..107ea89
--- /dev/null
+++ b/ext/mbedtls
@@ -0,0 +1 @@
+Subproject commit 107ea89daaefb9867ea9121002fbbdf926780e98
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 28b1d4e..124cc4e 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -88,6 +88,34 @@
} \
} while (0)
+#define SKIP_TEST_IF_SMCCC_VERSION_LT(major, minor) \
+ do { \
+ smc_args args = {0}; \
+ smc_ret_values ret; \
+ args.fid = SMCCC_VERSION; \
+ ret = tftf_smc(&args); \
+ if ((int32_t)ret.ret0 < MAKE_SMCCC_VERSION(major, minor)) { \
+ tftf_testcase_printf( \
+ "Unexpected SMCCC version: 0x%x\n", \
+ (int)ret.ret0); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (0)
+
+#define SKIP_TEST_IF_SMCCC_FUNC_NOT_SUPPORTED(func) \
+ do { \
+ smc_ret_values ret; \
+ smc_args args = {0}; \
+ args.fid = SMCCC_ARCH_FEATURES; \
+ args.arg1 = func; \
+ ret = tftf_smc(&args); \
+ if ((int)ret.ret0 == SMC_ARCH_CALL_NOT_SUPPORTED) { \
+ tftf_testcase_printf( \
+ #func " is not implemented\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (0)
+
#define SKIP_TEST_IF_DIT_NOT_SUPPORTED() \
do { \
if (!is_armv8_4_dit_present()) { \
@@ -212,7 +240,7 @@
#define SKIP_TEST_IF_TRBE_NOT_SUPPORTED() \
do { \
- if (!get_armv9_0_trbe_support()) { \
+ if (!is_feat_trbe_present()) { \
tftf_testcase_printf("ARMv9-TRBE not supported\n"); \
return TEST_RESULT_SKIPPED; \
} \
@@ -319,6 +347,38 @@
} \
} while (false)
+#define SKIP_TEST_IF_FPMR_NOT_SUPPORTED() \
+ do { \
+ if(!is_feat_fpmr_present()) { \
+ tftf_testcase_printf("FEAT_FPMR not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
+#define SKIP_TEST_IF_SCTLR2_NOT_SUPPORTED() \
+ do { \
+ if (!is_feat_sctlr2_supported()) { \
+ tftf_testcase_printf("FEAT_SCTLR2 not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
+#define SKIP_TEST_IF_THE_NOT_SUPPORTED() \
+ do { \
+ if (!is_feat_the_supported()) { \
+ tftf_testcase_printf("FEAT_THE not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
+#define SKIP_TEST_IF_D128_NOT_SUPPORTED() \
+ do { \
+ if (!is_feat_d128_supported()) { \
+ tftf_testcase_printf("FEAT_D128 not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
#define SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP() \
do { \
u_register_t retrmm = 0U; \
@@ -364,6 +424,13 @@
} \
} while (false)
+#define SKIP_TEST_IF_DOUBLE_FAULT2_NOT_SUPPORTED() \
+ do { \
+ if (is_feat_double_fault2_present() == false) { \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
/* Helper macro to verify if system suspend API is supported */
#define is_psci_sys_susp_supported() \
(tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND) \
diff --git a/include/configs/tftf_mbedtls_config.h b/include/configs/tftf_mbedtls_config.h
new file mode 100644
index 0000000..77e7ba9
--- /dev/null
+++ b/include/configs/tftf_mbedtls_config.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Based on migration guide[1]:
+ *
+ * config.h was split into build_info.h and mbedtls_config.h. In code, use
+ * #include <mbedtls/build_info.h>. Don't include mbedtls/config.h and don't
+ * refer to MBEDTLS_CONFIG_FILE. And also the guide recommends, if you have a
+ * custom configuration file don't define MBEDTLS_CONFIG_H anymore.
+ *
+ * [1] https://github.com/Mbed-TLS/mbedtls/blob/v3.6.0/docs/3.0-migration-guide.md
+ */
+
+#include <limits.h>
+/* This is needed for size_t */
+#include <stddef.h>
+/* For snprintf function declaration */
+#include <stdio.h>
+
+/* This file is compatible with release 3.6.2 */
+#define MBEDTLS_CONFIG_VERSION 0x03060200
+
+/* Configuration file to build mbed TLS with the required features for TFTF */
+#define MBEDTLS_PLATFORM_MEMORY
+
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+#define MBEDTLS_CIPHER_C
+
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_RESTARTABLE
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECP_WINDOW_SIZE (2U) /* Valid range = [2,7] */
+
+/*
+ * This is enabled in TFTF as PSA calls are made within the trust boundary.
+ * Disabling this option causes mbedtls to create a local copy of input buffer
+ * using buffer_alloc_calloc().
+ */
+#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+
+#define MBEDTLS_ERROR_C
+
+#define MBEDTLS_HKDF_C
+#define MBEDTLS_HMAC_DRBG_C
+
+#define MBEDTLS_MD_C
+
+#define MBEDTLS_PLATFORM_C
+
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA224_C
+#define MBEDTLS_SHA384_C
+#define MBEDTLS_SHA512_C
+
+#define MBEDTLS_VERSION_C
+
+/*
+ * Prevent the use of 128-bit division which
+ * creates dependency on external libraries.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+/* Memory buffer allocator option */
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8
+
+#define MBEDTLS_GENPRIME
+
+#define MBEDTLS_X509_CRL_PARSE_C
+#define MBEDTLS_X509_CSR_PARSE_C
+#define MBEDTLS_X509_CREATE_C
+#define MBEDTLS_X509_CSR_WRITE_C
+
+#define MBEDTLS_AES_C
+#define MBEDTLS_GCM_C
+
+#define MBEDTLS_CHACHA20_C
+#define MBEDTLS_POLY1305_C
+#define MBEDTLS_CHACHAPOLY_C
+
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_DHM_C
+
+#define MBEDTLS_PK_WRITE_C
+
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+#define MBEDTLS_OID_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_PKCS1_V21
+
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
diff --git a/include/lib/aarch32/arch_features.h b/include/lib/aarch32/arch_features.h
index 3c6a338..999f7ec 100644
--- a/include/lib/aarch32/arch_features.h
+++ b/include/lib/aarch32/arch_features.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -59,4 +59,11 @@
{
return 0;
}
+
+static inline unsigned int amu_get_version(void)
+{
+ return (unsigned int)(read_id_pfr0() >> ID_PFR0_AMU_SHIFT) &
+ ID_PFR0_AMU_MASK;
+}
+
#endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 50cb5f9..f0d1398 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -218,6 +218,12 @@
#define ID_AA64PFR0_CSV2_SUPPORTED ULL(0x1)
#define ID_AA64PFR0_CSV2_2_SUPPORTED ULL(0x2)
+/* ID_AA64DFR0_EL1.DoubleLock definitions */
+#define ID_AA64DFR0_DOUBLELOCK_SHIFT U(36)
+#define ID_AA64DFR0_DOUBLELOCK_MASK ULL(0xf)
+#define ID_AA64DFR0_DOUBLELOCK_WIDTH U(4)
+#define DOUBLELOCK_IMPLEMENTED ULL(0)
+
/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
#define ID_AA64DFR0_PMS_SHIFT U(32)
#define ID_AA64DFR0_PMS_LENGTH U(4)
@@ -260,6 +266,7 @@
/* ID_DFR0_EL1.Tracefilt definitions */
#define ID_AA64DFR0_TRACEFILT_SHIFT U(40)
#define ID_AA64DFR0_TRACEFILT_MASK U(0xf)
+#define ID_AA64DFR0_TRACEFILT_WIDTH U(4)
#define ID_AA64DFR0_TRACEFILT_SUPPORTED U(1)
/* ID_AA64DFR0_EL1.PMUVer definitions */
@@ -432,6 +439,11 @@
/* ID_AA64MMFR3_EL1 definitions */
#define ID_AA64MMFR3_EL1 S3_0_C0_C7_3
+#define ID_AA64MMFR3_EL1_D128_SHIFT U(32)
+#define ID_AA64MMFR3_EL1_D128_MASK ULL(0xf)
+#define ID_AA64MMFR3_EL1_D128_WIDTH U(4)
+#define ID_AA64MMFR3_EL1_D128_SUPPORTED ULL(0x1)
+
#define ID_AA64MMFR3_EL1_S2POE_SHIFT U(20)
#define ID_AA64MMFR3_EL1_S2POE_MASK ULL(0xf)
#define ID_AA64MMFR3_EL1_S2POE_WIDTH U(4)
@@ -452,12 +464,26 @@
#define ID_AA64MMFR3_EL1_S1PIE_WIDTH U(4)
#define ID_AA64MMFR3_EL1_S1PIE_SUPPORTED ULL(0x1)
+#define ID_AA64MMFR3_EL1_SCTLRX_SHIFT U(4)
+#define ID_AA64MMFR3_EL1_SCTLRX_MASK ULL(0xf)
+#define ID_AA64MMFR3_EL1_SCTLRX_WIDTH ULL(0x4)
+#define ID_AA64MMFR3_EL1_SCTLR2_SUPPORTED ULL(0x1)
+
#define ID_AA64MMFR3_EL1_TCRX_SHIFT U(0)
#define ID_AA64MMFR3_EL1_TCRX_MASK ULL(0xf)
#define ID_AA64MMFR3_EL1_TCRX_WIDTH U(4)
#define ID_AA64MMFR3_EL1_TCR2_SUPPORTED ULL(0x1)
/* ID_AA64PFR1_EL1 definitions */
+#define ID_AA64PFR1_EL1_DF2_SHIFT U(56)
+#define ID_AA64PFR1_EL1_DF2_WIDTH U(4)
+#define ID_AA64PFR1_EL1_DF2_MASK (0xf << ID_AA64PFR1_EL1_DF2_SHIFT)
+
+#define ID_AA64PFR1_EL1_THE_SHIFT U(48)
+#define ID_AA64PFR1_EL1_THE_MASK ULL(0xf)
+#define ID_AA64PFR1_EL1_THE_WIDTH U(4)
+#define ID_AA64PFR1_EL1_THE_SUPPORTED ULL(1)
+
#define ID_AA64PFR1_EL1_GCS_SHIFT U(44)
#define ID_AA64PFR1_EL1_GCS_MASK ULL(0xf)
#define ID_AA64PFR1_EL1_GCS_WIDTH U(4)
@@ -484,6 +510,7 @@
#define ID_AA64PFR1_MPAM_FRAC_SHIFT U(16)
#define ID_AA64PFR1_MPAM_FRAC_MASK ULL(0xf)
+#define ID_AA64PFR1_RAS_FRAC_MASK ULL(0xf)
#define ID_AA64PFR1_RAS_FRAC_SHIFT U(12)
#define ID_AA64PFR1_RAS_FRAC_MASK ULL(0xf)
#define ID_AA64PFR1_RAS_FRAC_WIDTH U(4)
@@ -504,6 +531,16 @@
#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf)
#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */
+#define ID_AA64PFR1_DF2_SHIFT U(56)
+#define ID_AA64PFR1_DF2_WIDTH ULL(0x4)
+
+/* ID_AA64PFR2_EL1 definitions */
+#define ID_AA64PFR2_EL1 S3_0_C0_C4_2
+#define ID_AA64PFR2_EL1_FPMR_SHIFT U(32)
+#define ID_AA64PFR2_EL1_FPMR_MASK ULL(0xf)
+#define ID_AA64PFR2_EL1_FPMR_WIDTH U(4)
+#define ID_AA64PFR2_EL1_FPMR_SUPPORTED ULL(0x1)
+
/* ID_PFR1_EL1 definitions */
#define ID_PFR1_VIRTEXT_SHIFT U(12)
#define ID_PFR1_VIRTEXT_MASK U(0xf)
@@ -553,6 +590,16 @@
#define SCTLR_DSSBS_BIT (ULL(1) << 44)
#define SCTLR_RESET_VAL SCTLR_EL3_RES1
+/* SCTLR2 register definitions */
+#define SCTLR2_EL2 S3_4_C1_C0_3
+#define SCTLR2_EL1 S3_0_C1_C0_3
+
+#define SCTLR2_NMEA_BIT (UL(1) << 2)
+#define SCTLR2_EnADERR_BIT (UL(1) << 3)
+#define SCTLR2_EnANERR_BIT (UL(1) << 4)
+#define SCTLR2_EASE_BIT (UL(1) << 5)
+#define SCTLR2_EnIDCP128_BIT (UL(1) << 6)
+
/* CPACR_El1 definitions */
#define CPACR_EL1_FPEN(x) ((x) << 20)
#define CPACR_EL1_FP_TRAP_EL0 U(0x1)
@@ -571,37 +618,110 @@
/* SCR definitions */
#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
-#define SCR_AMVOFFEN_BIT (UL(1) << 35)
-#define SCR_ATA_BIT (U(1) << 26)
-#define SCR_FIEN_BIT (U(1) << 21)
-#define SCR_API_BIT (U(1) << 17)
-#define SCR_APK_BIT (U(1) << 16)
-#define SCR_TWE_BIT (U(1) << 13)
-#define SCR_TWI_BIT (U(1) << 12)
-#define SCR_ST_BIT (U(1) << 11)
-#define SCR_RW_BIT (U(1) << 10)
-#define SCR_SIF_BIT (U(1) << 9)
-#define SCR_HCE_BIT (U(1) << 8)
-#define SCR_SMD_BIT (U(1) << 7)
-#define SCR_EA_BIT (U(1) << 3)
-#define SCR_FIQ_BIT (U(1) << 2)
-#define SCR_IRQ_BIT (U(1) << 1)
-#define SCR_NS_BIT (U(1) << 0)
+#define SCR_NSE_SHIFT U(62)
+#define SCR_FGTEN2_BIT (UL(1) << 59)
+#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT)
+#define SCR_EnIDCP128_BIT (UL(1) << 55)
+#define SCR_PFAREn_BIT (UL(1) << 53)
+#define SCR_TWERR_BIT (UL(1) << 52)
+#define SCR_TMEA_BIT (UL(1) << 51)
+#define SCR_EnFPM_BIT (UL(1) << 50)
+#define SCR_MECEn_BIT (UL(1) << 49)
+#define SCR_GPF_BIT (UL(1) << 48)
+#define SCR_D128En_BIT (UL(1) << 47)
+#define SCR_AIEn_BIT (UL(1) << 46)
+#define SCR_TWEDEL_SHIFT U(30)
+#define SCR_TWEDEL_MASK ULL(0xf)
+#define SCR_PIEN_BIT (UL(1) << 45)
+#define SCR_SCTLR2En_BIT (UL(1) << 44)
+#define SCR_TCR2EN_BIT (UL(1) << 43)
+#define SCR_RCWMASKEn_BIT (UL(1) << 42)
+#define SCR_ENTP2_SHIFT U(41)
+#define SCR_TRNDR_BIT (UL(1) << 40)
+#define SCR_GCSEn_BIT (UL(1) << 39)
+#define SCR_HXEn_BIT (UL(1) << 38)
+#define SCR_ADEn_BIT (UL(1) << 37)
+#define SCR_EnAS0_BIT (UL(1) << 36)
+#define SCR_ENTP2_BIT (UL(1) << SCR_ENTP2_SHIFT)
+#define SCR_AMVOFFEN_SHIFT U(35)
+#define SCR_AMVOFFEN_BIT (UL(1) << SCR_AMVOFFEN_SHIFT)
+#define SCR_TME_BIT (UL(1) << 34)
+#define SCR_TWEDEn_BIT (UL(1) << 29)
+#define SCR_ECVEN_BIT (UL(1) << 28)
+#define SCR_FGTEN_BIT (UL(1) << 27)
+#define SCR_ATA_BIT (UL(1) << 26)
+#define SCR_EnSCXT_BIT (UL(1) << 25)
+#define SCR_FIEN_BIT (UL(1) << 21)
+#define SCR_NMEA_BIT (UL(1) << 20)
+#define SCR_EASE_BIT (UL(1) << 19)
+#define SCR_EEL2_BIT (UL(1) << 18)
+#define SCR_API_BIT (UL(1) << 17)
+#define SCR_APK_BIT (UL(1) << 16)
+#define SCR_TERR_BIT (UL(1) << 15)
+#define SCR_TLOR_BIT (UL(1) << 14)
+#define SCR_TWE_BIT (UL(1) << 13)
+#define SCR_TWI_BIT (UL(1) << 12)
+#define SCR_ST_BIT (UL(1) << 11)
+#define SCR_RW_BIT (UL(1) << 10)
+#define SCR_SIF_BIT (UL(1) << 9)
+#define SCR_HCE_BIT (UL(1) << 8)
+#define SCR_SMD_BIT (UL(1) << 7)
+#define SCR_EA_BIT (UL(1) << 3)
+#define SCR_FIQ_BIT (UL(1) << 2)
+#define SCR_IRQ_BIT (UL(1) << 1)
+#define SCR_NS_BIT (UL(1) << 0)
+#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
#define SCR_VALID_BIT_MASK U(0x2f8f)
#define SCR_RESET_VAL SCR_RES1_BITS
/* MDCR_EL3 definitions */
+#define MDCR_EnSTEPOP_BIT (ULL(1) << 50)
+#define MDCR_ETBAD(x) ((x) << 48)
+#define MDCR_EnITE_BIT (ULL(1) << 47)
+#define MDCR_EPMSSAD(x) (ULL(x) << 45)
+#define MDCR_EnPMSS_BIT (ULL(1) << 44)
+#define MDCR_EBWE_BIT (ULL(1) << 43)
+#define MDCR_EnPMS3_BIT (ULL(1) << 42)
+#define MDCR_PMEE(x) ((x) << 40)
+#define MDCR_EnTB2_BIT (ULL(1) << 39)
+#define MDCR_E3BREC_BIT (ULL(1) << 38)
+#define MDCR_E3BREW_BIT (ULL(1) << 37)
+#define MDCR_EnPMSN_BIT (ULL(1) << 36)
+#define MDCR_MPMX_BIT (ULL(1) << 35)
+#define MDCR_MCCD_BIT (ULL(1) << 34)
+#define MDCR_SBRBE_SHIFT U(32)
+#define MDCR_SBRBE_MASK ULL(0x3)
+#define MDCR_SBRBE(x) (ULL(x) << MDCR_SBRBE_SHIFT)
+#define MDCR_PMSSE(x) ((x) << 30)
+#define MDCR_NSTBE_BIT (ULL(1) << 26)
+#define MDCR_NSTB(x) ((x) << 24)
+#define MDCR_NSTB_EL1 ULL(0x3)
+#define MDCR_NSTBE_BIT (ULL(1) << 26)
+#define MDCR_MTPME_BIT (ULL(1) << 28)
+#define MDCR_TDCC_BIT (ULL(1) << 27)
+#define MDCR_SCCD_BIT (ULL(1) << 23)
+#define MDCR_ETAD_BIT (ULL(1) << 22)
+#define MDCR_EPMAD_BIT (ULL(1) << 21)
+#define MDCR_EDAD_BIT (ULL(1) << 20)
+#define MDCR_TTRF_BIT (ULL(1) << 19)
+#define MDCR_STE_BIT (ULL(1) << 18)
+#define MDCR_SPME_BIT (ULL(1) << 17)
+#define MDCR_SDD_BIT (ULL(1) << 16)
#define MDCR_SPD32(x) ((x) << 14)
#define MDCR_SPD32_LEGACY ULL(0x0)
#define MDCR_SPD32_DISABLE ULL(0x2)
#define MDCR_SPD32_ENABLE ULL(0x3)
-#define MDCR_SDD_BIT (ULL(1) << 16)
#define MDCR_NSPB(x) ((x) << 12)
#define MDCR_NSPB_EL1 ULL(0x3)
+#define MDCR_NSPBE_BIT (ULL(1) << 11)
#define MDCR_TDOSA_BIT (ULL(1) << 10)
#define MDCR_TDA_BIT (ULL(1) << 9)
+#define MDCR_EnPM2_BIT (ULL(1) << 7)
#define MDCR_TPM_BIT (ULL(1) << 6)
-#define MDCR_SCCD_BIT (ULL(1) << 23)
+#define MDCR_EDADE_BIT (ULL(1) << 4)
+#define MDCR_ETADE_BIT (ULL(1) << 3)
+#define MDCR_EPMADE_BIT (ULL(1) << 2)
+#define MDCR_RLTE_BIT (ULL(1) << 0)
#define MDCR_EL3_RESET_VAL ULL(0x0)
/* MDCR_EL2 definitions */
@@ -667,6 +787,14 @@
#define EVNTI_SHIFT U(4)
#define EVNTI_MASK U(0xf)
+/* CPTR_EL3 definitions */
+#define CPTR_EL3_TCPAC_BIT (ULL(1) << 31)
+#define CPTR_EL3_TAM_BIT (ULL(1) << 30)
+#define CPTR_EL3_TTA_BIT (ULL(1) << 20)
+#define CPTR_EL3_ESM_BIT (ULL(1) << 12)
+#define CPTR_EL3_TFP_BIT (ULL(1) << 10)
+#define CPTR_EL3_EZ_BIT (ULL(1) << 8)
+
/* CPTR_EL2 definitions */
#define CPTR_EL2_RES1 ((ULL(1) << 13) | (ULL(1) << 9) | (ULL(0xff)))
#define CPTR_EL2_TCPAC_BIT (ULL(1) << 31)
@@ -1245,6 +1373,7 @@
/* MPAM register definitions */
#define MPAM3_EL3_MPAMEN_BIT (ULL(1) << 63)
+#define MPAM3_EL3_TRAPLOWER_BIT (ULL(1) << 62)
#define MPAMHCR_EL2_TRAP_MPAMIDR_EL1 (ULL(1) << 31)
#define MPAM2_EL2_TRAPMPAM0EL1 (ULL(1) << 49)
@@ -1391,6 +1520,12 @@
******************************************************************************/
#define MDSELR_EL1 S2_0_C0_C4_2
+/******************************************************************************
+ * Armv8.9 - Translation Hardening Extension Registers
+ ******************************************************************************/
+#define RCWMASK_EL1 S3_0_C13_C0_6
+#define RCWSMASK_EL1 S3_0_C13_C0_3
+
/*******************************************************************************
* Armv9.0 - Trace Buffer Extension System Registers
******************************************************************************/
@@ -1526,6 +1661,24 @@
#define POR_EL1 S3_0_C10_C2_4
#define S2POR_EL1 S3_0_C10_C2_5
+/* Perm value encoding for S2POR_EL1 */
+#define PERM_LABEL_NO_ACCESS U(0)
+#define PERM_LABEL_RESERVED_1 U(1)
+#define PERM_LABEL_MRO U(2)
+#define PERM_LABEL_MRO_TL1 U(3)
+#define PERM_LABEL_WO U(4)
+#define PERM_LABEL_RESERVED_5 U(5)
+#define PERM_LABEL_MRO_TL0 U(6)
+#define PERM_LABEL_MRO_TL01 U(7)
+#define PERM_LABEL_RO U(8)
+#define PERM_LABEL_RO_uX U(9)
+#define PERM_LABEL_RO_pX U(10)
+#define PERM_LABEL_RO_upX U(11)
+#define PERM_LABEL_RW U(12)
+#define PERM_LABEL_RW_uX U(13)
+#define PERM_LABEL_RW_pX U(14)
+#define PERM_LABEL_RW_upX U(15)
+
/*******************************************************************************
* FEAT_GCS - Guarded Control Stack Registers
******************************************************************************/
@@ -1543,4 +1696,9 @@
#define SCXTNUM_EL1 S3_0_C13_C0_7
#define SCXTNUM_EL0 S3_3_C13_C0_7
+/*******************************************************************************
+ * Floating Point Mode Register definitions
+ ******************************************************************************/
+#define FPMR S3_3_C4_C4_2
+
#endif /* ARCH_H */
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index c7d824a..cee8dd2 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -120,12 +120,6 @@
(read_id_aa64isar2_el1() & mask_id_aa64isar2)) != 0U;
}
-static inline bool is_armv8_4_amuv1_present(void)
-{
- return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
- ID_AA64PFR0_AMU_MASK) == 1U;
-}
-
static inline bool is_armv8_4_dit_present(void)
{
return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) &
@@ -186,13 +180,6 @@
ID_AA64DFR0_DEBUG_SHIFT);
}
-static inline bool get_armv9_0_trbe_support(void)
-{
- return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT) &
- ID_AA64DFR0_TRACEBUFFER_MASK) ==
- ID_AA64DFR0_TRACEBUFFER_SUPPORTED;
-}
-
static inline bool get_armv8_4_trf_support(void)
{
return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT) &
@@ -233,7 +220,7 @@
static inline bool get_feat_brbe_support(void)
{
return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_BRBE_SHIFT) &
- ID_AA64DFR0_BRBE_MASK) ==
+ ID_AA64DFR0_BRBE_MASK) >=
ID_AA64DFR0_BRBE_SUPPORTED;
}
@@ -474,6 +461,22 @@
ID_AA64ISAR1_LS64_MASK);
}
+static inline unsigned int amu_get_version(void)
+{
+ return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
+ ID_AA64PFR0_AMU_MASK;
+}
+
+static inline bool is_feat_amuv1_present(void)
+{
+ return amu_get_version() >= ID_AA64PFR0_AMU_V1;
+}
+
+static inline bool is_feat_amuv1p1_present(void)
+{
+ return amu_get_version() >= ID_AA64PFR0_AMU_V1P1;
+}
+
static inline bool is_feat_trbe_present(void)
{
return EXTRACT(ID_AA64DFR0_TRACEBUFFER, read_id_aa64dfr0_el1())
@@ -525,4 +528,40 @@
return EXTRACT(ID_AA64PFR1_EL1_MTE, read_id_aa64pfr1_el1())
>= MTE_IMPLEMENTED_ELX;
}
+
+static inline bool is_feat_double_fault2_present(void)
+{
+ return (EXTRACT(ID_AA64PFR1_EL1_DF2,
+ read_id_aa64pfr1_el1()) == 1UL);
+}
+
+static inline bool is_feat_fpmr_present(void)
+{
+ return EXTRACT(ID_AA64PFR2_EL1_FPMR, read_id_aa64pfr2_el1())
+ == ID_AA64PFR2_EL1_FPMR_SUPPORTED;
+}
+
+static inline bool is_feat_sctlr2_supported(void)
+{
+ return (((read_id_aa64mmfr3_el1() >> ID_AA64MMFR3_EL1_SCTLRX_SHIFT) &
+ ID_AA64MMFR3_EL1_SCTLRX_MASK) == ID_AA64MMFR3_EL1_SCTLR2_SUPPORTED);
+}
+
+static inline bool is_feat_the_supported(void)
+{
+ return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_THE_SHIFT) &
+ ID_AA64PFR1_EL1_THE_MASK) == ID_AA64PFR1_EL1_THE_SUPPORTED);
+}
+
+static inline bool is_feat_d128_supported(void)
+{
+ return (((read_id_aa64mmfr3_el1() >> ID_AA64MMFR3_EL1_D128_SHIFT) &
+ ID_AA64MMFR3_EL1_D128_MASK) == ID_AA64MMFR3_EL1_D128_SUPPORTED);
+}
+
+static inline bool is_feat_doublelock_present(void)
+{
+ return EXTRACT(ID_AA64DFR0_DOUBLELOCK, read_id_aa64dfr0_el1())
+ >= DOUBLELOCK_IMPLEMENTED;
+}
#endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index c906181..35d2454 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -190,6 +190,7 @@
DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(id_aa64pfr2_el1, ID_AA64PFR2_EL1)
DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
DEFINE_SYSREG_READ_FUNC(id_pfr0_el1)
@@ -322,6 +323,9 @@
DEFINE_SYSREG_RW_FUNCS(sctlr_el2)
DEFINE_SYSREG_RW_FUNCS(sctlr_el3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2)
+
DEFINE_SYSREG_RW_FUNCS(actlr_el1)
DEFINE_SYSREG_RW_FUNCS(actlr_el2)
DEFINE_SYSREG_RW_FUNCS(actlr_el3)
@@ -645,6 +649,10 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(pir_el2, PIR_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(s2pir_el2, S2PIR_EL2)
+/* Armv8.9 Translation Hardening Extension */
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwmask_el1, RCWMASK_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwsmask_el1, RCWSMASK_EL1)
+
/* Armv9.4 Guarded Control Stack Extension */
DEFINE_RENAME_SYSREG_RW_FUNCS(gcscr_el2, GCSCR_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el2, GCSPR_EL2)
@@ -675,6 +683,9 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(fpcr, FPCR)
DEFINE_RENAME_SYSREG_RW_FUNCS(fpsr, FPSR)
+/* Floating point Mode Register */
+DEFINE_RENAME_SYSREG_RW_FUNCS(fpmr, FPMR)
+
/* ID_AA64ISAR2_EL1 */
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
diff --git a/include/lib/aarch64/serror.h b/include/lib/aarch64/serror.h
index ac25f87..e6aa64f 100644
--- a/include/lib/aarch64/serror.h
+++ b/include/lib/aarch64/serror.h
@@ -7,8 +7,8 @@
#ifndef __SERROR_H__
#define __SERROR_H__
-typedef bool (*exception_handler_t)(void);
-void register_custom_serror_handler(exception_handler_t handler);
+typedef bool (*serr_exception_handler_t)(bool *incr_elr_elx);
+void register_custom_serror_handler(serr_exception_handler_t handler);
void unregister_custom_serror_handler(void);
#endif /* __SERROR_H__ */
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index 3ce053d..838e4b9 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -61,8 +61,6 @@
CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask);
-unsigned int amu_get_version(void);
-
uint64_t amu_group0_cnt_read(unsigned int idx);
#if __aarch64__
uint64_t amu_group0_voffset_read(unsigned int idx);
diff --git a/include/lib/extensions/sysreg128.h b/include/lib/extensions/sysreg128.h
new file mode 100644
index 0000000..5be2ffc
--- /dev/null
+++ b/include/lib/extensions/sysreg128.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SYSREG128_H
+#define SYSREG128_H
+
+#include <stdint.h>
+
+#ifdef __aarch64__
+
+/* Assembly function prototypes. */
+uint128_t read128_par_el1(void);
+uint128_t read128_ttbr0_el1(void);
+uint128_t read128_ttbr1_el1(void);
+uint128_t read128_ttbr0_el2(void);
+uint128_t read128_ttbr1_el2(void);
+uint128_t read128_vttbr_el2(void);
+uint128_t read128_rcwmask_el1(void);
+uint128_t read128_rcwsmask_el1(void);
+
+void write128_par_el1(uint128_t v);
+void write128_ttbr0_el1(uint128_t v);
+void write128_ttbr1_el1(uint128_t v);
+void write128_ttbr0_el2(uint128_t v);
+void write128_ttbr1_el2(uint128_t v);
+void write128_vttbr_el2(uint128_t v);
+void write128_rcwmask_el1(uint128_t v);
+void write128_rcwsmask_el1(uint128_t v);
+
+#endif /* __aarch64__ */
+
+#endif /* SYSREG128_H */
diff --git a/include/lib/pcie/pcie.h b/include/lib/pcie/pcie.h
index aa3911f..65e0202 100644
--- a/include/lib/pcie/pcie.h
+++ b/include/lib/pcie/pcie.h
@@ -11,6 +11,9 @@
#include <stdint.h>
#include <utils_def.h>
+/* platforms need to ensure that number of entries is less that this value */
+#define MAX_PCIE_INFO_ENTRIES 5
+
typedef struct {
unsigned long ecam_base; /* ECAM base address */
unsigned int segment_num; /* Segment number of this ECAM */
@@ -18,10 +21,10 @@
unsigned int end_bus_num; /* Last bus number */
} pcie_info_block_t;
-typedef struct {
+struct pcie_info_table{
unsigned int num_entries; /* Number of entries */
- pcie_info_block_t block[];
-} pcie_info_table_t;
+ pcie_info_block_t block[MAX_PCIE_INFO_ENTRIES];
+};
typedef struct {
uint32_t bdf;
@@ -96,6 +99,7 @@
#define CC_SUB_SHIFT 16
#define CC_BASE_SHIFT 24
+void pcie_init(void);
void pcie_create_info_table(void);
pcie_device_bdf_table_t *pcie_get_bdf_table(void);
uint32_t pcie_find_capability(uint32_t bdf, uint32_t cid_type, uint32_t cid,
diff --git a/include/lib/pcie/pcie_doe.h b/include/lib/pcie/pcie_doe.h
index 4e12afd..bac0dbf 100644
--- a/include/lib/pcie/pcie_doe.h
+++ b/include/lib/pcie/pcie_doe.h
@@ -8,6 +8,11 @@
#ifndef PCIE_DOE_H
#define PCIE_DOE_H
+#include <stdbool.h>
+#include <stddef.h>
+#include <pcie.h>
+#include <test_helpers.h>
+
/* DOE Extended Capability */
#define DOE_CAP_ID 0x002E
@@ -86,10 +91,45 @@
uint8_t next_index;
} pcie_doe_disc_resp_t;
+/* Skip test if DA is not supported in RMI features */
+#define CHECK_DA_SUPPORT_IN_RMI(_reg0) \
+ do { \
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP(); \
+ /* Get feature register0 */ \
+ if (host_rmi_features(0UL, &_reg0) != REALM_SUCCESS) { \
+ ERROR("Failed to get RMI feat_reg0\n"); \
+ return TEST_RESULT_FAIL; \
+ } \
+ \
+ /* DA not supported in RMI features? */ \
+ if ((_reg0 & RMI_FEATURE_REGISTER_0_DA_EN) == 0UL) { \
+ WARN("DA not in RMI features, skipping\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
+#define SKIP_TEST_IF_DOE_NOT_SUPPORTED(_bdf, _doe_cap_base) \
+ do { \
+ /* Test PCIe DOE only for RME */ \
+ if (!get_armv9_2_feat_rme_support()) { \
+ tftf_testcase_printf("FEAT_RME not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ \
+ pcie_init(); \
+ if (pcie_find_doe_device(&(_bdf), &(_doe_cap_base)) != 0) { \
+ tftf_testcase_printf("PCIe DOE not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
void print_doe_disc(pcie_doe_disc_resp_t *data);
int pcie_doe_send_req(uint32_t header, uint32_t bdf, uint32_t doe_cap_base,
uint32_t *req_addr, uint32_t req_len);
int pcie_doe_recv_resp(uint32_t bdf, uint32_t doe_cap_base,
uint32_t *resp_addr, uint32_t *resp_len);
+int pcie_doe_communicate(uint32_t header, uint32_t bdf, uint32_t doe_cap_base, void *req_buf,
+ size_t req_sz, void *rsp_buf, size_t *rsp_sz);
+int pcie_find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr);
#endif /* PCIE_DOE_H */
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 36e2e0f..c65b061 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -140,48 +140,109 @@
void waitms(uint64_t ms);
void waitus(uint64_t us);
+/* Define fields in common for smc_args and smc_args_ext */
+#define FID_COMMON_ARGS() \
+ /* \
+ * Function identifier. Identifies which function is being \
+ * invoked. \
+ */ \
+ uint32_t fid; \
+ \
+ u_register_t arg1; \
+ u_register_t arg2; \
+ u_register_t arg3; \
+ u_register_t arg4; \
+ u_register_t arg5; \
+ u_register_t arg6; \
+ u_register_t arg7;
+
+/* Define fields in common for smc_ret_values and smc_ret_values_ext */
+#define COMMON_RETVALS() \
+ u_register_t ret0; \
+ u_register_t ret1; \
+ u_register_t ret2; \
+ u_register_t ret3; \
+ u_register_t ret4; \
+ u_register_t ret5; \
+ u_register_t ret6; \
+ u_register_t ret7;
+
+
/*
- * SMC calls take a function identifier and up to 7 arguments.
+ * SMC calls take a function identifier and up to 7 arguments if using x8
+ * as an address pointing to a structure where return values are stored.
* Additionally, few SMC calls that originate from EL2 leverage the seventh
* argument explicitly. Given that TFTF runs in EL2, we need to be able to
* specify it.
*/
typedef struct {
- /* Function identifier. Identifies which function is being invoked. */
- uint32_t fid;
-
- u_register_t arg1;
- u_register_t arg2;
- u_register_t arg3;
- u_register_t arg4;
- u_register_t arg5;
- u_register_t arg6;
- u_register_t arg7;
+ FID_COMMON_ARGS()
} smc_args;
-/* SMC calls can return up to 8 register values */
+/*
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls take up to 17 arguments.
+ */
typedef struct {
- u_register_t ret0;
- u_register_t ret1;
- u_register_t ret2;
- u_register_t ret3;
- u_register_t ret4;
- u_register_t ret5;
- u_register_t ret6;
- u_register_t ret7;
+ FID_COMMON_ARGS()
+ u_register_t arg8;
+ u_register_t arg9;
+ u_register_t arg10;
+ u_register_t arg11;
+ u_register_t arg12;
+ u_register_t arg13;
+ u_register_t arg14;
+ u_register_t arg15;
+ u_register_t arg16;
+ u_register_t arg17;
+} smc_args_ext;
+
+/*
+ * SMC calls can return up to 8 register values if x8 is used as an address
+ * pointing to a structure where the return values are stored.
+ */
+typedef struct {
+ COMMON_RETVALS()
} smc_ret_values;
/*
- * Trigger an SMC call.
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls return up to 18 register values.
+ */
+typedef struct {
+ COMMON_RETVALS()
+ u_register_t ret8;
+ u_register_t ret9;
+ u_register_t ret10;
+ u_register_t ret11;
+ u_register_t ret12;
+ u_register_t ret13;
+ u_register_t ret14;
+ u_register_t ret15;
+ u_register_t ret16;
+ u_register_t ret17;
+} smc_ret_values_ext;
+
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by address
+ * stored in x8.
*/
smc_ret_values tftf_smc(const smc_args *args);
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by 'ret'
+ */
+void tftf_smc_no_retval_x8(const smc_args_ext *args, smc_ret_values_ext *ret);
+
/* Assembler routine to trigger a SMC call. */
smc_ret_values asm_tftf_smc64(uint32_t fid, u_register_t arg1, u_register_t arg2,
u_register_t arg3, u_register_t arg4,
u_register_t arg5, u_register_t arg6,
u_register_t arg7);
+/* Assembler routine to trigger a SMC call without smc_ret_values in x8. */
+u_register_t asm_tftf_smc64_no_retval_x8(const smc_args_ext *args,
+ smc_ret_values_ext *ret);
/*
* Update the SVE hint for the current CPU. Any SMC call made through tftf_smc
* will update the SVE hint bit in the SMC Function ID.
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index c8b785c..1a51823 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -193,4 +193,12 @@
return platform_get_core_pos(read_mpidr_el1() & MPID_MASK);
}
+/* Forward declaration */
+struct pcie_info_table;
+
+/*
+ * Retrieve platform PCIe information.
+ */
+const struct pcie_info_table *plat_pcie_get_info_table(void);
+
#endif /* __PLATFORM_H__ */
diff --git a/include/runtime_services/arm_arch_svc.h b/include/runtime_services/arm_arch_svc.h
index 0d2eb38..0b4e2ad 100644
--- a/include/runtime_services/arm_arch_svc.h
+++ b/include/runtime_services/arm_arch_svc.h
@@ -13,5 +13,6 @@
#define SMCCC_ARCH_WORKAROUND_1 0x80008000
#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
#define SMCCC_ARCH_WORKAROUND_3 0x80003FFF
+#define SMCCC_ARCH_FEATURE_AVAILABILITY U(0x80000003)
#endif /* __ARM_ARCH_SVC_H__ */
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 4dc3f53..0a63e96 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -357,8 +357,8 @@
*/
struct ffa_partition_rxtx_header {
uint32_t flags;
- /* MBZ */
- uint32_t reserved;
+ /* Reserved (SBZ). */
+ uint32_t reserved_1;
/* Offset from the beginning of the buffer to the message payload. */
uint32_t offset;
/* Sender(Bits[31:16]) and Receiver(Bits[15:0]) endpoint IDs. */
@@ -366,6 +366,10 @@
ffa_id_t sender;
/* Size of message in buffer. */
uint32_t size;
+ /* Reserved (SBZ). Added in v1.2 */
+ uint32_t reserved_2;
+ /* UUID identifying the communication protocol. Added in v1.2. */
+ struct ffa_uuid uuid;
};
#define FFA_RXTX_HEADER_SIZE sizeof(struct ffa_partition_rxtx_header)
@@ -375,11 +379,13 @@
struct ffa_partition_rxtx_header *header)
{
header->flags = 0;
- header->reserved = 0;
+ header->reserved_1 = 0;
header->offset = FFA_RXTX_HEADER_SIZE;
header->sender = sender;
header->receiver = receiver;
header->size = size;
+ header->reserved_2 = 0;
+ header->uuid = (struct ffa_uuid){0};
}
/* The maximum length possible for a single message. */
diff --git a/include/runtime_services/host_realm_managment/host_crypto_utils.h b/include/runtime_services/host_realm_managment/host_crypto_utils.h
new file mode 100644
index 0000000..2f865c0
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_crypto_utils.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HOST_CRYPTO_UTILS_H
+#define HOST_CRYPTO_UTILS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256 0x10
+#define PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384 0x20
+#define PUBLIC_KEY_ALGO_RSASSA_3072 0x30
+
+int host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+ size_t cert_chain_len,
+ void *public_key,
+ size_t *public_key_len,
+ void *public_key_metadata,
+ size_t *public_key_metadata_len,
+ uint8_t *public_key_algo);
+
+#endif /* HOST_CRYPTO_UTILS_H */
diff --git a/include/runtime_services/host_realm_managment/host_realm_helper.h b/include/runtime_services/host_realm_managment/host_realm_helper.h
index 168bb0a..6909a4e 100644
--- a/include/runtime_services/host_realm_managment/host_realm_helper.h
+++ b/include/runtime_services/host_realm_managment/host_realm_helper.h
@@ -18,7 +18,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
/*
* Creates realm, initializes heap, creates RTTs and also
@@ -29,7 +30,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
/*
* Creates realm, initializes heap, creates RTTs,
@@ -40,7 +42,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
bool host_destroy_realm(struct realm *realm_ptr);
void host_rec_send_sgi(struct realm *realm_ptr,
unsigned int sgi, unsigned int rec_num);
diff --git a/include/runtime_services/host_realm_managment/host_realm_mem_layout.h b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
index 7458146..1bef986 100644
--- a/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
+++ b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
@@ -41,8 +41,8 @@
#ifdef ENABLE_REALM_PAYLOAD_TESTS
/* 1MB for shared buffer between Realm and Host */
#define NS_REALM_SHARED_MEM_SIZE U(0x100000)
- /* 8MB of memory used as a pool for realm's objects creation */
- #define PAGE_POOL_MAX_SIZE U(0x800000)
+ /* 10MB of memory used as a pool for realm's objects creation */
+ #define PAGE_POOL_MAX_SIZE U(0xA00000)
#else
#define NS_REALM_SHARED_MEM_SIZE U(0x0)
#define PAGE_POOL_MAX_SIZE U(0x0)
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 484deeb..00435b0 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -18,6 +18,12 @@
#define RMI_FNUM_MIN_VALUE U(0x150)
#define RMI_FNUM_MAX_VALUE U(0x18F)
+/*
+ * Defines member of structure and reserves space
+ * for the next member with specified offset.
+ */
+#define SET_MEMBER_RMI SET_MEMBER
+
/* Get RMI fastcall std FID from offset */
#define SMC64_RMI_FID(_offset) \
((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
@@ -92,6 +98,11 @@
#define RMI_DATA_DESTROY SMC64_RMI_FID(U(0x5))
/*
+ * FID: 0xC4000156
+ */
+#define SMC_RMI_PDEV_AUX_COUNT SMC64_RMI_FID(U(0x6))
+
+/*
* arg0 == RD address
*/
#define RMI_REALM_ACTIVATE SMC64_RMI_FID(U(0x7))
@@ -135,6 +146,30 @@
/*
* arg0 == RD address
+ * arg1 == RTT address
+ * arg2 == map address
+ * arg3 == level
+ * arg4 == RTT tree index
+ *
+ * ret0 == status/index
+ */
+#define RMI_RTT_AUX_CREATE SMC64_RMI_FID(U(0x2D))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address (PA) of the RTT, if ret0 == RMI_SUCCESS
+ * Otherwise, undefined.
+ * ret2 == Top of the non-live address region. Only valid
+ * if ret0 == RMI_SUCCESS or ret0 == (RMI_ERROR_RTT_WALK, x)
+ */
+#define RMI_RTT_AUX_DESTROY SMC64_RMI_FID(U(0x2E))
+
+/*
+ * arg0 == RD address
* arg1 == map address
* arg2 == level
*
@@ -156,6 +191,31 @@
/*
* arg0 == RD address
* arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ * ret4 == ripas
+ */
+#define RMI_RTT_AUX_MAP_PROTECTED SMC64_RMI_FID(U(0x30))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ */
+#define RMI_RTT_AUX_MAP_UNPROTECTED SMC64_RMI_FID(U(0x31))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
* arg2 == level
*
* ret1 == level
@@ -174,6 +234,40 @@
#define RMI_RTT_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x12))
/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_PROTECTED SMC64_RMI_FID(U(0x33))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x34))
+
+/*
+ * arg0 == RD address
+ * arg1 == target rec
+ * arg2 == base adr
+ * arg3 == top adr
+ *
+ * ret0 == return code
+ * ret1 == Top IPA of range whose S2AP was modified
+ * ret2 == Index of RTT tree in which base alignment check failed
+ */
+#define RMI_RTT_SET_S2AP SMC64_RMI_FID(U(0x3B))
+
+/*
* arg0 == calling rec address
* arg1 == target rec address
*/
@@ -195,6 +289,16 @@
/*
* arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address(PA) of the RTT folded, if ret0 == RMI_SUCCESS
+ */
+#define RMI_RTT_AUX_FOLD SMC64_RMI_FID(U(0x2F))
+
+/*
+ * arg0 == RD address
*/
#define RMI_REC_AUX_COUNT SMC64_RMI_FID(U(0x17))
@@ -219,6 +323,156 @@
*/
#define RMI_RTT_SET_RIPAS SMC64_RMI_FID(U(0x19))
+/*
+ * FID: 0xC4000170
+ */
+#define SMC_RMI_GRANULE_DEV_DELEGATE SMC64_RMI_FID(U(0x20))
+
+/*
+ * FID: 0xC4000171
+ */
+#define SMC_RMI_GRANULE_DEV_UNDELEGATE SMC64_RMI_FID(U(0x21))
+
+/*
+ * FID: 0xC4000172
+ */
+#define SMC_RMI_DEV_MAP SMC64_RMI_FID(U(0x22))
+
+/*
+ * FID: 0xC4000173
+ */
+#define SMC_RMI_DEV_UNMAP SMC64_RMI_FID(U(0x23))
+
+/*
+ * FID: 0xC4000174
+ */
+#define SMC_RMI_PDEV_ABORT SMC64_RMI_FID(U(0x24))
+
+/*
+ * FID: 0xC4000175
+ */
+#define SMC_RMI_PDEV_COMMUNICATE SMC64_RMI_FID(U(0x25))
+
+/*
+ * FID: 0xC4000176
+ */
+#define SMC_RMI_PDEV_CREATE SMC64_RMI_FID(U(0x26))
+
+/*
+ * FID: 0xC4000177
+ */
+#define SMC_RMI_PDEV_DESTROY SMC64_RMI_FID(U(0x27))
+
+/*
+ * FID: 0xC4000178
+ */
+#define SMC_RMI_PDEV_GET_STATE SMC64_RMI_FID(U(0x28))
+
+/*
+ * FID: 0xC4000179
+ */
+#define SMC_RMI_PDEV_IDE_RESET SMC64_RMI_FID(U(0x29))
+
+/*
+ * FID: 0xC400017A
+ */
+#define SMC_RMI_PDEV_NOTIFY SMC64_RMI_FID(U(0x2A))
+
+/*
+ * FID: 0xC400017B
+ */
+#define SMC_RMI_PDEV_SET_PUBKEY SMC64_RMI_FID(U(0x2B))
+
+/*
+ * FID: 0xC400017C
+ */
+#define SMC_RMI_PDEV_STOP SMC64_RMI_FID(U(0x2C))
+
+/*
+ * FID: 0xC400017D
+ */
+#define SMC_RMI_RTT_AUX_CREATE SMC64_RMI_FID(U(0x2D))
+
+/*
+ * FID: 0xC400017E
+ */
+#define SMC_RMI_RTT_AUX_DESTROY SMC64_RMI_FID(U(0x2E))
+
+/*
+ * FID: 0xC400017F
+ */
+#define SMC_RMI_RTT_AUX_FOLD SMC64_RMI_FID(U(0x2F))
+
+/*
+ * FID: 0xC4000180
+ */
+#define SMC_RMI_RTT_AUX_MAP_PROTECTED SMC64_RMI_FID(U(0x30))
+
+/*
+ * FID: 0xC4000181
+ */
+#define SMC_RMI_RTT_AUX_MAP_UNPROTECTED SMC64_RMI_FID(U(0x31))
+
+/*
+ * FID: 0xC4000183
+ */
+#define SMC_RMI_RTT_AUX_UNMAP_PROTECTED SMC64_RMI_FID(U(0x33))
+
+/*
+ * FID: 0xC4000184
+ */
+#define SMC_RMI_RTT_AUX_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x34))
+
+/*
+ * FID: 0xC4000185
+ */
+#define SMC_RMI_VDEV_ABORT SMC64_RMI_FID(U(0x35))
+
+/*
+ * FID: 0xC4000186
+ */
+#define SMC_RMI_VDEV_COMMUNICATE SMC64_RMI_FID(U(0x36))
+
+/*
+ * FID: 0xC4000187
+ */
+#define SMC_RMI_VDEV_CREATE SMC64_RMI_FID(U(0x37))
+
+/*
+ * FID: 0xC4000188
+ */
+#define SMC_RMI_VDEV_DESTROY SMC64_RMI_FID(U(0x38))
+
+/*
+ * FID: 0xC4000189
+ */
+#define SMC_RMI_VDEV_GET_STATE SMC64_RMI_FID(U(0x39))
+
+/*
+ * FID: 0xC400018A
+ */
+#define SMC_RMI_VDEV_STOP SMC64_RMI_FID(U(0x3A))
+
+/*
+ * FID: 0xC400018B
+ */
+#define SMC_RMI_RTT_SET_S2AP SMC64_RMI_FID(U(0x3B))
+
+/*
+ * FID: 0xC400018C
+ */
+#define SMC_RMI_MEC_SET_SHARED SMC64_RMI_FID(U(0x3C))
+
+/*
+ * FID: 0xC400018D
+ */
+#define SMC_RMI_MEC_SET_PRIVATE SMC64_RMI_FID(U(0x3D))
+
+/*
+ * FID: 0xC400018E
+ */
+#define SMC_RMI_VDEV_COMPLETE SMC64_RMI_FID(U(0x3E))
+
#define GRANULE_SIZE PAGE_SIZE_4KB
/* Maximum number of auxiliary granules required for a REC */
@@ -237,10 +491,14 @@
#define RMI_FEATURE_FALSE 0U
#define RMI_FEATURE_TRUE 1U
-/* RmiRealmFlags format */
-#define RMI_REALM_FLAGS_LPA2 BIT(0)
-#define RMI_REALM_FLAGS_SVE BIT(1)
-#define RMI_REALM_FLAGS_PMU BIT(2)
+/* RmiRealmFlags0 format */
+#define RMI_REALM_FLAGS0_LPA2 BIT(0)
+#define RMI_REALM_FLAGS0_SVE BIT(1)
+#define RMI_REALM_FLAGS0_PMU BIT(2)
+#define RMI_REALM_FLAGS0_DA BIT(3)
+
+/* RmiRealmFlags1 format */
+#define RMI_REALM_FLAGS1_RTT_TREE_PP BIT(0)
/* RmiInterfaceVersion type */
#define RMI_MAJOR_VERSION 0U
@@ -265,7 +523,11 @@
#define RMI_EXIT_RIPAS_CHANGE 4U
#define RMI_EXIT_HOST_CALL 5U
#define RMI_EXIT_SERROR 6U
-#define RMI_EXIT_INVALID (RMI_EXIT_SERROR + 1U)
+#define RMI_EXIT_IO 7U
+#define RMI_EXIT_RTT_REQUEST 8U
+#define RMI_EXIT_S2AP_CHANGE 9U
+#define RMI_EXIT_VDEV_REQUEST 10U
+#define RMI_EXIT_INVALID (RMI_EXIT_VDEV_REQUEST + 1U)
/* RmiRecRunnable types */
#define RMI_NOT_RUNNABLE 0U
@@ -305,20 +567,34 @@
#define RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS_WIDTH 4UL
#define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER_SHIFT 38UL
#define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER_WIDTH 4UL
+#define RMI_FEATURE_REGISTER_0_DA_EN BIT(42)
/*
* Format of feature_flag[63:32].
* Value -1 (0 in case of NUM_BPS and NUM_WPS) indicates not set field,
* and parameter will be set from the corresponding field of feature register 0.
*/
-#define FEATURE_SVE_VL_SHIFT 32UL
-#define FEATURE_SVE_VL_WIDTH 8UL
-#define FEATURE_NUM_BPS_SHIFT 40UL
-#define FEATURE_NUM_BPS_WIDTH 8UL
-#define FEATURE_NUM_WPS_SHIFT 48UL
-#define FEATURE_NUM_WPS_WIDTH 8UL
-#define FEATURE_PMU_NUM_CTRS_SHIFT 56UL
-#define FEATURE_PMU_NUM_CTRS_WIDTH 8UL
+#define RMI_FEATURE_REGISTER_0_DA BIT(42)
+
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_SHIFT 43UL
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_WIDTH 2UL
+
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_SHIFT 45UL
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_WIDTH 4UL
+
+#define FEATURE_SVE_VL_SHIFT 56UL
+#define FEATURE_SVE_VL_WIDTH 4UL
+#define FEATURE_NUM_BPS_SHIFT 14UL
+#define FEATURE_NUM_BPS_WIDTH 6UL
+#define FEATURE_NUM_WPS_SHIFT 20UL
+#define FEATURE_NUM_WPS_WIDTH 6UL
+#define FEATURE_PMU_NUM_CTRS_SHIFT 35UL
+#define FEATURE_PMU_NUM_CTRS_WIDTH 4UL
+
+/* Possible values for RmiPlaneRttFeature */
+#define RMI_PLANE_RTT_AUX 0UL
+#define RMI_PLANE_RTT_AUX_SINGLE 1UL
+#define RMI_PLANE_RTT_SINGLE 2UL
/* RmiStatusCode types */
/*
@@ -358,6 +634,18 @@
* index: RTT level at which the walk terminated
*/
RMI_ERROR_RTT = 4,
+ /*
+ * An attribute of a device does not match the expected value
+ */
+ RMI_ERROR_DEVICE = 5,
+ /*
+ * The command is not supported
+ */
+ RMI_ERROR_NOT_SUPPORTED = 6,
+ /*
+ * RTTE in an auxiliary RTT contained an unexpected value
+ */
+ RMI_ERROR_RTT_AUX = 7,
RMI_ERROR_COUNT
} status_t;
@@ -398,31 +686,41 @@
*/
struct rmi_realm_params {
/* Flags */
- SET_MEMBER(unsigned long flags, 0, 0x8); /* Offset 0 */
+ SET_MEMBER(unsigned long flags0, 0, 0x8); /* Offset 0 */
/* Requested IPA width */
- SET_MEMBER(unsigned int s2sz, 0x8, 0x10); /* 0x8 */
+ SET_MEMBER(unsigned int s2sz, 0x8, 0x10); /* 0x8 */
/* Requested SVE vector length */
- SET_MEMBER(unsigned int sve_vl, 0x10, 0x18); /* 0x10 */
+ SET_MEMBER(unsigned int sve_vl, 0x10, 0x18); /* 0x10 */
/* Requested number of breakpoints */
- SET_MEMBER(unsigned int num_bps, 0x18, 0x20); /* 0x18 */
+ SET_MEMBER(unsigned int num_bps, 0x18, 0x20); /* 0x18 */
/* Requested number of watchpoints */
- SET_MEMBER(unsigned int num_wps, 0x20, 0x28); /* 0x20 */
+ SET_MEMBER(unsigned int num_wps, 0x20, 0x28); /* 0x20 */
/* Requested number of PMU counters */
- SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30); /* 0x28 */
+ SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30); /* 0x28 */
/* Measurement algorithm */
- SET_MEMBER(unsigned char hash_algo, 0x30, 0x400); /* 0x30 */
+ SET_MEMBER(unsigned char algorithm, 0x30, 0x38); /* 0x30 */
+ /* Number of auxiliary Planes */
+ SET_MEMBER(unsigned int num_aux_planes, 0x38, 0x400); /* 0x38 */
/* Realm Personalization Value */
- SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800); /* 0x400 */
+ SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800); /* 0x400 */
SET_MEMBER(struct {
- /* Virtual Machine Identifier */
- unsigned short vmid; /* 0x800 */
- /* Realm Translation Table base */
- u_register_t rtt_base; /* 0x808 */
- /* RTT starting level */
- long rtt_level_start; /* 0x810 */
- /* Number of starting level RTTs */
- unsigned int rtt_num_start; /* 0x818 */
- }, 0x800, 0x1000);
+ /* Virtual Machine Identifier */
+ unsigned short vmid; /* 0x800 */
+ /* Realm Translation Table base */
+ unsigned long rtt_base; /* 0x808 */
+ /* RTT starting level */
+ long rtt_level_start; /* 0x810 */
+ /* Number of starting level RTTs */
+ unsigned int rtt_num_start; /* 0x818 */
+ }, 0x800, 0x820);
+ /* Flags */
+ SET_MEMBER(unsigned long flags1, 0x820, 0x828); /* 0x820 */
+ /* MECID */
+ SET_MEMBER(long mecid, 0x828, 0xF00); /* 0x828 */
+ /* Auxiliary Virtual Machine Identifiers */
+ SET_MEMBER(unsigned short aux_vmid[3], 0xF00, 0xF80); /* 0xF00 */
+ /* Base address of auxiliary RTTs */
+ SET_MEMBER(unsigned long aux_rtt_base[3], 0xF80, 0x1000); /* 0xF80 */
};
/*
@@ -537,6 +835,249 @@
SET_MEMBER(struct rmi_rec_exit exit, 0x800, 0x1000); /* 0x800 */
};
+/*
+ * RmiPdevProtConfig
+ * Represents the protection between system and device.
+ * Width: 2 bits
+ */
+#define RMI_PDEV_IOCOH_E2E_IDE U(0)
+#define RMI_PDEV_IOCOH_E2E_SYS U(1)
+#define RMI_PDEV_FCOH_E2E_IDE U(2)
+#define RMI_PDEV_FCOH_E2E_SYS U(3)
+
+/*
+ * RmiPdevFlags
+ * Fieldset contains flags provided by the Host during PDEV creation
+ * Width: 64 bits
+ */
+/* RmiPdevProtConfig Bits 1:0 */
+#define RMI_PDEV_FLAGS_PROT_CONFIG_SHIFT UL(0)
+#define RMI_PDEV_FLAGS_PROT_CONFIG_WIDTH UL(2)
+
+/*
+ * RmiPdevEvent
+ * Represents physical device event.
+ * Width: 8 bits
+ */
+#define RMI_PDEV_EVENT_IDE_KEY_REFRESH U(0)
+
+/*
+ * RmiPdevState
+ * Represents the state of a PDEV
+ * Width: 8 bits
+ */
+#define RMI_PDEV_STATE_NEW U(0)
+#define RMI_PDEV_STATE_NEEDS_KEY U(1)
+#define RMI_PDEV_STATE_HAS_KEY U(2)
+#define RMI_PDEV_STATE_READY U(3)
+#define RMI_PDEV_STATE_COMMUNICATING U(4)
+#define RMI_PDEV_STATE_STOPPING U(5)
+#define RMI_PDEV_STATE_STOPPED U(6)
+#define RMI_PDEV_STATE_ERROR U(7)
+
+/*
+ * RmiSignatureAlgorithm
+ * Represents signature algorithm used in PDEV set key RMI call.
+ * Width: 8 bits
+ */
+#define RMI_SIGNATURE_ALGORITHM_RSASSA_3072 U(0)
+#define RMI_SIGNATURE_ALGORITHM_ECDSA_P256 U(1)
+#define RMI_SIGNATURE_ALGORITHM_ECDSA_P384 U(2)
+
+/*
+ * RmiDevMemShared
+ * Represents whether device memory Granule should be shared
+ * Width: 1 bit
+ */
+#define RMI_DEV_MEM_PRIVATE U(0)
+#define RMI_DEV_MEM_SHARED U(1)
+
+/*
+ * RmiDevDelegateFlags
+ * Fieldset contains flags provided by the Host during device memory granule
+ * delegation.
+ * Width: 64 bits
+ */
+/* RmiDevMemShared: Bit 0 */
+#define RMI_DEV_DELEGATE_FLAGS_SHARE_SHIFT U(0)
+#define RMI_DEV_DELEGATE_FLAGS_SHARE_WIDTH U(1)
+
+/*
+ * RmiDevCommEnterStatus (Name in Spec RmiDevCommStatus)
+ * Represents status passed from the Host to the RMM during device communication.
+ * Width: 8 bits
+ */
+#define RMI_DEV_COMM_ENTER_STATUS_SUCCESS U(0)
+#define RMI_DEV_COMM_ENTER_STATUS_ERROR U(1)
+#define RMI_DEV_COMM_ENTER_STATUS_NONE U(2)
+
+/*
+ * RmiDevCommEnter
+ * This structure contains data passed from the Host to the RMM during device
+ * communication.
+ * Width: 256 (0x100) bytes
+ */
+struct rmi_dev_comm_enter {
+ /* RmiDevCommEnterStatus: Status of device transaction */
+ SET_MEMBER_RMI(unsigned char status, 0, 0x8);
+ /* Address: Address of request buffer */
+ SET_MEMBER_RMI(unsigned long req_addr, 0x8, 0x10);
+ /* Address: Address of response buffer */
+ SET_MEMBER_RMI(unsigned long resp_addr, 0x10, 0x18);
+ /* UInt64: Amount of valid data in response buffer in bytes */
+ SET_MEMBER_RMI(unsigned long resp_len, 0x18, 0x100);
+};
+
+/*
+ * RmiDevCommExitFlags
+ * Fieldset contains flags provided by the RMM during a device transaction.
+ * Width: 64 bits
+ */
+#define RMI_DEV_COMM_EXIT_FLAGS_CACHE_SHIFT UL(0)
+#define RMI_DEV_COMM_EXIT_FLAGS_CACHE_WIDTH UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_SEND_SHIFT UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_SEND_WIDTH UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_WAIT_SHIFT UL(2)
+#define RMI_DEV_COMM_EXIT_FLAGS_WAIT_WIDTH UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_MULTI_SHIFT UL(3)
+#define RMI_DEV_COMM_EXIT_FLAGS_MULTI_WIDTH UL(1)
+
+/*
+ * RmiDevCommProtocol
+ * Represents the protocol used for device communication.
+ * Width: 8 bits
+ */
+#define RMI_DEV_COMM_PROTOCOL_SPDM U(0)
+#define RMI_DEV_COMM_PROTOCOL_SECURE_SPDM U(1)
+
+/*
+ * RmiDevCommExit
+ * This structure contains data passed from the RMM to the Host during device
+ * communication.
+ * Width: 256 (0x100) bytes.
+ */
+struct rmi_dev_comm_exit {
+ /*
+ * RmiDevCommExitFlags: Flags indicating the actions the host is
+ * requested to perform
+ */
+ SET_MEMBER_RMI(unsigned long flags, 0, 0x8);
+ /*
+ * UInt64: If flags.cache is true, offset in the device response buffer
+ * to the start of data to be cached in bytes.
+ */
+ SET_MEMBER_RMI(unsigned long cache_offset, 0x8, 0x10);
+ /*
+ * UInt64: If flags.cache is true, amount of data to be cached in
+ * bytes.
+ */
+ SET_MEMBER_RMI(unsigned long cache_len, 0x10, 0x18);
+ /* RmiDevCommProtocol: If flags.send is true, type of request */
+ SET_MEMBER_RMI(unsigned char protocol, 0x18, 0x20);
+ /*
+ * UInt64: If flags.send is true, amount of valid data in request buffer
+ * in bytes
+ */
+ SET_MEMBER_RMI(unsigned long req_len, 0x20, 0x28);
+ /*
+ * UInt64: If flags.wait is true, amount of time to wait for device
+ * response in milliseconds
+ */
+ SET_MEMBER_RMI(unsigned long timeout, 0x28, 0x100);
+};
+
+/*
+ * RmiDevCommData
+ * This structure contains data structure shared between Host and RMM for
+ * device communication.
+ * Width: 4096 (0x1000) bytes.
+ */
+#define RMI_DEV_COMM_ENTER_OFFSET 0x0
+#define RMI_DEV_COMM_EXIT_OFFSET 0x800
+#define RMI_DEV_COMM_DATA_SIZE 0x1000
+struct rmi_dev_comm_data {
+ /* RmiDevCommEnter: Entry information */
+ SET_MEMBER_RMI(struct rmi_dev_comm_enter enter,
+ RMI_DEV_COMM_ENTER_OFFSET, RMI_DEV_COMM_EXIT_OFFSET);
+ /* RmiDevCommExit: Exit information */
+ SET_MEMBER_RMI(struct rmi_dev_comm_exit exit,
+ RMI_DEV_COMM_EXIT_OFFSET, RMI_DEV_COMM_DATA_SIZE);
+};
+
+/*
+ * RmiAddressRange
+ * This structure contains base and top value of an address range.
+ * Width: 16 (0x10) bytes.
+ */
+struct rmi_address_range {
+ /* Address: Base of the address range (inclusive) */
+ SET_MEMBER_RMI(unsigned long base, 0, 0x8);
+ /* Address: Top of the address range (exclusive) */
+ SET_MEMBER_RMI(unsigned long top, 0x8, 0x10);
+};
+
+/*
+ * Maximum number of aux granules paramenter passed in rmi_pdev_params during
+ * PDEV createto PDEV create
+ */
+#define PDEV_PARAM_AUX_GRANULES_MAX U(32)
+
+/*
+ * Maximum number of IO coherent RmiAddressRange parameter passed in
+ * rmi_pdev_params during PDEV create
+ */
+#define PDEV_PARAM_IOCOH_ADDR_RANGE_MAX U(16)
+
+/*
+ * Maximum number of fully coherent RmiAddressRange parameter passed in
+ * rmi_pdev_params during PDEV create
+ */
+#define PDEV_PARAM_FCOH_ADDR_RANGE_MAX U(4)
+
+/*
+ * RmiPdevParams
+ * This structure contains parameters provided by Host during PDEV creation.
+ * Width: 4096 (0x1000) bytes.
+ */
+struct rmi_pdev_params {
+ /* RmiPdevFlags: Flags */
+ SET_MEMBER_RMI(unsigned long flags, 0, 0x8);
+ /* Bits64: Physical device identifier */
+ SET_MEMBER_RMI(unsigned long pdev_id, 0x8, 0x10);
+ /* Bits16: Segment ID */
+ SET_MEMBER_RMI(unsigned short segment_id, 0x10, 0x18);
+ /* Bits16: Root Port identifier */
+ SET_MEMBER_RMI(unsigned short root_id, 0x18, 0x20);
+ /* UInt64: Certificate identifier */
+ SET_MEMBER_RMI(unsigned long cert_id, 0x20, 0x28);
+ /* UInt64: Base requester ID range (inclusive) */
+ SET_MEMBER_RMI(unsigned long rid_base, 0x28, 0x30);
+ /* UInt64: Top of requester ID range (exclusive) */
+ SET_MEMBER_RMI(unsigned long rid_top, 0x30, 0x38);
+ /* RmiHashAlgorithm: Algorithm used to generate device digests */
+ SET_MEMBER_RMI(unsigned char hash_algo, 0x38, 0x40);
+ /* UInt64: Number of auxiliary granules */
+ SET_MEMBER_RMI(unsigned long num_aux, 0x40, 0x48);
+ /* UInt64: IDE stream identifier */
+ SET_MEMBER_RMI(unsigned long ide_sid, 0x48, 0x50);
+ /* UInt64: Number of IO-coherent address ranges */
+ SET_MEMBER_RMI(unsigned long iocoh_num_addr_range, 0x50, 0x58);
+ /* UInt64: Number of fully-coherent address ranges */
+ SET_MEMBER_RMI(unsigned long fcoh_num_addr_range, 0x58, 0x100);
+
+ /* Address: Addresses of auxiliary granules */
+ SET_MEMBER_RMI(unsigned long aux[PDEV_PARAM_AUX_GRANULES_MAX], 0x100,
+ 0x200);
+ /* RmiAddressRange: IO-coherent address range */
+ SET_MEMBER_RMI(struct rmi_address_range
+ iocoh_addr_range[PDEV_PARAM_IOCOH_ADDR_RANGE_MAX],
+ 0x200, 0x300);
+ /* RmiAddressRange: Fully coherent address range */
+ SET_MEMBER_RMI(struct rmi_address_range
+ fcoh_addr_range[PDEV_PARAM_FCOH_ADDR_RANGE_MAX],
+ 0x300, 0x1000);
+};
+
struct rtt_entry {
long walk_level;
uint64_t out_addr;
@@ -554,6 +1095,7 @@
struct realm {
u_register_t host_shared_data;
unsigned int rec_count;
+ unsigned int num_aux_planes;
u_register_t par_base;
u_register_t par_size;
u_register_t rd;
@@ -574,9 +1116,12 @@
uint8_t pmu_num_ctrs;
bool payload_created;
bool shared_mem_created;
+ bool rtt_tree_single;
unsigned short vmid;
enum realm_state state;
long start_level;
+ u_register_t aux_rtt_addr[MAX_AUX_PLANE_COUNT];
+ unsigned short aux_vmid[MAX_AUX_PLANE_COUNT];
};
/* RMI/SMC */
@@ -615,6 +1160,12 @@
u_register_t start,
u_register_t end,
u_register_t *top);
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+ u_register_t rec,
+ u_register_t start,
+ u_register_t end,
+ u_register_t *top,
+ u_register_t *rtt_tree);
u_register_t host_rmi_psci_complete(u_register_t calling_rec, u_register_t target_rec,
unsigned long status);
void host_rmi_init_cmp_result(void);
@@ -646,4 +1197,15 @@
u_register_t map_size);
u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr, long level);
+u_register_t host_rmi_pdev_aux_count(u_register_t pdev_ptr, u_register_t *count);
+u_register_t host_rmi_pdev_create(u_register_t pdev_ptr,
+ u_register_t params_ptr);
+u_register_t host_rmi_pdev_get_state(u_register_t pdev_ptr, u_register_t *state);
+u_register_t host_rmi_pdev_communicate(u_register_t pdev_ptr,
+ u_register_t data_ptr);
+u_register_t host_rmi_pdev_set_pubkey(u_register_t pdev_ptr, u_register_t key,
+ u_register_t len, uint8_t algo);
+u_register_t host_rmi_pdev_stop(u_register_t pdev_ptr);
+u_register_t host_rmi_pdev_destroy(u_register_t pdev_ptr);
+
#endif /* HOST_REALM_RMI_H */
diff --git a/include/runtime_services/host_realm_managment/host_shared_data.h b/include/runtime_services/host_realm_managment/host_shared_data.h
index 7cfffe6..7005c0d 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -70,7 +70,10 @@
REALM_PAUTH_FAULT,
REALM_DIT_CHECK_CMD,
REALM_SME_ID_REGISTERS,
- REALM_SME_UNDEF_ABORT
+ REALM_SME_UNDEF_ABORT,
+ REALM_FEAT_DOUBLEFAULT2_TEST,
+ REALM_ATTESTATION,
+ REALM_ATTESTATION_FAULT
};
/*
diff --git a/include/runtime_services/host_realm_managment/realm_def.h b/include/runtime_services/host_realm_managment/realm_def.h
index 5258b87..5d3a196 100644
--- a/include/runtime_services/host_realm_managment/realm_def.h
+++ b/include/runtime_services/host_realm_managment/realm_def.h
@@ -10,7 +10,7 @@
#include <xlat_tables_defs.h>
-/* 1MB for Realm payload as a default value */
+/* 1 MB for Realm payload as a default value */
#define REALM_MAX_LOAD_IMG_SIZE U(0x100000)
#define REALM_STACK_SIZE 0x1000U
#define DATA_PATTERN_1 0x12345678U
@@ -19,6 +19,10 @@
#define REALM_ERROR 1U
#define MAX_REC_COUNT 17U
#define MAX_REALM_COUNT U(2)
+#define MAX_AUX_PLANE_COUNT U(3)
+#define MAX_PLANE_COUNT MAX_AUX_PLANE_COUNT + U(1)
+#define PRIMARY_RTT_INDEX 0U
+#define PRIMARY_PLANE_ID 0U
/* Only support 4KB at the moment */
@@ -101,4 +105,6 @@
(((idx) & ~MASK(RMI_MPIDR_AFF0)) << \
(RMI_MPIDR_AFF1_SHIFT - RMI_MPIDR_AFF0_WIDTH)));
+#define REALM_TOKEN_BUF_SIZE GRANULE_SIZE
+
#endif /* REALM_DEF_H */
diff --git a/include/runtime_services/smccc.h b/include/runtime_services/smccc.h
index b898138..513ec8f 100644
--- a/include/runtime_services/smccc.h
+++ b/include/runtime_services/smccc.h
@@ -80,4 +80,9 @@
#define SMC_GET_SOC_VERSION 0
#define SMC_GET_SOC_REVISION 1
+#define SCR_EL3_OPCODE U(0x1E1100)
+#define CPTR_EL3_OPCODE U(0x1E1140)
+#define MDCR_EL3_OPCODE U(0x1E1320)
+#define MPAM3_EL3_OPCODE U(0x1EA500)
+
#endif /* __SMCCC_H__ */
diff --git a/include/runtime_services/spm_test_helpers.h b/include/runtime_services/spm_test_helpers.h
index 93027d6..14b2fb5 100644
--- a/include/runtime_services/spm_test_helpers.h
+++ b/include/runtime_services/spm_test_helpers.h
@@ -104,12 +104,6 @@
event_t *cpu_booted);
/**
- * Call FFA_RUN in the designated SP to make it reach the message loop.
- * Used within CPU_ON handlers, to bring up the SP in the current core.
- */
-bool spm_core_sp_init(ffa_id_t sp_id);
-
-/**
* Initializes the Mailbox for other SPM related tests that need to use
* RXTX buffers.
*/
diff --git a/lib/context_mgmt/aarch64/context_el2.c b/lib/context_mgmt/aarch64/context_el2.c
index 3049274..2bea84b 100644
--- a/lib/context_mgmt/aarch64/context_el2.c
+++ b/lib/context_mgmt/aarch64/context_el2.c
@@ -57,7 +57,7 @@
{
if (is_armv8_6_fgt_present()) {
EL2_SAVE_CTX_REG(ctx, hdfgrtr_el2);
- if (is_armv8_4_amuv1_present())
+ if (is_feat_amuv1_present())
EL2_SAVE_CTX_REG(ctx, hafgrtr_el2);
EL2_SAVE_CTX_REG(ctx, hdfgwtr_el2);
EL2_SAVE_CTX_REG(ctx, hfgitr_el2);
@@ -231,7 +231,7 @@
{
if (is_armv8_6_fgt_present()) {
EL2_WRITE_MASK_CTX_REG(ctx, hdfgrtr_el2, or_mask);
- if (is_armv8_4_amuv1_present())
+ if (is_feat_amuv1_present())
EL2_WRITE_MASK_CTX_REG(ctx, hafgrtr_el2, or_mask);
EL2_WRITE_MASK_CTX_REG(ctx, hdfgwtr_el2, or_mask);
EL2_WRITE_MASK_CTX_REG(ctx, hfgitr_el2, or_mask);
diff --git a/lib/exceptions/aarch64/serror.c b/lib/exceptions/aarch64/serror.c
index 9c35712..a57514b 100644
--- a/lib/exceptions/aarch64/serror.c
+++ b/lib/exceptions/aarch64/serror.c
@@ -9,9 +9,9 @@
#include <debug.h>
#include <serror.h>
-static exception_handler_t custom_serror_handler;
+static serr_exception_handler_t custom_serror_handler;
-void register_custom_serror_handler(exception_handler_t handler)
+void register_custom_serror_handler(serr_exception_handler_t handler)
{
custom_serror_handler = handler;
}
@@ -23,9 +23,24 @@
bool tftf_serror_handler(void)
{
+ uint64_t elr_elx = IS_IN_EL2() ? read_elr_el2() : read_elr_el1();
+ bool resume = false;
+ bool incr_elr_elx = false;
+
if (custom_serror_handler == NULL) {
return false;
}
- return custom_serror_handler();
+ resume = custom_serror_handler(&incr_elr_elx);
+
+ if (resume && incr_elr_elx) {
+ /* Move ELR to next instruction to allow tftf to continue */
+ if (IS_IN_EL2()) {
+ write_elr_el2(elr_elx + 4U);
+ } else {
+ write_elr_el1(elr_elx + 4U);
+ }
+ }
+
+ return resume;
}
diff --git a/lib/ext_mbedtls/mbedtls.mk b/lib/ext_mbedtls/mbedtls.mk
new file mode 100644
index 0000000..74ab284
--- /dev/null
+++ b/lib/ext_mbedtls/mbedtls.mk
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MBEDTLS_DIR ?= ext/mbedtls
+ifeq (${MBEDTLS_DIR},)
+$(error Error: MBEDTLS_DIR not set)
+endif
+
+MBEDTLS_PRESENT := $(wildcard ${MBEDTLS_DIR}/include/mbedtls)
+
+ifneq (${MBEDTLS_PRESENT},)
+$(info Found mbedTLS at ${MBEDTLS_DIR})
+
+TFTF_INCLUDES += -I${MBEDTLS_DIR}/include
+MBEDTLS_CONFIG_FILE ?= "<configs/tftf_mbedtls_config.h>"
+$(eval $(call add_define,TFTF_DEFINES,MBEDTLS_CONFIG_FILE))
+
+#
+# Include mbedtls source required to parse x509 certificate and its helper
+# routines. This can be later extended to include other crypto/PSA crypto
+# library sources.
+#
+TESTS_SOURCES += \
+ $(addprefix ${MBEDTLS_DIR}/library/, \
+ asn1parse.c \
+ asn1write.c \
+ constant_time.c \
+ bignum.c \
+ oid.c \
+ hmac_drbg.c \
+ memory_buffer_alloc.c \
+ platform.c \
+ platform_util.c \
+ bignum_core.c \
+ md.c \
+ pk.c \
+ pk_ecc.c \
+ pk_wrap.c \
+ pkparse.c \
+ sha256.c \
+ sha512.c \
+ ecdsa.c \
+ ecp_curves.c \
+ ecp.c \
+ rsa.c \
+ rsa_alt_helpers.c \
+ x509.c \
+ x509_crt.c \
+ )
+else
+$(info MbedTLS not found, some dependent tests will be skipped or fail.)
+endif
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index f730568..56abf7a 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,22 +7,10 @@
#include <amu.h>
#include <amu_private.h>
#include <arch.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <assert.h>
-/*
- * Get AMU version value from pfr0.
- * Return values
- * ID_PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
- * ID_PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
- * ID_PFR0_AMU_NOT_SUPPORTED: not supported
- */
-unsigned int amu_get_version(void)
-{
- return (unsigned int)(read_id_pfr0() >> ID_PFR0_AMU_SHIFT) &
- ID_PFR0_AMU_MASK;
-}
-
/* Read the group 0 counter identified by the given `idx`. */
uint64_t amu_group0_cnt_read(unsigned int idx)
{
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 491edde..c089746 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,21 +7,10 @@
#include <amu.h>
#include <amu_private.h>
#include <arch.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <assert.h>
-/*
- * Get AMU version value from aa64pfr0.
- * Return values
- * ID_AA64PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
- * ID_AA64PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
- * ID_AA64PFR0_AMU_NOT_SUPPORTED: not supported
- */
-unsigned int amu_get_version(void)
-{
- return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
- ID_AA64PFR0_AMU_MASK;
-}
/* Check if group 1 counters is implemented */
int amu_group1_supported(void)
diff --git a/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S b/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
new file mode 100644
index 0000000..27db8b1
--- /dev/null
+++ b/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+#if __aarch64__
+
+ .globl read128_par_el1
+ .globl read128_ttbr0_el1
+ .globl read128_ttbr1_el1
+ .globl read128_ttbr0_el2
+ .globl read128_ttbr1_el2
+ .globl read128_vttbr_el2
+ .globl read128_rcwmask_el1
+ .globl read128_rcwsmask_el1
+ .globl write128_par_el1
+ .globl write128_ttbr0_el1
+ .globl write128_ttbr1_el1
+ .globl write128_ttbr0_el2
+ .globl write128_ttbr1_el2
+ .globl write128_vttbr_el2
+ .globl write128_rcwmask_el1
+ .globl write128_rcwsmask_el1
+
+func read128_par_el1 /* MRRS x0, x1, S3_0_C7_C4_0 */
+ .inst 0xD5787400
+ ret
+endfunc read128_par_el1
+
+func read128_ttbr0_el1 /* MRRS x0, x1, S3_0_C2_C0_0 */
+ .inst 0xD5782000
+ ret
+endfunc read128_ttbr0_el1
+
+func read128_ttbr1_el1 /* MRRS x0, x1, S3_0_C2_C0_1 */
+ .inst 0xD5782020
+ ret
+endfunc read128_ttbr1_el1
+
+func read128_ttbr0_el2 /* MRRS x0, x1, S3_4_C2_C0_0 */
+ .inst 0xD57C2000
+ ret
+endfunc read128_ttbr0_el2
+
+func read128_ttbr1_el2 /* MRRS x0, x1, S3_4_C2_C0_1 */
+ .inst 0xD57C2020
+ ret
+endfunc read128_ttbr1_el2
+
+func read128_vttbr_el2 /* MRRS x0, x1, S3_4_C2_C1_0 */
+ .inst 0xD57C2100
+ ret
+endfunc read128_vttbr_el2
+
+func read128_rcwmask_el1 /* MRRS x0, x1, S3_0_C13_C0_6 */
+ .inst 0xD578D0C0
+ ret
+endfunc read128_rcwmask_el1
+
+func read128_rcwsmask_el1 /* MRRS x0, x1, S3_0_C13_C0_3 */
+ .inst 0xD578D060
+ ret
+endfunc read128_rcwsmask_el1
+
+func write128_par_el1 /* MSRR S3_0_C7_C4_0, x0, x1 */
+ .inst 0xD5587400
+ ret
+endfunc write128_par_el1
+
+func write128_ttbr0_el1 /* MSRR S3_0_C2_C0_0, x0, x1 */
+ .inst 0xD5582000
+ ret
+endfunc write128_ttbr0_el1
+
+func write128_ttbr1_el1 /* MSRR S3_0_C2_C0_1, x0, x1 */
+ .inst 0xD5582020
+ ret
+endfunc write128_ttbr1_el1
+
+func write128_ttbr0_el2 /* MSRR S3_4_C2_C0_0, x0, x1 */
+ .inst 0xD55C2000
+ ret
+endfunc write128_ttbr0_el2
+
+func write128_ttbr1_el2 /* MSRR S3_4_C2_C0_1, x0, x1 */
+ .inst 0xD55C2020
+ ret
+endfunc write128_ttbr1_el2
+
+func write128_vttbr_el2 /* MSRR S3_4_C2_C1_0, x0, x1 */
+ .inst 0xD55C2100
+ ret
+endfunc write128_vttbr_el2
+
+func write128_rcwmask_el1 /* MSRR S3_0_C13_C0_6, x0, x1 */
+ .inst 0xD558D0C0
+ ret
+endfunc write128_rcwmask_el1
+
+func write128_rcwsmask_el1 /* MSRR S3_0_C13_C0_3, x0, x1 */
+ .inst 0xD558D060
+ ret
+endfunc write128_rcwsmask_el1
+
+#endif /* __aarch64__ */
diff --git a/lib/pcie/pcie.c b/lib/pcie/pcie.c
index c3906d5..8de2825 100644
--- a/lib/pcie/pcie.c
+++ b/lib/pcie/pcie.c
@@ -5,19 +5,20 @@
*/
#include <assert.h>
+#include <errno.h>
#include <stddef.h>
#include <debug.h>
#include <mmio.h>
#include <pcie.h>
+#include <pcie_doe.h>
#include <pcie_spec.h>
+#include <platform.h>
#include <tftf_lib.h>
-#include <platform_pcie.h>
-
#define PCIE_DEBUG VERBOSE
-const pcie_info_table_t *g_pcie_info_table;
+const struct pcie_info_table *g_pcie_info_table;
pcie_device_bdf_table_t *g_pcie_bdf_table;
pcie_device_bdf_table_t pcie_bdf_table[PCIE_DEVICE_BDF_TABLE_SZ];
@@ -256,6 +257,8 @@
return 1;
}
+ assert(g_pcie_bdf_table != NULL);
+
while (index < g_pcie_bdf_table->num_entries) {
*rp_bdf = g_pcie_bdf_table->device[index++].bdf;
@@ -294,6 +297,8 @@
uint32_t bdf, rp_bdf;
pcie_device_bdf_table_t *bdf_tbl_ptr = g_pcie_bdf_table;
+ assert(bdf_tbl_ptr != NULL);
+
for (unsigned int tbl_index = 0; tbl_index < bdf_tbl_ptr->num_entries;
tbl_index++) {
bdf = bdf_tbl_ptr->device[tbl_index].bdf;
@@ -317,6 +322,8 @@
*/
pcie_device_bdf_table_t *pcie_get_bdf_table(void)
{
+ assert(g_pcie_bdf_table != NULL);
+
return g_pcie_bdf_table;
}
@@ -336,6 +343,8 @@
assert(g_pcie_bdf_table != NULL);
g_pcie_bdf_table->num_entries = 0;
+
+ assert(g_pcie_info_table != NULL);
assert(g_pcie_info_table->num_entries != 0);
for (ecam_index = 0; ecam_index < g_pcie_info_table->num_entries; ecam_index++) {
@@ -420,6 +429,8 @@
uint32_t reg_value;
uintptr_t ecam_base = 0;
+ assert(g_pcie_info_table != NULL);
+
while (ecam_index < g_pcie_info_table->num_entries) {
/* Derive ECAM specific information */
const pcie_info_block_t *block = &g_pcie_info_table->block[ecam_index];
@@ -462,13 +473,15 @@
uint32_t ecam_index = 0;
uint32_t ecam_base, ecam_start_bus, ecam_end_bus;
pcie_device_bdf_table_t *bdf_tbl_ptr = g_pcie_bdf_table;
- uint32_t num_rciep = 0, num_rcec = 0;
- uint32_t num_iep = 0, num_irp = 0;
- uint32_t num_ep = 0, num_rp = 0;
- uint32_t num_dp = 0, num_up = 0;
- uint32_t num_pcie_pci = 0, num_pci_pcie = 0;
+ uint32_t num_rciep __unused = 0, num_rcec __unused = 0;
+ uint32_t num_iep __unused = 0, num_irp __unused = 0;
+ uint32_t num_ep __unused = 0, num_rp __unused = 0;
+ uint32_t num_dp __unused = 0, num_up __unused = 0;
+ uint32_t num_pcie_pci __unused = 0, num_pci_pcie __unused = 0;
uint32_t bdf_counter;
+ assert(bdf_tbl_ptr != NULL);
+
if (bdf_tbl_ptr->num_entries == 0) {
INFO("BDF Table: No RCiEP or iEP found\n");
return;
@@ -525,6 +538,8 @@
INFO("Number of PCI/PCIe Bridge: %u\n", num_pci_pcie);
INFO("Number of PCIe/PCI Bridge: %u\n", num_pcie_pci);
+ assert(g_pcie_info_table != NULL);
+
while (ecam_index < g_pcie_info_table->num_entries) {
/* Derive ECAM specific information */
@@ -540,7 +555,7 @@
while (tbl_index < bdf_tbl_ptr->num_entries) {
uint32_t seg_num, bus_num, dev_num, func_num;
- uint32_t device_id, vendor_id, reg_value;
+ uint32_t device_id __unused, vendor_id __unused, reg_value;
uint32_t bdf, dev_ecam_base;
bdf = bdf_tbl_ptr->device[tbl_index++].bdf;
@@ -588,13 +603,30 @@
INFO("Creating PCIe info table\n");
g_pcie_info_table = plat_pcie_get_info_table();
+ if (g_pcie_info_table == NULL) {
+ ERROR("PCIe info not returned by platform\n");
+ panic();
+ }
+
g_pcie_bdf_table = pcie_bdf_table;
num_ecam = g_pcie_info_table->num_entries;
INFO("Number of ECAM regions : %u\n", num_ecam);
- if (num_ecam == 0) {
- return;
+ if ((num_ecam == 0) || (num_ecam > MAX_PCIE_INFO_ENTRIES)) {
+ ERROR("PCIe info entries invalid\n");
+ panic();
}
pcie_create_device_bdf_table();
pcie_print_device_info();
}
+
+void pcie_init(void)
+{
+ static bool is_init;
+
+ /* Create PCIe table and enumeration */
+ if (!is_init) {
+ pcie_create_info_table();
+ is_init = true;
+ }
+}
diff --git a/lib/pcie/pcie_doe.c b/lib/pcie/pcie_doe.c
index 3c6819c..bd8e53a 100644
--- a/lib/pcie/pcie_doe.c
+++ b/lib/pcie/pcie_doe.c
@@ -5,7 +5,9 @@
*
*/
+#include <assert.h>
#include <errno.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -14,12 +16,6 @@
#include <pcie_doe.h>
#include <tftf_lib.h>
-#if LOG_LEVEL >= LOG_LEVEL_INFO
-#define DOE_INFO(...) mp_printf(__VA_ARGS__)
-#else
-#define DOE_INFO(...)
-#endif
-
static int pcie_doe_wait_ready(uint32_t bdf, uint32_t doe_cap_base)
{
uint32_t value;
@@ -65,9 +61,9 @@
INFO("Vendor ID: 0x%x, ", data->vendor_id);
if (type >= ARRAY_SIZE(doe_object_type)) {
- DOE_INFO("Unknown type: 0x%x\n", type);
+ INFO("Unknown type: 0x%x\n", type);
} else {
- DOE_INFO("%s\n", doe_object_type[type]);
+ INFO("%s\n", doe_object_type[type]);
}
}
@@ -77,16 +73,16 @@
if (last) {
if ((j & 7) == 0) {
- INFO(" %08x\n", data);
+ VERBOSE(" %08x\n", data);
} else {
- DOE_INFO(" %08x\n", data);
+ VERBOSE(" %08x\n", data);
}
} else if ((j & 7) == 0) {
- INFO(" %08x", data);
+ VERBOSE(" %08x", data);
} else if ((j & 7) == 7) {
- DOE_INFO(" %08x\n", data);
+ VERBOSE(" %08x\n", data);
} else {
- DOE_INFO(" %08x", data);
+ VERBOSE(" %08x", data);
}
}
@@ -121,11 +117,11 @@
/* Calculated adjusted data length in DW */
doe_length = (rem_length == 0) ? send_length : (send_length + 1);
- INFO(">%08x", header);
+ VERBOSE(">%08x", header);
pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG,
header);
- DOE_INFO(" %08x", doe_length + DOE_HEADER_LENGTH);
+ VERBOSE(" %08x", doe_length + DOE_HEADER_LENGTH);
pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG,
doe_length + DOE_HEADER_LENGTH);
@@ -144,7 +140,7 @@
pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG, value);
} else if (((i + DOE_HEADER_LENGTH) & 7) != 0) {
- DOE_INFO("\n");
+ VERBOSE("\n");
}
/* Set Go bit */
@@ -178,7 +174,7 @@
* Vendor ID and Data Object Type
*/
value = pcie_read_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG);
- INFO("<%08x", value);
+ VERBOSE("<%08x", value);
/* Indicate a successful transfer of the current data object DW */
pcie_write_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG, 0);
@@ -188,13 +184,13 @@
* Length in DW
*/
value = pcie_read_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG);
- DOE_INFO(" %08x", value);
+ VERBOSE(" %08x", value);
pcie_write_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG, 0);
/* Check value */
if ((value & PCI_DOE_RESERVED_MASK) != 0) {
- DOE_INFO("\n");
+ VERBOSE("\n");
ERROR("DOE Data Object Header 2 error\n");
return -EIO;
}
@@ -214,7 +210,7 @@
}
if (((i + DOE_HEADER_LENGTH) & 7) != 0) {
- DOE_INFO("\n");
+ VERBOSE("\n");
}
value = pcie_read_cfg(bdf, doe_cap_base + DOE_STATUS_REG);
@@ -225,3 +221,55 @@
return 0;
}
+
+int pcie_doe_communicate(uint32_t header, uint32_t bdf, uint32_t doe_cap_base,
+ void *req_buf, size_t req_sz, void *rsp_buf, size_t *rsp_sz)
+{
+ int rc;
+
+ assert(header == DOE_HEADER_0 || header == DOE_HEADER_1 || header == DOE_HEADER_2);
+
+ rc = pcie_doe_send_req(header, bdf, doe_cap_base,
+ (uint32_t *)req_buf, (uint32_t)req_sz);
+ if (rc != 0) {
+ ERROR("PCIe DOE %s failed %d\n", "Request", rc);
+ return rc;
+ }
+
+ rc = pcie_doe_recv_resp(bdf, doe_cap_base, (uint32_t *)rsp_buf,
+ (uint32_t *)rsp_sz);
+ return rc;
+}
+
+int pcie_find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr)
+{
+ pcie_device_bdf_table_t *bdf_table_ptr = pcie_get_bdf_table();
+ uint32_t num_bdf = bdf_table_ptr->num_entries;
+
+ INFO("PCI BDF table entries: %u\n", num_bdf);
+
+ /* If no entries in BDF table return error */
+ if (num_bdf == 0) {
+ ERROR("No BDFs entries found\n");
+ return -ENODEV;
+ }
+
+ INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr);
+
+ while (num_bdf-- != 0) {
+ uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf;
+ uint32_t status, doe_cap_base;
+
+ /* Check for DOE capability */
+ status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base);
+ if (status == PCIE_SUCCESS) {
+ INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base);
+ *bdf_ptr = bdf;
+ *cap_base_ptr = doe_cap_base;
+ return 0;
+ }
+ }
+
+ ERROR("No PCIe DOE capability found\n");
+ return -ENODEV;
+}
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 5c68642..3981aa9 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -254,7 +254,7 @@
tftf_prepare_cpu_off();
tftf_set_cpu_offline();
- INFO("Powering off\n");
+ INFO("Powering off CPU:%lx\n", read_mpidr_el1());
/* Flush console before the last CPU is powered off. */
if (tftf_get_ref_cnt() == 0)
@@ -307,7 +307,7 @@
enable_irq();
- INFO("Booting\n");
+ INFO("Booting CPU:%lx\n", read_mpidr_el1());
tftf_set_cpu_online();
diff --git a/lib/smc/aarch64/asm_smc.S b/lib/smc/aarch64/asm_smc.S
index b11baa8..d4cede9 100644
--- a/lib/smc/aarch64/asm_smc.S
+++ b/lib/smc/aarch64/asm_smc.S
@@ -38,6 +38,59 @@
.endm
+ .macro smccc_conduit_nox8 _conduit
+
+ /*
+ * Store address pointing at the smc_ret_values structure in the stack
+ */
+ str x1, [sp, #-16]!
+
+ /*
+ * Store arguments in x0..x17. Start from highest registers so address
+ * pointed by x0 is preserved until it is no longer needed.
+ */
+ ldp x16, x17, [x0, #128]
+ ldp x14, x15, [x0, #112]
+ ldp x12, x13, [x0, #96]
+ ldp x10, x11, [x0, #80]
+ ldp x8, x9, [x0, #64]
+ ldp x6, x7, [x0, #48]
+ ldp x4, x5, [x0, #32]
+ ldp x2, x3, [x0, #16]
+ ldp x0, x1, [x0, #0]
+
+ /* "Conduit" arguments are already stored in x0..x17 */
+ \_conduit #0
+
+ /*
+ * Store value received in x0 as x0 will be used to compute addresses
+ * to store the results.
+ */
+ str x0, [sp, #-16]!
+
+ /* Load address of smc_ret_values structure into x0 */
+ ldr x0, [sp, #16]
+
+ /* Store values x1..x17 in the smc_ret_values structure */
+ stp x16, x17, [x0, #128]
+ stp x14, x15, [x0, #112]
+ stp x12, x13, [x0, #96]
+ stp x10, x11, [x0, #80]
+ stp x8, x9, [x0, #64]
+ stp x6, x7, [x0, #48]
+ stp x4, x5, [x0, #32]
+ stp x2, x3, [x0, #16]
+ str x1, [x0, #8]
+
+ /*
+ * Load previously stored value of x0 into x1 and store it in the
+ * smc_ret_values structure. Return sp to its original position.
+ */
+ ldr x1, [sp], #32
+ str x1, [x0, #0]
+
+ .endm
+
/* ---------------------------------------------------------------------------
* smc_ret_values asm_tftf_smc64(uint32_t fid,
* u_register_t arg1,
@@ -56,6 +109,17 @@
ret
endfunc asm_tftf_smc64
+ .globl asm_tftf_smc64_no_retval_x8
+
+/* ---------------------------------------------------------------------------
+ * void asm_tftf_smc64_no_retval_x8(smc_args *args, smc_ret_values *ret);
+ * ---------------------------------------------------------------------------
+ */
+func asm_tftf_smc64_no_retval_x8
+ smccc_conduit_nox8 smc
+ ret
+endfunc asm_tftf_smc64_no_retval_x8
+
/* ---------------------------------------------------------------------------
* hvc_ret_values asm_tftf_hvcc64(uint32_t fid,
* u_register_t arg1,
diff --git a/lib/smc/aarch64/smc.c b/lib/smc/aarch64/smc.c
index 9912e72..b0fea4b 100644
--- a/lib/smc/aarch64/smc.c
+++ b/lib/smc/aarch64/smc.c
@@ -102,3 +102,19 @@
args->arg6,
args->arg7);
}
+
+void tftf_smc_no_retval_x8(const smc_args_ext *args, smc_ret_values_ext *ret)
+{
+ uint32_t fid = args->fid;
+ /* Copy args into new structure so the fid field can be modified */
+ smc_args_ext args_copy = *args;
+
+ if (tftf_smc_get_sve_hint()) {
+ fid |= MASK(FUNCID_SVE_HINT);
+ } else {
+ fid &= ~MASK(FUNCID_SVE_HINT);
+ }
+ args_copy.fid = fid;
+
+ asm_tftf_smc64_no_retval_x8(&args_copy, ret);
+}
diff --git a/plat/arm/fvp/fvp_pcie.c b/plat/arm/fvp/fvp_pcie.c
index 0569832..c43e42d 100644
--- a/plat/arm/fvp/fvp_pcie.c
+++ b/plat/arm/fvp/fvp_pcie.c
@@ -11,7 +11,7 @@
CASSERT(PLATFORM_NUM_ECAM != 0, PLATFORM_NUM_ECAM_is_zero);
-const pcie_info_table_t fvp_pcie_cfg = {
+const struct pcie_info_table fvp_pcie_cfg = {
.num_entries = PLATFORM_NUM_ECAM,
.block[0] = {
PLATFORM_PCIE_ECAM_BASE_ADDR_0,
@@ -21,7 +21,7 @@
}
};
-const pcie_info_table_t *plat_pcie_get_info_table(void)
+const struct pcie_info_table *plat_pcie_get_info_table(void)
{
return &fvp_pcie_cfg;
}
diff --git a/plat/arm/fvp/include/platform_pcie.h b/plat/arm/fvp/include/platform_pcie.h
index c76c7d9..4b3a0e9 100644
--- a/plat/arm/fvp/include/platform_pcie.h
+++ b/plat/arm/fvp/include/platform_pcie.h
@@ -19,6 +19,4 @@
#define PLATFORM_PCIE_START_BUS_NUM_0 0x0
#define PLATFORM_PCIE_END_BUS_NUM_0 0xFF
-const pcie_info_table_t *plat_pcie_get_info_table(void);
-
#endif /* PLATFORM_PCIE_H */
diff --git a/plat/arm/fvp/plat_setup.c b/plat/arm/fvp/plat_setup.c
index e6e4244..69cb0a1 100644
--- a/plat/arm/fvp/plat_setup.c
+++ b/plat/arm/fvp/plat_setup.c
@@ -35,9 +35,7 @@
#if USE_NVM
MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
#endif
-#if USE_PCIE
MAP_REGION_FLAT(PCIE_CONFIG_BASE, PCIE_CONFIG_SIZE, MT_DEVICE | MT_RW | MT_NS),
-#endif
MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS),
{0}
};
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index 7a2850f..ee30721 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -90,12 +90,8 @@
$(eval $(call add_define,TFTF_DEFINES,PA_SIZE))
$(eval $(call add_define,REALM_DEFINES,PA_SIZE))
-ifeq ($(TESTS),pcie-doe)
-USE_PCIE=1
-$(eval $(call add_define,TFTF_DEFINES,USE_PCIE))
-endif
-
-PLAT_INCLUDES += -Iplat/arm/fvp/include/
+PLAT_INCLUDES += -Iplat/arm/fvp/include/ \
+ -Iinclude/lib/pcie/
PLAT_SOURCES := drivers/arm/gic/arm_gic_v2v3.c \
drivers/arm/gic/gic_v2.c \
@@ -104,6 +100,7 @@
drivers/arm/timer/private_timer.c \
drivers/arm/timer/system_timer.c \
plat/arm/fvp/${ARCH}/plat_helpers.S \
+ plat/arm/fvp/fvp_pcie.c \
plat/arm/fvp/fvp_pwr_state.c \
plat/arm/fvp/fvp_topology.c \
plat/arm/fvp/fvp_mem_prot.c \
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h
new file mode 100644
index 0000000..b9e3654
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the CSS specific definitions for the third generation of
+ * platforms.
+ */
+
+#ifndef NRD_CSS_DEF3_H
+#define NRD_CSS_DEF3_H
+
+/*******************************************************************************
+ * CSS memory map related defines
+ ******************************************************************************/
+
+/* Sub-system Peripherals */
+#define NRD_CSS_PERIPH0_BASE UL(0x2A400000)
+#define NRD_CSS_PERIPH0_SIZE UL(0x0DC00000)
+
+/* Peripherals and PCIe expansion area */
+#define NRD_CSS_PERIPH1_BASE UL(0x60000000)
+#define NRD_CSS_PERIPH1_SIZE UL(0x20000000)
+
+/* DRAM base address and size */
+#define NRD_CSS_DRAM1_BASE UL(0x80000000)
+#define NRD_CSS_DRAM1_SIZE UL(0x80000000)
+
+/* AP Non-Secure UART related constants */
+#define NRD_CSS_NSEC_UART_BASE UL(0x2A400000)
+
+/* Base address of trusted watchdog (SP805) */
+#define NRD_CSS_TWDOG_BASE UL(0x2A480000)
+
+/* Base address of non-trusted watchdog (SP805) */
+#define NRD_CSS_WDOG_BASE UL(0x2A440000)
+
+/* Memory mapped Generic timer interfaces */
+#define NRD_CSS_NSEC_CNT_BASE1 UL(0x2A830000)
+
+#endif /* NRD_CSS_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
new file mode 100644
index 0000000..245b3d7
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the CSS-firmware specific definitions for the third
+ * generation of platforms.
+ */
+
+#ifndef NRD_CSS_FW_DEF3_H
+#define NRD_CSS_FW_DEF3_H
+
+#include "nrd_css_def3.h"
+
+/*******************************************************************************
+ * Console config
+ ******************************************************************************/
+
+#define NRD_CSS_NSEC_CLK_IN_HZ UL(7372800)
+
+#endif /* NRD_CSS_FW_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
new file mode 100644
index 0000000..20c748e
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is limited to include the platform port definitions for the
+ * third generation of platforms.
+ */
+
+#ifndef NRD_PLAT_ARM_DEF3_H
+#define NRD_PLAT_ARM_DEF3_H
+
+#ifndef __ASSEMBLER__
+#include <lib/mmio.h>
+#endif /* __ASSEMBLER__ */
+
+#include <lib/utils_def.h>
+#include "nrd_css_fw_def3.h"
+#include "nrd_ros_def3.h"
+
+/* Platform binary types for linking */
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Stack size
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE U(0x1400) /* 5120 bytes */
+
+/* Size of coherent stacks */
+#define PCPU_DV_MEM_STACK_SIZE U(0x600) /* 1536 bytes */
+
+/*******************************************************************************
+ * Core count
+ ******************************************************************************/
+
+#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
+ NRD_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_NUM_AFFS (PLAT_ARM_CLUSTER_COUNT + PLATFORM_CORE_COUNT)
+
+/*******************************************************************************
+ * Power related definitions
+ ******************************************************************************/
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1
+
+#define PLAT_MAX_PWR_LEVEL PLATFORM_MAX_AFFLVL
+#define PLAT_MAX_PWR_STATES_PER_LVL U(2)
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+
+/*******************************************************************************
+ * XLAT definitions
+ ******************************************************************************/
+
+/* Platform specific page table and MMU setup constants */
+#define MAX_XLAT_TABLES U(7)
+#define MAX_MMAP_REGIONS U(16)
+
+/*******************************************************************************
+ * I/O definitions
+ ******************************************************************************/
+
+/* I/O Storage NOR flash device */
+#define MAX_IO_DEVICES U(1)
+#define MAX_IO_HANDLES U(1)
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+
+#define IRQ_NS_SGI_0 U(0)
+#define IRQ_NS_SGI_7 U(7)
+
+/* Maximum SPI */
+#define PLAT_MAX_SPI_OFFSET_ID U(256)
+
+/*******************************************************************************
+ * Timer config
+ ******************************************************************************/
+
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER U(26)
+
+/* Memory mapped Generic timer interfaces */
+#define SYS_CNT_BASE1 NRD_CSS_NSEC_CNT_BASE1
+
+/* AP_REFCLK Generic Timer, Non-secure. */
+#define IRQ_CNTPSIRQ1 U(109)
+
+/* Times(in ms) used by test code for completion of different events */
+#define PLAT_SUSPEND_ENTRY_TIME U(15)
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME U(30)
+
+/*******************************************************************************
+ * Console config
+ ******************************************************************************/
+
+#define PLAT_ARM_UART_BASE NRD_CSS_NSEC_UART_BASE
+#define PLAT_ARM_UART_CLK_IN_HZ NRD_CSS_NSEC_CLK_IN_HZ
+
+/*******************************************************************************
+ * DRAM config
+ ******************************************************************************/
+
+/* TF-A reserves DRAM space 0xFF000000- 0xFFFFFFFF for TZC */
+#define DRAM_BASE NRD_CSS_DRAM1_BASE
+#define DRAM_SIZE (NRD_CSS_DRAM1_SIZE - 0x1000000)
+
+/*******************************************************************************
+ * Cache related config
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (1U << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE UL(0xE0000000)
+
+/*******************************************************************************
+ * TFTF NVM configs
+ ******************************************************************************/
+
+#define TFTF_NVM_OFFSET U(0x0)
+#define TFTF_NVM_SIZE UL(0x08000000) /* 128 MB */
+
+/*******************************************************************************
+ * Watchdog related config
+ ******************************************************************************/
+
+/* Base address of trusted watchdog (SP805) */
+#define SP805_TWDOG_BASE NRD_CSS_TWDOG_BASE
+
+/* Base address of non-trusted watchdog (SP805) */
+#define SP805_WDOG_BASE NRD_CSS_WDOG_BASE
+
+/* Trusted watchdog (SP805) Interrupt ID */
+#define IRQ_TWDOG_INTID U(107)
+
+/*******************************************************************************
+ * Flash related config
+ ******************************************************************************/
+
+/* Base address and size of external NVM flash */
+#define FLASH_BASE NRD_ROS_FLASH_BASE
+#define FLASH_SIZE NRD_ROS_FLASH_SIZE
+#define NOR_FLASH_BLOCK_SIZE UL(0x40000) /* 256KB */
+
+#endif /* NRD_PLAT_ARM_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h
new file mode 100644
index 0000000..2822ed9
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the RoS specific definitions for the third generation of
+ * platforms.
+ */
+
+#ifndef NRD_ROS_DEF3_H
+#define NRD_ROS_DEF3_H
+
+/*******************************************************************************
+ * ROS configs
+ ******************************************************************************/
+
+/* Base address and size of external NVM flash */
+#define NRD_ROS_FLASH_BASE UL(0x08000000) /* 128MB */
+#define NRD_ROS_FLASH_SIZE UL(0x04000000) /* 64MB */
+
+#endif /* NRD_ROS_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h
new file mode 100644
index 0000000..f3ae5ef
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <nrd3/nrd_plat_arm_def3.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(16)
+#define NRD_MAX_CPUS_PER_CLUSTER U(1)
+#define NRD_MAX_PE_PER_CPU U(1)
+
+/* GIC-600 & interrupt handling related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICR_BASE UL(0x301C0000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+
+/* Platform specific page table and MMU setup constants */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 46)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 46)
+
+#endif /* PLATFORM_DEF_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/neoverse_rd/platform/rdv3/platform.mk
new file mode 100644
index 0000000..3fd2cd2
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/platform.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/arm/neoverse_rd/common/nrd_common.mk
+
+PLAT_INCLUDES += -Iplat/arm/neoverse_rd/platform/rdv3/include/
+
+PLAT_SOURCES += plat/arm/neoverse_rd/platform/rdv3/topology.c
+
+PLAT_TESTS_SKIP_LIST := plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
+
+RD_V3_VARIANTS := 0
+
+ifneq ($(NRD_PLATFORM_VARIANT), \
+ $(filter $(NRD_PLATFORM_VARIANT),$(RD_V3_VARIANTS)))
+ $(error "NRD_PLATFORM_VARIANT for RD-V3 should be 0, currently \
+ set to ${NRD_PLATFORM_VARIANT}.")
+endif
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
new file mode 100644
index 0000000..d5904e8
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# OS-initiated mode is not supported on RD-V3
+PSCI CPU Suspend in OSI mode
+
+# System suspend is not supported as there are no wakeup sources in RD-V3 FVP
+PSCI STAT/Stats test cases after system suspend
+PSCI System Suspend Validation
+
+# The following test cases result in unhandled exception at EL3
+CPU extensions/Use trace buffer control Registers
+CPU extensions/Use trace filter control Registers
+CPU extensions/Use branch record buffer control registers
+
+Framework Validation
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/topology.c b/plat/arm/neoverse_rd/platform/rdv3/topology.c
new file mode 100644
index 0000000..07e2a57
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/topology.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <plat_topology.h>
+#include <tftf_lib.h>
+
+static const struct {
+ unsigned int cluster_id;
+ unsigned int cpu_id;
+} plat_cores[] = {
+ /* Cluster0: 1 core */
+ { 0, 0 },
+ /* Cluster1: 1 core */
+ { 1, 0 },
+ /* Cluster2: 1 core */
+ { 2, 0 },
+ /* Cluster3: 1 core */
+ { 3, 0 },
+ /* Cluster4: 1 core */
+ { 4, 0 },
+ /* Cluster5: 1 core */
+ { 5, 0 },
+ /* Cluster6: 1 core */
+ { 6, 0 },
+ /* Cluster7: 1 core */
+ { 7, 0 },
+ /* Cluster8: 1 core */
+ { 8, 0 },
+ /* Cluster9: 1 core */
+ { 9, 0 },
+ /* Cluster10: 1 core */
+ { 10, 0 },
+ /* Cluster11: 1 core */
+ { 11, 0 },
+ /* Cluster12: 1 core */
+ { 12, 0 },
+ /* Cluster13: 1 core */
+ { 13, 0 },
+ /* Cluster14: 1 core */
+ { 14, 0 },
+ /* Cluster15: 1 core */
+ { 15, 0 },
+};
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char plat_pd_tree_desc[] = {
+ /* Number of root nodes */
+ PLAT_ARM_CLUSTER_COUNT,
+ /* Number of children for the 1st node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 2nd node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 3rd node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 4th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 5th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 6th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 7th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 8th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 9th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 10th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 11th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 12th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 13th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 14th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 15th node */
+ NRD_MAX_CPUS_PER_CLUSTER,
+ /* Number of children for the 16th node */
+ NRD_MAX_CPUS_PER_CLUSTER
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+ return plat_pd_tree_desc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+ unsigned int mpid;
+
+ assert(core_pos < PLATFORM_CORE_COUNT);
+
+ mpid = make_mpid(plat_cores[core_pos].cluster_id,
+ plat_cores[core_pos].cpu_id);
+
+ return (uint64_t)mpid;
+}
\ No newline at end of file
diff --git a/plat/common/plat_common.c b/plat/common/plat_common.c
index c43ae12..a4195c3 100644
--- a/plat/common/plat_common.c
+++ b/plat/common/plat_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,6 +24,7 @@
#pragma weak tftf_plat_enable_mmu
#pragma weak tftf_plat_reset
#pragma weak plat_get_prot_regions
+#pragma weak plat_pcie_get_info_table
#if IMAGE_TFTF
@@ -148,3 +149,8 @@
*nelem = 0;
return NULL;
}
+
+const struct pcie_info_table *plat_pcie_get_info_table(void)
+{
+ return NULL;
+}
diff --git a/plat/xilinx/versal/tests_to_skip.txt b/plat/xilinx/versal/tests_to_skip.txt
index 87b9e41..997bc61 100644
--- a/plat/xilinx/versal/tests_to_skip.txt
+++ b/plat/xilinx/versal/tests_to_skip.txt
@@ -30,6 +30,10 @@
PSCI System Suspend Validation/system suspend from all cores
PSCI System Suspend Validation/Validate suspend to RAM functionality
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
#TESTS: el3-power-state
EL3 power state parser validation/Create all power states and validate EL3 power state parsing
EL3 power state parser validation/Create invalid local power state at all levels and validate EL3 power state parsing
diff --git a/plat/xilinx/versal_net/tests_to_skip.txt b/plat/xilinx/versal_net/tests_to_skip.txt
index 80e7cb2..f9668ee 100644
--- a/plat/xilinx/versal_net/tests_to_skip.txt
+++ b/plat/xilinx/versal_net/tests_to_skip.txt
@@ -58,6 +58,10 @@
PSCI System Suspend Validation/system suspend from all cores
PSCI System Suspend Validation/Validate suspend to RAM functionality
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
#TESTS: el3-power-state
EL3 power state parser validation
diff --git a/plat/xilinx/zynqmp/tests_to_skip.txt b/plat/xilinx/zynqmp/tests_to_skip.txt
index 271fdc8..f72de18 100644
--- a/plat/xilinx/zynqmp/tests_to_skip.txt
+++ b/plat/xilinx/zynqmp/tests_to_skip.txt
@@ -49,6 +49,10 @@
PSCI STAT/Stats test cases for CPU OFF
PSCI STAT/Stats test cases after system suspend
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
#TESTS: el3-power-state
EL3 power state parser validation
diff --git a/realm/aarch64/realm_exceptions.S b/realm/aarch64/realm_exceptions.S
index 210dd3e..c1d1c0c 100644
--- a/realm/aarch64/realm_exceptions.S
+++ b/realm/aarch64/realm_exceptions.S
@@ -43,8 +43,9 @@
b interrupt_vector_entry
end_vector_entry fiq_spx
-unhandled_exception serr_spx
-
+vector_entry serr_spx
+ b serr_exception_vector_entry
+end_vector_entry serr_spx
/*
* Lower EL using AArch64 : 0x400 - 0x600.
*/
@@ -116,6 +117,22 @@
eret
endfunc sync_exception_vector_entry
+func serr_exception_vector_entry
+ sub sp, sp, #0x100
+ save_gp_regs
+ mov x19, sp
+ bl tftf_serror_handler
+ cbnz x0, 0f
+ mov x0, x19
+ /* Save original stack pointer value on the stack */
+ add x1, x0, #0x100
+ str x1, [x0, #0xf8]
+ b realm_print_exception
+0: restore_gp_regs
+ add sp, sp, #0x100
+ eret
+endfunc serr_exception_vector_entry
+
func interrupt_vector_entry
sub sp, sp, #0x100
save_gp_regs
diff --git a/realm/include/realm_helpers.h b/realm/include/realm_helpers.h
new file mode 100644
index 0000000..a9b2f7c
--- /dev/null
+++ b/realm/include/realm_helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REALM_HELPERS_H
+#define REALM_HELPERS_H
+
+/* Generate 64-bit random number */
+unsigned long long realm_rand64(void);
+/*
+ * Function to enter Aux Plane from Primary Plane
+ * arg1 == plane index
+ * arg2 == permission index to be used by plane
+ * arg3 == base entrypoint
+ * arg4 == entry flags
+ * aarg5 == run object, needs to be PAGE aligned
+ */
+bool realm_plane_enter(u_register_t plane_index, u_register_t perm_index,
+ u_register_t base, u_register_t flags, rsi_plane_run *run);
+
+/* Function for initializing planes, called at Boot */
+void realm_plane_init(void);
+
+#endif /* REALM_HELPERS_H */
+
diff --git a/realm/include/realm_rsi.h b/realm/include/realm_rsi.h
index 92a078b..33e8fcf 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -8,6 +8,7 @@
#ifndef REALM_RSI_H
#define REALM_RSI_H
+#include <arch.h>
#include <stdint.h>
#include <host_shared_data.h>
#include <tftf_lib.h>
@@ -71,7 +72,9 @@
/* IPA width in bits */
SET_MEMBER(unsigned long ipa_width, 0, 8); /* Offset 0 */
/* Hash algorithm */
- SET_MEMBER(unsigned long algorithm, 8, 0x200); /* Offset 8 */
+ SET_MEMBER(unsigned long algorithm, 8, 0x10); /* Offset 8 */
+ /* Number of auxiliary Planes */
+ SET_MEMBER(unsigned long num_aux_planes, 0x10, 0x200); /* Offset 0x10 */
/* Realm Personalization Value */
SET_MEMBER(unsigned char rpv[RSI_RPV_SIZE], 0x200, 0x1000); /* Offset 0x200 */
};
@@ -127,6 +130,21 @@
*/
#define RSI_IPA_STATE_GET SMC_RSI_FID(8U)
+/*
+ * ret0 == Status / error
+ * ret1 == Token maximum length
+ */
+#define RSI_ATTEST_TOKEN_INIT SMC_RSI_FID(4U)
+
+/*
+ * arg0 == Base of buffer to write the token to
+ * arg1 == Offset within the buffer
+ * arg2 == Size of the buffer
+ * ret0 == Status / error
+ * ret1 == Size of received token hunk
+ */
+#define RSI_ATTEST_TOKEN_CONTINUE SMC_RSI_FID(5U)
+
typedef enum {
RSI_EMPTY = 0U,
RSI_RAM,
@@ -142,7 +160,151 @@
#define RSI_NO_CHANGE_DESTROYED 0UL
#define RSI_CHANGE_DESTROYED 1UL
-/* Request RIPAS of a target IPA range to be changed to a specified value */
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ * ret1 == perm value
+ */
+#define RSI_MEM_GET_PERM_VALUE SMC_RSI_FID(0x10U)
+
+/*
+ * arg1 == base adr
+ * arg2 == top adr
+ * arg3 == perm index
+ * arg4 == cookie
+ *
+ * ret0 == status
+ * ret1 == new_base
+ * ret2 == response
+ * ret3 == new_cookie
+ */
+#define RSI_MEM_SET_PERM_INDEX SMC_RSI_FID(0x11U)
+
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ */
+#define RSI_MEM_SET_PERM_VALUE SMC_RSI_FID(0x12U)
+
+#define RSI_PLANE_NR_GPRS 31U
+#define RSI_PLANE_GIC_NUM_LRS 16U
+
+/*
+ * Flags provided by the Primary Plane to the secondary ones upon
+ * plane entry.
+ */
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFI U(1UL << 0)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFE U(1UL << 1)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_HC U(1UL << 2)
+
+/* Data structure used to pass values from P0 to the RMM on Plane entry */
+struct rsi_plane_entry {
+ /* Flags */
+ SET_MEMBER(u_register_t flags, 0, 0x8); /* Offset 0 */
+ /* PC */
+ SET_MEMBER(u_register_t pc, 0x8, 0x100); /* Offset 0x8 */
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x100, 0x200); /* 0x100 */
+ /* EL1 system registers */
+ SET_MEMBER(struct {
+ /* GICv3 Hypervisor Control Register */
+ u_register_t gicv3_hcr; /* 0x200 */
+ /* GICv3 List Registers */
+ u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS]; /* 0x208 */
+ }, 0x200, 0x800);
+};
+
+/* Data structure used to pass values from the RMM to P0 on Plane exit */
+struct rsi_plane_exit {
+ /* Exit reason */
+ SET_MEMBER(u_register_t exit_reason, 0, 0x100);/* Offset 0 */
+ SET_MEMBER(struct {
+ /* Exception Link Register */
+ u_register_t elr; /* 0x100 */
+ /* Exception Syndrome Register */
+ u_register_t esr; /* 0x108 */
+ /* Fault Address Register */
+ u_register_t far; /* 0x108 */
+ /* Hypervisor IPA Fault Address register */
+ u_register_t hpfar; /* 0x110 */
+ }, 0x100, 0x200);
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x200, 0x300); /* 0x200 */
+ SET_MEMBER(struct {
+ /* GICv3 Hypervisor Control Register */
+ u_register_t gicv3_hcr; /* 0x300 */
+ /* GICv3 List Registers */
+ u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS]; /* 0x308 */
+ /* GICv3 Maintenance Interrupt State Register */
+ u_register_t gicv3_misr; /* 0x388 */
+ /* GICv3 Virtual Machine Control Register */
+ u_register_t gicv3_vmcr; /* 0x390 */
+ }, 0x300, 0x600);
+};
+
+typedef struct {
+ /* Entry information */
+ SET_MEMBER(struct rsi_plane_entry enter, 0, 0x800); /* Offset 0 */
+ /* Exit information */
+ SET_MEMBER(struct rsi_plane_exit exit, 0x800, 0x1000);/* 0x800 */
+} rsi_plane_run;
+
+/*
+ * arg1 == plane index
+ * arg2 == run pointer
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_ENTER SMC_RSI_FID(0x13U)
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ *
+ * ret0 == status
+ * ret1 = register value
+ */
+#define RSI_PLANE_REG_READ SMC_RSI_FID(0x1EU)
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ * arg3 == register value
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_REG_WRITE SMC_RSI_FID(0x1FU)
+
+/*
+ * Function to set overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t perm);
+
+/*
+ * Function to Get overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t *perm);
+
+/* Function to Set overlay permission index for a specified IPA range See RSI_MEM_SET_PERM_INDEX */
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+ u_register_t top,
+ u_register_t perm_index,
+ u_register_t cookie,
+ u_register_t *new_base,
+ u_register_t *response,
+ u_register_t *new_cookie);
+
+/* Request RIPAS of a target IPA range to be changed to a specified value. */
u_register_t rsi_ipa_state_set(u_register_t base,
u_register_t top,
rsi_ripas_type ripas,
@@ -162,7 +324,30 @@
/* This function will call the Host to request IPA of the NS shared buffer */
u_register_t rsi_get_ns_buffer(void);
+/* This function will initialize the attestation context */
+u_register_t rsi_attest_token_init(u_register_t challenge_0,
+ u_register_t challenge_1,
+ u_register_t challenge_2,
+ u_register_t challenge_3,
+ u_register_t challenge_4,
+ u_register_t challenge_5,
+ u_register_t challenge_6,
+ u_register_t challenge_7,
+ u_register_t *out_token_upper_bound);
+
+/* This function will retrieve the (or part of) attestation token */
+u_register_t rsi_attest_token_continue(u_register_t buffer_addr,
+ u_register_t offset,
+ u_register_t buffer_size,
+ u_register_t *bytes_copied);
+
/* This function call Host and request to exit Realm with proper exit code */
void rsi_exit_to_host(enum host_call_cmd exit_code);
+/* Function to get Realm configuration. See RSI_REALM_CONFIG */
+u_register_t rsi_realm_config(struct rsi_realm_config *s);
+
+/* Function to enter aux plane. See RSI_PLANE_ENTER */
+u_register_t rsi_plane_enter(u_register_t plane_index, u_register_t run);
+
#endif /* REALM_RSI_H */
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index b58949b..2c1d3a1 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -27,6 +27,9 @@
bool test_realm_multiple_rec_multiple_cpu_cmd(void);
bool test_realm_sme_read_id_registers(void);
bool test_realm_sme_undef_abort(void);
+bool test_realm_sctlr2_ease(void);
+bool test_realm_attestation(void);
+bool test_realm_attestation_fault(void);
#endif /* REALM_TESTS_H */
diff --git a/realm/realm.mk b/realm/realm.mk
index 305c007..f59387c 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -26,12 +26,15 @@
$(addprefix realm/, \
aarch64/realm_entrypoint.S \
aarch64/realm_exceptions.S \
+ realm_attestation.c \
realm_exception_report.c \
realm_debug.c \
+ realm_helpers.c \
realm_interrupt.c \
realm_multiple_rec.c \
realm_pauth.c \
realm_payload_main.c \
+ realm_plane.c \
realm_pmuv3.c \
realm_psci.c \
realm_rsi.c \
@@ -43,6 +46,7 @@
lib/${ARCH}/misc_helpers.S \
lib/smc/${ARCH}/asm_smc.S \
lib/smc/${ARCH}/smc.c \
+ lib/exceptions/${ARCH}/serror.c \
lib/exceptions/${ARCH}/sync.c \
lib/locks/${ARCH}/spinlock.S \
lib/delay/delay.c \
diff --git a/realm/realm_attestation.c b/realm/realm_attestation.c
new file mode 100644
index 0000000..e42484e
--- /dev/null
+++ b/realm/realm_attestation.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <realm_rsi.h>
+
+#include <arch_features.h>
+#include <debug.h>
+#include <realm_def.h>
+#include <sync.h>
+#include <realm_helpers.h>
+
+#define CHALLENGE_SIZE 8
+
+static unsigned char attest_token_buffer[REALM_TOKEN_BUF_SIZE]
+ __aligned(GRANULE_SIZE);
+static uint64_t attest_token_offset;
+
+bool test_realm_attestation(void)
+{
+ u_register_t rsi_ret;
+ u_register_t bytes_copied;
+ u_register_t token_upper_bound;
+ u_register_t challenge[CHALLENGE_SIZE];
+
+ for (unsigned int i = 0U; i < CHALLENGE_SIZE; i++) {
+ challenge[i] = realm_rand64();
+ }
+
+ rsi_ret = rsi_attest_token_init(challenge[0],
+ challenge[1],
+ challenge[2],
+ challenge[3],
+ challenge[4],
+ challenge[5],
+ challenge[6],
+ challenge[7],
+ &token_upper_bound);
+
+ if (rsi_ret != RSI_SUCCESS) {
+ realm_printf("RSI_ATTEST_TOKEN_INIT"
+ " returned with code %lu\n", rsi_ret);
+ return false;
+ }
+
+ if (token_upper_bound > REALM_TOKEN_BUF_SIZE) {
+ realm_printf("Attestation token buffer is not large enough"
+ " to hold the token.\n");
+ return false;
+ }
+
+ do {
+ rsi_ret = rsi_attest_token_continue(
+ (u_register_t)attest_token_buffer,
+ attest_token_offset,
+ REALM_TOKEN_BUF_SIZE,
+ &bytes_copied);
+
+ if ((rsi_ret != RSI_SUCCESS) && (rsi_ret != RSI_INCOMPLETE)) {
+ realm_printf("RSI_ATTEST_TOKEN_CONTINUE"
+ " returned with code %lu\n", rsi_ret);
+ return false;
+ }
+
+ attest_token_offset += bytes_copied;
+
+ } while (rsi_ret != RSI_SUCCESS);
+
+ return true;
+}
+
+bool test_realm_attestation_fault(void)
+{
+ u_register_t rsi_ret;
+ u_register_t bytes_copied;
+
+ /*
+ * This RSI call will fail as RSI_ATTEST_TOKEN_INIT has to be invoked
+ * before calling RSI_ATTEST_TOKEN_CONTINUE.
+ */
+ rsi_ret = rsi_attest_token_continue(
+ (u_register_t)attest_token_buffer,
+ attest_token_offset,
+ REALM_TOKEN_BUF_SIZE,
+ &bytes_copied);
+
+ if ((rsi_ret == RSI_SUCCESS) || (rsi_ret == RSI_INCOMPLETE)) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/realm/realm_helpers.c b/realm/realm_helpers.c
new file mode 100644
index 0000000..6a3c57d
--- /dev/null
+++ b/realm/realm_helpers.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+/* Generate 64-bit random number */
+unsigned long long realm_rand64(void)
+{
+ return ((unsigned long long)rand() << 32) | rand();
+}
+
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 47f9b9f..3339b9a 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -16,11 +16,13 @@
#include "realm_def.h"
#include <realm_rsi.h>
#include <realm_tests.h>
+#include <serror.h>
#include <sync.h>
#include <tftf_lib.h>
static fpu_state_t rl_fpu_state_write;
static fpu_state_t rl_fpu_state_read;
+
/*
* This function reads sleep time in ms from shared buffer and spins PE
* in a loop for that time period.
@@ -176,7 +178,7 @@
/* Causes data abort */
realm_printf("Generate Data Abort\n");
*((volatile uint64_t *)base);
- /* Should not return */
+
return false;
}
@@ -200,6 +202,53 @@
return false;
}
+static bool realm_serror_handler_doublefault(bool *incr_elr_elx)
+{
+ *incr_elr_elx = false;
+
+ if ((read_sctlr2_el1() & SCTLR2_EASE_BIT) != 0UL) {
+ /* The serror exception should have been routed here */
+ *incr_elr_elx = true;
+
+ return true;
+ }
+
+ rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+ /* Should have never get here */
+ return false;
+}
+
+static bool realm_sync_handler_doublefault(void)
+{
+ if ((read_sctlr2_el1() & SCTLR2_EASE_BIT) == 0UL) {
+ /* The sync exception should have been routed here */
+ return true;
+ }
+
+ rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+ /* Should have never get here */
+ return false;
+}
+
+static void test_realm_feat_doublefault2(void)
+{
+ u_register_t ease_bit = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+
+ unregister_custom_sync_exception_handler();
+ register_custom_sync_exception_handler(realm_sync_handler_doublefault);
+ register_custom_serror_handler(realm_serror_handler_doublefault);
+
+ if (ease_bit != 0UL) {
+ write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EASE_BIT);
+ } else {
+ write_sctlr2_el1(read_sctlr2_el1() & ~SCTLR2_EASE_BIT);
+ }
+
+ (void)test_realm_data_access_cmd();
+}
+
/*
* This is the entry function for Realm payload, it first requests the shared buffer
* IPA address from Host using HOST_CALL/RSI, it reads the command to be executed,
@@ -213,7 +262,12 @@
bool test_succeed = false;
register_custom_sync_exception_handler(realm_exception_handler);
+
+ /* No serror handler registered by default */
+ unregister_custom_serror_handler();
+
realm_set_shared_structure((host_shared_data_t *)rsi_get_ns_buffer());
+
if (realm_get_my_shared_structure() != NULL) {
uint8_t cmd = realm_shared_data_get_my_realm_cmd();
@@ -232,6 +286,10 @@
case REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD:
test_succeed = test_realm_multiple_rec_multiple_cpu_cmd();
break;
+ case REALM_FEAT_DOUBLEFAULT2_TEST:
+ test_realm_feat_doublefault2();
+ test_succeed = true;
+ break;
case REALM_INSTR_FETCH_CMD:
test_succeed = test_realm_instr_fetch_cmd();
break;
@@ -310,6 +368,12 @@
case REALM_SME_UNDEF_ABORT:
test_succeed = test_realm_sme_undef_abort();
break;
+ case REALM_ATTESTATION:
+ test_succeed = test_realm_attestation();
+ break;
+ case REALM_ATTESTATION_FAULT:
+ test_succeed = test_realm_attestation_fault();
+ break;
default:
realm_printf("%s() invalid cmd %u\n", __func__, cmd);
break;
diff --git a/realm/realm_plane.c b/realm/realm_plane.c
new file mode 100644
index 0000000..ef1e0ab
--- /dev/null
+++ b/realm/realm_plane.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <stdio.h>
+#include <arch.h>
+#include <arch_features.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <host_realm_helper.h>
+#include <realm_rsi.h>
+#include <sync.h>
+
+bool is_plane0;
+
+void realm_plane_init(void)
+{
+ u_register_t ret;
+
+ ret = rsi_get_version(RSI_ABI_VERSION_VAL);
+ if (ret == RSI_ERROR_STATE) {
+ is_plane0 = false;
+ } else {
+ is_plane0 = true;
+ }
+}
+
+static void restore_plane_context(rsi_plane_run *run)
+{
+ for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
+ run->enter.gprs[i] = run->exit.gprs[i];
+ }
+
+ run->enter.pc = run->exit.elr;
+}
+
+/* return true to re-enter PlaneN, false to exit to P0 */
+static bool handle_plane_exit(u_register_t plane_index,
+ u_register_t perm_index,
+ rsi_plane_run *run)
+{
+ u_register_t ec = EC_BITS(run->exit.esr);
+
+ /* Disallow SMC from Plane N */
+ if (ec == EC_AARCH64_SMC) {
+ restore_plane_context(run);
+ run->enter.gprs[0] = RSI_ERROR_STATE;
+ return true;
+ }
+ return false;
+}
+
+static bool plane_common_init(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t base,
+ rsi_plane_run *run)
+{
+ u_register_t ret;
+
+ memset(run, 0, sizeof(rsi_plane_run));
+ run->enter.pc = base;
+
+ /* Perm init */
+ ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
+ if (ret != RSI_SUCCESS) {
+ ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
+ return false;
+ }
+ return true;
+}
+
+bool realm_plane_enter(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t base,
+ u_register_t flags,
+ rsi_plane_run *run)
+{
+ u_register_t ret;
+ bool ret1;
+
+ ret1 = plane_common_init(plane_index, perm_index, base, run);
+ if (!ret1) {
+ return ret1;
+ }
+
+ run->enter.flags = flags;
+
+ while (ret1) {
+ ret = rsi_plane_enter(plane_index, (u_register_t)run);
+ if (ret != RSI_SUCCESS) {
+ ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
+ return false;
+ }
+
+ VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
+ run->exit.exit_reason,
+ run->exit.esr,
+ run->exit.hpfar,
+ run->exit.far);
+
+ ret1 = handle_plane_exit(plane_index, perm_index, run);
+ }
+ return true;
+}
+
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index b2a49d4..1c6fc8e 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -22,6 +22,11 @@
if (res.ret0 == SMC_UNKNOWN) {
return SMC_UNKNOWN;
}
+
+ if (res.ret0 == RSI_ERROR_STATE) {
+ return RSI_ERROR_STATE;
+ }
+
/* Return lower version */
return res.ret1;
}
@@ -87,3 +92,121 @@
}
return res.ret0;
}
+
+/* This function will initialize the attestation context */
+u_register_t rsi_attest_token_init(u_register_t challenge_0,
+ u_register_t challenge_1,
+ u_register_t challenge_2,
+ u_register_t challenge_3,
+ u_register_t challenge_4,
+ u_register_t challenge_5,
+ u_register_t challenge_6,
+ u_register_t challenge_7,
+ u_register_t *out_token_upper_bound)
+{
+ smc_ret_values_ext res = {};
+
+ tftf_smc_no_retval_x8(&(smc_args_ext) {
+ RSI_ATTEST_TOKEN_INIT,
+ challenge_0,
+ challenge_1,
+ challenge_2,
+ challenge_3,
+ challenge_4,
+ challenge_5,
+ challenge_6,
+ challenge_7
+ },
+ &res);
+
+ if (res.ret0 == RSI_SUCCESS) {
+ *out_token_upper_bound = res.ret1;
+ }
+
+ return res.ret0;
+}
+
+/* This function will retrieve the (or part of) attestation token */
+u_register_t rsi_attest_token_continue(u_register_t buffer_addr,
+ u_register_t offset,
+ u_register_t buffer_size,
+ u_register_t *bytes_copied)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args) {
+ RSI_ATTEST_TOKEN_CONTINUE,
+ buffer_addr,
+ offset,
+ buffer_size
+ });
+
+ if ((res.ret0 == RSI_SUCCESS) || (res.ret0 == RSI_INCOMPLETE)) {
+ *bytes_copied = res.ret1;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_realm_config(struct rsi_realm_config *s)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_REALM_CONFIG, (u_register_t)s});
+ return res.ret0;
+}
+
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t *perm)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_GET_PERM_VALUE, plane_index, perm_index});
+ if (res.ret0 == RSI_SUCCESS) {
+ *perm = res.ret1;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t perm)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_SET_PERM_VALUE, plane_index, perm_index, perm});
+ return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+ u_register_t top,
+ u_register_t perm_index,
+ u_register_t cookie,
+ u_register_t *new_base,
+ u_register_t *response,
+ u_register_t *new_cookie)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_SET_PERM_INDEX, base, top, perm_index, cookie});
+ if (res.ret0 == RSI_SUCCESS) {
+ *new_base = res.ret1;
+ *response = res.ret2;
+ *new_cookie = res.ret3;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_plane_enter(u_register_t plane_index,
+ u_register_t plane_run)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_PLANE_ENTER, plane_index, plane_run});
+ return res.ret0;
+}
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index b608d7b..c15ee4e 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -61,8 +61,9 @@
ffa_ret = ffa_msg_wait();
for (;;) {
- VERBOSE("Woke up with func id: %s\n",
- ffa_func_name(ffa_func_id(ffa_ret)));
+ VERBOSE("Woke up with func:%s id: %x\n",
+ ffa_func_name(ffa_func_id(ffa_ret)),
+ ffa_func_id(ffa_ret));
if (ffa_func_id(ffa_ret) == FFA_ERROR) {
ERROR("Error: %s\n",
@@ -74,7 +75,7 @@
ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64 &&
ffa_func_id(ffa_ret) != FFA_INTERRUPT &&
ffa_func_id(ffa_ret) != FFA_RUN) {
- ERROR("%s(%u) unknown func id %s\n", __func__, vm_id,
+ ERROR("%s(%x) unknown func id %s\n", __func__, vm_id,
ffa_func_name(ffa_func_id(ffa_ret)));
break;
}
@@ -87,10 +88,15 @@
* informational as we're running with virtual
* interrupts unmasked and the interrupt is processed
* by the interrupt handler.
- *
- * Received FFA_RUN in waiting state, the endpoint
- * simply returns by FFA_MSG_WAIT.
*/
+ if (ffa_func_id(ffa_ret) == FFA_RUN) {
+ /*
+ * Received FFA_RUN in waiting state, the
+ * endpoint simply returns by FFA_MSG_WAIT.
+ */
+ VERBOSE("Nothing to do. Exit to NWd\n");
+ }
+
ffa_ret = ffa_msg_wait();
continue;
}
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index fc0ccbd..4e27995 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -92,7 +92,8 @@
lib/extensions/sme/aarch64/sme_helpers.S \
lib/extensions/sme/aarch64/sme2_helpers.S \
lib/extensions/sve/aarch64/sve.c \
- lib/extensions/sve/aarch64/sve_helpers.S
+ lib/extensions/sve/aarch64/sve_helpers.S \
+ lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
endif
ifeq (${ARCH},aarch64)
diff --git a/tftf/tests/doe_tests/doe_helpers.c b/tftf/tests/doe_tests/doe_helpers.c
index 28b6a86..75f63b6 100644
--- a/tftf/tests/doe_tests/doe_helpers.c
+++ b/tftf/tests/doe_tests/doe_helpers.c
@@ -13,14 +13,6 @@
#include <pcie_doe.h>
#include <spdm.h>
-#include <platform_pcie.h>
-
-void pcie_init(void)
-{
- /* Create PCIe table and enumeration */
- pcie_create_info_table();
-}
-
/*
* @brief Returns the BDF Table pointer
*
@@ -33,39 +25,6 @@
return pcie_get_bdf_table();
}
-int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr)
-{
- pcie_device_bdf_table_t *bdf_table_ptr = pcie_get_bdf_table();
- uint32_t num_bdf = bdf_table_ptr->num_entries;
-
- INFO("PCI BDF table entries: %u\n", num_bdf);
-
- /* If no entries in BDF table return error */
- if (num_bdf == 0) {
- ERROR("No BDFs entries found\n");
- return -ENODEV;
- }
-
- INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr);
-
- while (num_bdf-- != 0) {
- uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf;
- uint32_t status, doe_cap_base;
-
- /* Check for DOE capability */
- status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base);
- if (status == PCIE_SUCCESS) {
- INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base);
- *bdf_ptr = bdf;
- *cap_base_ptr = doe_cap_base;
- return 0;
- }
- }
-
- ERROR("No PCIe DOE capability found\n");
- return -ENODEV;
-}
-
int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base)
{
uint32_t response[SPDM_GET_VERS_RESP_LEN], resp_len;
@@ -113,7 +72,7 @@
sizeof(ver_resp->version_number_entry_count));
while (entry_count-- != 0) {
- spdm_version_number_t ver = *ver_ptr++;
+ spdm_version_number_t ver __unused = *ver_ptr++;
INFO("SPDM v%llu.%llu.%llu.%llu\n",
EXTRACT(SPDM_VER_MAJOR, ver),
@@ -128,19 +87,14 @@
{
pcie_doe_disc_req_t request = { 0, };
pcie_doe_disc_resp_t response;
- uint32_t resp_len;
+ size_t resp_len;
int ret;
do {
- ret = pcie_doe_send_req(DOE_HEADER_0, bdf, doe_cap_base,
- (uint32_t *)&request,
- sizeof(pcie_doe_disc_req_t));
- if (ret != 0) {
- return ret;
- }
+ ret = pcie_doe_communicate(DOE_HEADER_0, bdf, doe_cap_base,
+ (void *)&request, sizeof(pcie_doe_disc_req_t),
+ (void *)&response, &resp_len);
- ret = pcie_doe_recv_resp(bdf, doe_cap_base,
- (uint32_t *)&response, &resp_len);
if (ret != 0) {
return ret;
}
diff --git a/tftf/tests/doe_tests/doe_helpers.h b/tftf/tests/doe_tests/doe_helpers.h
index 08137e3..8d48278 100644
--- a/tftf/tests/doe_tests/doe_helpers.h
+++ b/tftf/tests/doe_tests/doe_helpers.h
@@ -8,7 +8,8 @@
#ifndef DOE_HELPERS_H
#define DOE_HELPERS_H
-void pcie_init(void);
+#include <stdint.h>
+
int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr);
int doe_discovery(uint32_t bdf, uint32_t doe_cap_base);
int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base);
diff --git a/tftf/tests/doe_tests/test_doe.c b/tftf/tests/doe_tests/test_doe.c
index 6eb5079..84b30d5 100644
--- a/tftf/tests/doe_tests/test_doe.c
+++ b/tftf/tests/doe_tests/test_doe.c
@@ -5,25 +5,15 @@
*/
#include "doe_helpers.h"
-
+#include <pcie_doe.h>
#include <test_helpers.h>
-#define SKIP_TEST_IF_DOE_NOT_SUPPORTED() \
- do { \
- if (find_doe_device(&bdf, &doe_cap_base) != 0) { \
- tftf_testcase_printf("PCIe DOE not supported\n"); \
- return TEST_RESULT_SKIPPED; \
- } \
- } while (false)
-
test_result_t doe_discovery_test(void)
{
uint32_t bdf, doe_cap_base;
int ret;
- pcie_init();
-
- SKIP_TEST_IF_DOE_NOT_SUPPORTED();
+ SKIP_TEST_IF_DOE_NOT_SUPPORTED(bdf, doe_cap_base);
ret = doe_discovery(bdf, doe_cap_base);
if (ret != 0) {
@@ -38,7 +28,7 @@
uint32_t bdf, doe_cap_base;
int ret;
- SKIP_TEST_IF_DOE_NOT_SUPPORTED();
+ SKIP_TEST_IF_DOE_NOT_SUPPORTED(bdf, doe_cap_base);
ret = get_spdm_version(bdf, doe_cap_base);
if (ret != 0) {
diff --git a/tftf/tests/extensions/amu/test_amu.c b/tftf/tests/extensions/amu/test_amu.c
index 21305a7..0cc4395 100644
--- a/tftf/tests/extensions/amu/test_amu.c
+++ b/tftf/tests/extensions/amu/test_amu.c
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <amu.h>
#include <arch.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
diff --git a/tftf/tests/extensions/d128/test_d128.c b/tftf/tests/extensions/d128/test_d128.c
new file mode 100644
index 0000000..1e8df0c
--- /dev/null
+++ b/tftf/tests/extensions/d128/test_d128.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/extensions/sysreg128.h>
+#include <test_helpers.h>
+
+#include "./test_d128.h"
+
+/*
+ * @brief Test FEAT_D128 feature support when the extension is enabled.
+ *
+ * The test ensures that access to common system registers PAR_EL1, TTBR0_EL1, TTBR1_EL1,
+ * TTBR0_EL2, VTTBR_EL2 and the VHE register TTBR1_EL2 do not trap to EL3.
+ *
+ * Additonally this test verifies that EL1 registers are properly context switched by
+ * making dummy SMC call to TSPD (running at S-EL1).
+ *
+ * TODO: EL2 registers context switching.
+ *
+ * @return test_result_t
+ */
+test_result_t test_d128_support(void)
+{
+#ifdef __aarch64__
+ SKIP_TEST_IF_D128_NOT_SUPPORTED();
+ SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+ smc_args tsp_svc_params;
+
+ /* Access 128 bit variant of system registers */
+ read128_par_el1();
+ read128_ttbr0_el1();
+ read128_ttbr1_el1();
+ read128_ttbr0_el2();
+ read128_ttbr1_el2();
+ if (is_armv8_1_vhe_present()) {
+ read128_vttbr_el2();
+ }
+
+ /*
+ * Check that EL1 registers are properly contexted by EL3. Write to the registers
+ * make dummy SMC call TSP and ensure that values are prorperly contexted.
+ * NOTE: Ideal way would be to modify these registers in TSP in SMC handler
+ */
+ write128_par_el1(PAR_EL1_MASK_FULL);
+ write128_ttbr0_el1(TTBR_REG_MASK_FULL);
+ write128_ttbr1_el1(TTBR_REG_MASK_FULL);
+
+ tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+ tsp_svc_params.arg1 = 4;
+ tsp_svc_params.arg2 = 6;
+ tftf_smc(&tsp_svc_params);
+
+ if ((read128_par_el1() != PAR_EL1_MASK_FULL) ||
+ (read128_ttbr0_el1() != TTBR_REG_MASK_FULL) ||
+ (read128_ttbr1_el1() != TTBR_REG_MASK_FULL)) {
+ NOTICE("Unexpected value of registers after context switch\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+#else
+ SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/d128/test_d128.h b/tftf/tests/extensions/d128/test_d128.h
new file mode 100644
index 0000000..2e40753
--- /dev/null
+++ b/tftf/tests/extensions/d128/test_d128.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_D128_H
+#define TEST_D128_H
+
+/* Create Mask setting all used bits except PA */
+#define PAR_EL1_MASK_HIGH 0x0000000000000001
+#define PAR_EL1_MASK_LOW 0xFF00000000000F81
+#define PAR_EL1_MASK_FULL (((uint128_t)PAR_EL1_MASK_HIGH) << 64U | PAR_EL1_MASK_LOW)
+
+/* Masks created by setting all used bits */
+#define TTBR_REG_MASK_HIGH 0x0000000000FF0000
+#define TTBR_REG_MASK_LOW 0xFFFFFFFFFFFFFFE7
+#define TTBR_REG_MASK_FULL (((uint128_t)TTBR_REG_MASK_HIGH) << 64U | TTBR_REG_MASK_LOW)
+
+#endif /* TEST_D128_H */
diff --git a/tftf/tests/extensions/fpmr/test_fpmr.c b/tftf/tests/extensions/fpmr/test_fpmr.c
new file mode 100644
index 0000000..1e02780
--- /dev/null
+++ b/tftf/tests/extensions/fpmr/test_fpmr.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <debug.h>
+#include <arch_helpers.h>
+
+test_result_t test_fpmr_enabled(void)
+{
+ SKIP_TEST_IF_AARCH32();
+
+#if __aarch64__
+ SKIP_TEST_IF_FPMR_NOT_SUPPORTED();
+
+ read_fpmr();
+#endif
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/extensions/sctlr2/test_sctlr2.c b/tftf/tests/extensions/sctlr2/test_sctlr2.c
new file mode 100644
index 0000000..704d19d
--- /dev/null
+++ b/tftf/tests/extensions/sctlr2/test_sctlr2.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+
+/*
+ * @brief Test FEAT_SCTLR2 support when the extension is enabled.
+ *
+ * Ensure that reading of SCTLR2_EL1 and SCTLR2_EL2 system registers does not
+ * trap to EL3. Also, verify that SCTLR2_EL1 register value is preserved
+ * correctly during world switch to TSP.
+ *
+ * TODO: Test context switching of SCTLR2_EL2
+ *
+ * @return test_result_t
+ */
+test_result_t test_sctlr2_support(void)
+{
+#ifdef __aarch64__
+ SKIP_TEST_IF_SCTLR2_NOT_SUPPORTED();
+ SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+ smc_args tsp_svc_params;
+
+ /* Access the registers */
+ read_sctlr2_el1();
+ read_sctlr2_el2();
+
+ /* Check that SCTLR2_EL1 is properly contexted by EL3. Write to the registers
+ * make dummy SMC call TSP and ensure that values are prorperly contexted.
+ * Set EnIDCP128_BIT which is guaranteed to be present if SCTLR2 is present.
+ */
+ write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EnIDCP128_BIT);
+
+ tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+ tsp_svc_params.arg1 = 4;
+ tsp_svc_params.arg2 = 6;
+ tftf_smc(&tsp_svc_params);
+
+ if ((read_sctlr2_el1() & SCTLR2_EnIDCP128_BIT) == 0) {
+ ERROR("SCTLR2_EL1 unexpected value after context switch\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+#else
+ SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/the/test_the.c b/tftf/tests/extensions/the/test_the.c
new file mode 100644
index 0000000..b56be93
--- /dev/null
+++ b/tftf/tests/extensions/the/test_the.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/extensions/sysreg128.h>
+#include <test_helpers.h>
+
+#include "./test_the.h"
+
+/*
+ * @brief Test FEAT_THE support when the extension is enabled.
+ *
+ * Write to the RCWMASK_EL1 and RCWSMASK_EL1 system registers with
+ * a mask of allowed bits in 128-bit mode, if FEAT_D128 is supported,
+ * otherwise in 64-bit mode, perform a dummy SMC call, then read the
+ * registers back.
+ *
+ * The test ensures that accesses to these registers do not trap
+ * to EL3 as well as that their values are preserved correctly.
+ *
+ * @return test_result_t
+ */
+test_result_t test_the_support(void)
+{
+#ifdef __aarch64__
+ SKIP_TEST_IF_THE_NOT_SUPPORTED();
+ SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+ smc_args tsp_svc_params;
+ /* Standard SMC to ADD two numbers */
+ tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+ tsp_svc_params.arg1 = 4;
+ tsp_svc_params.arg2 = 6;
+
+ if (is_feat_d128_supported()) {
+ uint128_t reg_read;
+
+ write128_rcwmask_el1(RCWMASK_EL1_MASK_FULL);
+ write128_rcwsmask_el1(RCWSMASK_EL1_MASK_FULL);
+ tftf_smc(&tsp_svc_params);
+
+ reg_read = read128_rcwmask_el1();
+ if (reg_read != RCWMASK_EL1_MASK_FULL) {
+ NOTICE("RCWMASK_EL1 unexpected value after context switch: 0x%llx:0x%llx\n",
+ (uint64_t)(reg_read >> 64U), (uint64_t)reg_read);
+ return TEST_RESULT_FAIL;
+ }
+
+ reg_read = read128_rcwsmask_el1();
+ if (reg_read != RCWSMASK_EL1_MASK_FULL) {
+ NOTICE("RCWSMASK_EL1 unexpected value after context switch: 0x%llx:0x%llx\n",
+ (uint64_t)(reg_read >> 64U), (uint64_t)reg_read);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+ }
+
+ uint64_t reg_read;
+
+ write_rcwmask_el1(RCWMASK_EL1_MASK_LOW);
+ write_rcwsmask_el1(RCWSMASK_EL1_MASK_LOW);
+ tftf_smc(&tsp_svc_params);
+
+ reg_read = read_rcwmask_el1();
+ if (reg_read != RCWMASK_EL1_MASK_LOW) {
+ NOTICE("RCWMASK_EL1 unexpected value after context switch: 0x%llx\n", reg_read);
+ return TEST_RESULT_FAIL;
+ }
+
+ reg_read = read_rcwsmask_el1();
+ if (reg_read != RCWSMASK_EL1_MASK_LOW) {
+ NOTICE("RCWSMASK_EL1 unexpected value after context switch: 0x%llx\n", reg_read);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+#else
+ SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/the/test_the.h b/tftf/tests/extensions/the/test_the.h
new file mode 100644
index 0000000..92a3768
--- /dev/null
+++ b/tftf/tests/extensions/the/test_the.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_THE_H
+#define TEST_THE_H
+
+#define RCWMASK_EL1_MASK_HIGH 0x807BE01FF8000000
+#define RCWMASK_EL1_MASK_LOW 0xFFEC00000003FFFE
+#define RCWMASK_EL1_MASK_FULL \
+ (((uint128_t)RCWMASK_EL1_MASK_HIGH) << 64U | RCWMASK_EL1_MASK_LOW)
+
+#define RCWSMASK_EL1_MASK_HIGH 0x807BE01FF8000000
+#define RCWSMASK_EL1_MASK_LOW 0xFFFC00000003FFFE
+#define RCWSMASK_EL1_MASK_FULL \
+ (((uint128_t)RCWSMASK_EL1_MASK_HIGH) << 64U | RCWSMASK_EL1_MASK_LOW)
+
+#endif /* TEST_THE_H */
diff --git a/tftf/tests/misc_tests/test_ras_kfh.c b/tftf/tests/misc_tests/test_ras_kfh.c
index b38d6c4..f92e048 100644
--- a/tftf/tests/misc_tests/test_ras_kfh.c
+++ b/tftf/tests/misc_tests/test_ras_kfh.c
@@ -13,9 +13,10 @@
static volatile uint64_t serror_triggered;
extern void inject_unrecoverable_ras_error(void);
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
{
serror_triggered = 1;
+ *incr_elr_elx = false;
return true;
}
diff --git a/tftf/tests/misc_tests/test_ras_kfh_reflect.c b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
index d24fc47..eb93d72 100644
--- a/tftf/tests/misc_tests/test_ras_kfh_reflect.c
+++ b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
@@ -33,9 +33,10 @@
* One test each to verify reflection in sync and async exception.
*
*/
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
{
serror_triggered = 1;
+ *incr_elr_elx = false;
tftf_testcase_printf("SError event received.\n");
return true;
}
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
index 93abf15..7babcd1 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,7 @@
#include <psci.h>
#include <smccc.h>
#include <string.h>
+#include <test_helpers.h>
#include <tftf_lib.h>
#ifdef __aarch64__
@@ -69,21 +70,11 @@
{
smc_args args;
smc_ret_values ret;
- int32_t expected_ver;
unsigned int my_midr, midr_mask;
int wa_required;
size_t i;
- /* Check if SMCCC version is at least v1.1 */
- expected_ver = MAKE_SMCCC_VERSION(1, 1);
- memset(&args, 0, sizeof(args));
- args.fid = SMCCC_VERSION;
- ret = tftf_smc(&args);
- if ((int32_t)ret.ret0 < expected_ver) {
- tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
- (int)ret.ret0);
- return TEST_RESULT_SKIPPED;
- }
+ SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
/* Check if SMCCC_ARCH_WORKAROUND_1 is required or not */
memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
index 1557e4f..b5aa636 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <psci.h>
#include <smccc.h>
#include <string.h>
+#include <test_helpers.h>
#include <tftf_lib.h>
#ifdef __aarch64__
@@ -40,20 +41,10 @@
{
smc_args args;
smc_ret_values ret;
- int32_t expected_ver;
unsigned int my_midr, midr_mask;
size_t i;
- /* Check if SMCCC version is at least v1.1 */
- expected_ver = MAKE_SMCCC_VERSION(1, 1);
- memset(&args, 0, sizeof(args));
- args.fid = SMCCC_VERSION;
- ret = tftf_smc(&args);
- if ((int32_t)ret.ret0 < expected_ver) {
- tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
- (int)ret.ret0);
- return TEST_RESULT_SKIPPED;
- }
+ SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
/* Check if SMCCC_ARCH_WORKAROUND_2 is required or not */
memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
index ebf40a5..77c50cc 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <psci.h>
#include <smccc.h>
#include <string.h>
+#include <test_helpers.h>
#include <tftf_lib.h>
#ifdef __aarch64__
@@ -65,21 +66,11 @@
{
smc_args args;
smc_ret_values ret;
- int32_t expected_ver;
unsigned int my_midr, midr_mask;
int wa_required;
size_t i;
- /* Check if SMCCC version is at least v1.1 */
- expected_ver = MAKE_SMCCC_VERSION(1, 1);
- memset(&args, 0, sizeof(args));
- args.fid = SMCCC_VERSION;
- ret = tftf_smc(&args);
- if ((int32_t)ret.ret0 < expected_ver) {
- tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
- (int)ret.ret0);
- return TEST_RESULT_SKIPPED;
- }
+ SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
/* Check if SMCCC_ARCH_WORKAROUND_3 is required or not */
memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
new file mode 100644
index 0000000..1418ca1
--- /dev/null
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tftf.h>
+
+#include <arm_arch_svc.h>
+#include <smccc.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+static inline u_register_t get_feature_for_reg(u_register_t reg)
+{
+ smc_args args = {0};
+ smc_ret_values ret;
+
+ args.fid = SMCCC_ARCH_FEATURE_AVAILABILITY | (SMC_64 << FUNCID_CC_SHIFT);
+ args.arg1 = reg;
+ ret = tftf_smc(&args);
+
+ /* APi is pretty simple, support was already checked. This is simpler */
+ assert((int)ret.ret0 == SMC_ARCH_CALL_SUCCESS);
+ return ret.ret1;
+}
+
+static inline bool always_present(void)
+{
+ return true;
+}
+
+/*
+ * Checks that the bit's matches the feature's presence
+ * feat_func should be is_feat_xyz_present(), but get_feat_xyz_support() will
+ * also work.
+ */
+#define CHECK_BIT_SET(feat_func, bit) \
+ do { \
+ if (!!feat_func() != !!(reg & bit)) { \
+ tftf_testcase_printf( \
+ #feat_func " says feature is %ssupported but " \
+ #bit " was %sset!\n", feat_func() ? "" : "not ",\
+ (reg & bit) ? "" : "not "); \
+ bad = true; \
+ } \
+ reg &= ~bit; \
+ } while (0)
+
+/* when support for a new feature is added, we want this test to be
+ * updated. Fail the test so it's noticed. */
+#define CHECK_NO_BITS_SET(reg_name) \
+ do { \
+ if (reg != 0) { \
+ tftf_testcase_printf( \
+ #reg_name " still has values set: 0x%lx. " \
+ "Test needs to be updated\n", reg); \
+ bad = true; \
+ } \
+ } while (0)
+
+test_result_t test_smccc_arch_feature_availability(void)
+{
+ SKIP_TEST_IF_AARCH32();
+#ifdef __aarch64__
+
+ SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
+ SKIP_TEST_IF_SMCCC_FUNC_NOT_SUPPORTED(SMCCC_ARCH_FEATURE_AVAILABILITY);
+
+ u_register_t reg;
+ bool bad = false;
+
+ reg = get_feature_for_reg(SCR_EL3_OPCODE);
+ CHECK_BIT_SET(is_armv8_9_fgt2_present, SCR_FGTEN2_BIT);
+ CHECK_BIT_SET(is_feat_fpmr_present, SCR_EnFPM_BIT);
+ CHECK_BIT_SET(is_feat_d128_supported, SCR_D128En_BIT);
+ CHECK_BIT_SET(is_feat_s1pie_present, SCR_PIEN_BIT);
+ CHECK_BIT_SET(is_feat_sctlr2_supported, SCR_SCTLR2En_BIT);
+ CHECK_BIT_SET(is_feat_tcr2_supported, SCR_TCR2EN_BIT);
+ CHECK_BIT_SET(is_feat_the_supported, SCR_RCWMASKEn_BIT);
+ CHECK_BIT_SET(is_feat_sme_supported, SCR_ENTP2_BIT);
+ CHECK_BIT_SET(is_feat_rng_trap_present, SCR_TRNDR_BIT);
+ CHECK_BIT_SET(is_feat_gcs_present, SCR_GCSEn_BIT);
+ CHECK_BIT_SET(get_feat_hcx_support, SCR_HXEn_BIT);
+ CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_ADEn_BIT);
+ CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_EnAS0_BIT);
+ CHECK_BIT_SET(is_feat_amuv1p1_present, SCR_AMVOFFEN_BIT);
+ CHECK_BIT_SET(get_armv8_6_ecv_support, SCR_ECVEN_BIT);
+ CHECK_BIT_SET(is_armv8_6_fgt_present, SCR_FGTEN_BIT);
+ CHECK_BIT_SET(is_feat_mte2_present, SCR_ATA_BIT);
+ CHECK_BIT_SET(is_feat_csv2_2_present, SCR_EnSCXT_BIT);
+ CHECK_BIT_SET(is_armv8_3_pauth_present, SCR_APK_BIT);
+ CHECK_BIT_SET(is_feat_ras_present, SCR_TERR_BIT);
+ CHECK_NO_BITS_SET(SCR_EL3);
+
+ reg = get_feature_for_reg(CPTR_EL3_OPCODE);
+ CHECK_BIT_SET(always_present, CPTR_EL3_TCPAC_BIT);
+ CHECK_BIT_SET(is_feat_amuv1_present, CPTR_EL3_TAM_BIT);
+ CHECK_BIT_SET(get_armv8_0_sys_reg_trace_support, CPTR_EL3_TTA_BIT);
+ CHECK_BIT_SET(is_feat_sme_supported, CPTR_EL3_ESM_BIT);
+ CHECK_BIT_SET(always_present, CPTR_EL3_TFP_BIT);
+ CHECK_BIT_SET(is_armv8_2_sve_present, CPTR_EL3_EZ_BIT);
+ CHECK_NO_BITS_SET(CPTR_EL3);
+
+ reg = get_feature_for_reg(MDCR_EL3_OPCODE);
+ CHECK_BIT_SET(get_feat_brbe_support, MDCR_SBRBE(1));
+ CHECK_BIT_SET(is_armv8_6_fgt_present, MDCR_TDCC_BIT);
+ CHECK_BIT_SET(is_feat_trbe_present, MDCR_NSTB(1));
+ CHECK_BIT_SET(get_armv8_4_trf_support, MDCR_TTRF_BIT);
+ CHECK_BIT_SET(is_feat_spe_supported, MDCR_NSPB(1));
+ CHECK_BIT_SET(is_feat_doublelock_present, MDCR_TDOSA_BIT);
+ CHECK_BIT_SET(always_present, MDCR_TDA_BIT);
+ CHECK_BIT_SET(get_feat_pmuv3_supported, MDCR_TPM_BIT);
+ CHECK_NO_BITS_SET(MDCR_EL3);
+
+ reg = get_feature_for_reg(MPAM3_EL3_OPCODE);
+ CHECK_BIT_SET(is_feat_mpam_supported, MPAM3_EL3_TRAPLOWER_BIT);
+ CHECK_NO_BITS_SET(MPAM3_EL3);
+
+ if (bad)
+ return TEST_RESULT_FAIL;
+
+ return TEST_RESULT_SUCCESS;
+#endif /* __aarch64__ */
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c b/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c
new file mode 100644
index 0000000..80834fa
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef MBEDTLS_CONFIG_FILE
+#include <mbedtls/asn1.h>
+#include <mbedtls/bignum.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/memory_buffer_alloc.h>
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#endif
+
+#include <host_crypto_utils.h>
+#include <test_helpers.h>
+
+#ifdef MBEDTLS_CONFIG_FILE
+#define HOST_MBEDTLS_HEAP_SIZE (2U * SZ_4K)
+static unsigned char host_mbedtls_heap[HOST_MBEDTLS_HEAP_SIZE];
+
+static int host_get_leaf_cert_from_cert_chain(uint8_t *cert_chain,
+ size_t cert_chain_len,
+ uint8_t **leaf_cert,
+ size_t *leaf_cert_len)
+{
+ size_t asn1_len;
+ unsigned char *tag_ptr;
+ uint8_t *cert_chain_end;
+ uint8_t *cur_cert;
+ size_t cur_cert_len;
+ int cur_cert_idx;
+ int rc;
+
+ cur_cert = cert_chain;
+ cur_cert_idx = -1;
+ cert_chain_end = cert_chain + cert_chain_len;
+
+ /* Get leaf certificate from cert_chain */
+ while (true) {
+ tag_ptr = cur_cert;
+ rc = mbedtls_asn1_get_tag(&tag_ptr, cert_chain_end, &asn1_len,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE);
+ if (rc != 0) {
+ break;
+ }
+
+ cur_cert_len = asn1_len + (tag_ptr - cur_cert);
+ if (cur_cert + cur_cert_len > cert_chain_end) {
+ cur_cert_idx = -1;
+ break;
+ }
+
+ cur_cert = cur_cert + cur_cert_len;
+ cur_cert_idx++;
+ }
+
+ if (cur_cert_idx == -1) {
+ return -1;
+ }
+
+ *leaf_cert = cur_cert - cur_cert_len;
+ *leaf_cert_len = cur_cert_len;
+ INFO("leaf_cert_len: 0x%lx\n", *leaf_cert_len);
+
+ return 0;
+}
+
+/*
+ * @In:
+ * cert_chain - Certificate chain
+ * cert_chain_len - Length of certificate
+ * public_key_len - Max length of 'public_key' buffer
+ * metadata_len - Max length of 'metadata' buffer
+ *
+ * On success below variables are set:
+ * @Out:
+ * public_key - Public key content
+ * public_key_len - length of 'public_key'
+ * metadata - Public key metadata content
+ * metadata_len - length of 'metadata' if metadata exists, else set to 0
+ * public_key_algo - Public key algorithm
+ */
+static int _host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+ size_t cert_chain_len,
+ void *public_key,
+ size_t *public_key_len,
+ void *public_key_metadata,
+ size_t *public_key_metadata_len,
+ uint8_t *public_key_algo)
+{
+ uint8_t *leaf_cert;
+ size_t leaf_cert_len;
+ mbedtls_x509_crt crt;
+ mbedtls_pk_type_t pk_type;
+ int rc;
+
+ /* Get leaf cert and its length */
+ rc = host_get_leaf_cert_from_cert_chain(cert_chain, cert_chain_len,
+ &leaf_cert, &leaf_cert_len);
+ if (rc != 0) {
+ return -1;
+ }
+
+ /* Get public key from leaf certificate */
+ mbedtls_x509_crt_init(&crt);
+
+ if (mbedtls_x509_crt_parse_der(&crt, leaf_cert, leaf_cert_len) != 0) {
+ return -1;
+ }
+
+ pk_type = mbedtls_pk_get_type(&crt.pk);
+ if (pk_type != MBEDTLS_PK_ECKEY && pk_type != MBEDTLS_PK_RSA) {
+ rc = -1;
+ goto out_crt_free;
+ }
+
+ if (pk_type == MBEDTLS_PK_ECKEY) {
+ mbedtls_ecp_keypair *ecp;
+ mbedtls_ecp_group grp;
+ mbedtls_ecp_point pt;
+
+ ecp = mbedtls_pk_ec(crt.pk);
+ mbedtls_ecp_group_init(&grp);
+ mbedtls_ecp_point_init(&pt);
+ rc = mbedtls_ecp_export(ecp, &grp, NULL, &pt);
+
+ if (rc != 0 || (grp.id != MBEDTLS_ECP_DP_SECP256R1 &&
+ grp.id != MBEDTLS_ECP_DP_SECP384R1)) {
+ mbedtls_ecp_point_free(&pt);
+ mbedtls_ecp_group_free(&grp);
+ rc = -1;
+ goto out_crt_free;
+ }
+
+ rc = mbedtls_ecp_point_write_binary(&grp, &pt,
+ MBEDTLS_ECP_PF_UNCOMPRESSED,
+ public_key_len, public_key,
+ MBEDTLS_ECP_MAX_PT_LEN);
+
+ if (rc == 0) {
+ if (grp.id == MBEDTLS_ECP_DP_SECP256R1) {
+ *public_key_algo =
+ PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256;
+ } else {
+ *public_key_algo =
+ PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384;
+ }
+
+ /* No metadata for PK_ECKEY type */
+ *public_key_metadata_len = 0;
+ }
+
+ mbedtls_ecp_point_free(&pt);
+ mbedtls_ecp_group_free(&grp);
+ } else {
+ mbedtls_rsa_context *rsa;
+ mbedtls_mpi N;
+ mbedtls_mpi E;
+ size_t N_sz, E_sz;
+
+ rsa = mbedtls_pk_rsa(crt.pk);
+ mbedtls_mpi_init(&N);
+ mbedtls_mpi_init(&E);
+
+ rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E);
+ N_sz = mbedtls_mpi_size(&N);
+ E_sz = mbedtls_mpi_size(&E);
+ INFO("RSA public key len: %ld, metadata len:%ld\n", N_sz, E_sz);
+
+ /* Supported ALGO type RSASSA_3072 (384 bytes) */
+ if (rc == 0 && N_sz == 384) {
+ rc = mbedtls_mpi_write_binary(&N, public_key, N_sz);
+ rc |= mbedtls_mpi_write_binary(&E, public_key_metadata,
+ E_sz);
+ if (rc == 0) {
+ *public_key_algo = PUBLIC_KEY_ALGO_RSASSA_3072;
+ *public_key_len = N_sz;
+ *public_key_metadata_len = E_sz;
+ }
+ } else {
+ rc = -1;
+ }
+
+ mbedtls_mpi_free(&N);
+ mbedtls_mpi_free(&E);
+ }
+
+out_crt_free:
+ mbedtls_x509_crt_free(&crt);
+
+ return rc;
+}
+#endif
+
+int host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+ size_t cert_chain_len,
+ void *public_key,
+ size_t *public_key_len,
+ void *public_key_metadata,
+ size_t *public_key_metadata_len,
+ uint8_t *public_key_algo)
+{
+ int rc;
+
+#ifdef MBEDTLS_CONFIG_FILE
+ mbedtls_memory_buffer_alloc_init(host_mbedtls_heap,
+ sizeof(host_mbedtls_heap));
+
+ rc = _host_get_public_key_from_cert_chain(cert_chain, cert_chain_len,
+ public_key, public_key_len,
+ public_key_metadata,
+ public_key_metadata_len,
+ public_key_algo);
+#else
+ ERROR("MbedTLS not found.\n");
+ rc = -1;
+#endif
+ return rc;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
index 9c7ceba..3a4121b 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
@@ -34,7 +34,11 @@
RMI_EXIT(PSCI),
RMI_EXIT(RIPAS_CHANGE),
RMI_EXIT(HOST_CALL),
- RMI_EXIT(SERROR)
+ RMI_EXIT(SERROR),
+ RMI_EXIT(IO),
+ RMI_EXIT(RTT_REQUEST),
+ RMI_EXIT(S2AP_CHANGE),
+ RMI_EXIT(VDEV_REQUEST)
};
/*
@@ -135,7 +139,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
int8_t value;
@@ -169,6 +174,21 @@
EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag));
}
+ realm_ptr->rtt_tree_single = false;
+ if (num_aux_planes > 0U) {
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_PLANE_RTT, feature_flag) >=
+ RMI_PLANE_RTT_SINGLE) {
+ ERROR("S2POE not suported on TFTF\n");
+ return false;
+ }
+
+ /*
+ * @TODO: once S2POE is supported, this should be a parameter
+ * so it can be tested with and without support for auxiliary
+ * tables.
+ */
+ }
+
/* Disable PMU if not required */
if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
@@ -246,6 +266,12 @@
realm_ptr->start_level = sl;
+ if (num_aux_planes > MAX_AUX_PLANE_COUNT) {
+ ERROR("Invalid aux plane count\n");
+ return false;
+ }
+ realm_ptr->num_aux_planes = num_aux_planes;
+
/* Create Realm */
if (host_realm_create(realm_ptr) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_create");
@@ -283,7 +309,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
bool ret;
@@ -292,7 +319,8 @@
feature_flag,
sl,
rec_flag,
- rec_count);
+ rec_count,
+ num_aux_planes);
if (!ret) {
goto destroy_realm;
} else {
@@ -323,7 +351,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
bool ret;
@@ -333,7 +362,8 @@
feature_flag,
sl,
rec_flag,
- rec_count);
+ rec_count,
+ num_aux_planes);
if (!ret) {
goto destroy_realm;
} else {
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
index fdb1d4a..5c851a7 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
@@ -76,7 +76,7 @@
* must be preserved unless they contain result,
* as specified in the function definition.
*/
- if (regs[0] != RMI_RTT_READ_ENTRY) {
+ if ((regs[0] != RMI_RTT_READ_ENTRY) && (regs[0] != RMI_RTT_AUX_MAP_PROTECTED)) {
CHECK_RET(4);
}
@@ -184,6 +184,16 @@
rd, rtt, map_addr, (u_register_t)level}, 5U).ret0;
}
+static inline u_register_t host_rmi_rtt_aux_create(u_register_t rd,
+ u_register_t rtt,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index)
+{
+ return host_rmi_handler(&(smc_args) {RMI_RTT_AUX_CREATE,
+ rd, rtt, map_addr, (u_register_t)level, tree_index}, 6U).ret0;
+}
+
u_register_t host_rmi_rtt_destroy(u_register_t rd,
u_register_t map_addr,
long level,
@@ -200,6 +210,24 @@
return rets.ret0;
}
+u_register_t host_rmi_rtt_aux_destroy(u_register_t rd,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index,
+ u_register_t *rtt,
+ u_register_t *top)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_DESTROY,
+ rd, map_addr, (u_register_t)level,
+ tree_index,
+ (u_register_t)&rets}, 6U);
+ *rtt = rets.ret1;
+ *top = rets.ret2;
+ return rets.ret0;
+}
+
u_register_t host_rmi_features(u_register_t index, u_register_t *features)
{
smc_ret_values rets;
@@ -243,6 +271,22 @@
return rets.ret0;
}
+static inline u_register_t host_rmi_rtt_aux_fold(u_register_t rd,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index,
+ u_register_t *pa)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_FOLD,
+ rd, map_addr, (u_register_t)level,
+ tree_index,
+ (u_register_t)&rets}, 6U);
+ *pa = rets.ret1;
+ return rets.ret0;
+}
+
static inline u_register_t host_rmi_rec_aux_count(u_register_t rd,
u_register_t *aux_count)
{
@@ -276,6 +320,42 @@
rd, map_addr, (u_register_t)level, ns_pa}, 5U).ret0;
}
+u_register_t host_rmi_rtt_aux_map_unprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_UNPROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *fail_index = rets.ret1;
+ *level_pri = rets.ret2;
+ *state = rets.ret3;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_map_protected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state,
+ u_register_t *ripas)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_PROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *fail_index = rets.ret1;
+ *level_pri = rets.ret2;
+ *state = rets.ret3;
+ *ripas = rets.ret4;
+ return rets.ret0;
+}
+
u_register_t host_rmi_rtt_readentry(u_register_t rd,
u_register_t map_addr,
long level,
@@ -305,6 +385,36 @@
return rets.ret0;
}
+u_register_t host_rmi_rtt_aux_unmap_unprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_UNPROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *top = rets.ret1;
+ *level = rets.ret2;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_unmap_protected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_PROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *top = rets.ret1;
+ *level = rets.ret2;
+ return rets.ret0;
+}
+
bool host_ipa_is_ns(u_register_t addr, u_register_t rmm_feat_reg0)
{
return (addr >> (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, rmm_feat_reg0) - 1UL) == 1UL);
@@ -351,6 +461,42 @@
return REALM_SUCCESS;
}
+static u_register_t host_realm_create_rtt_aux_levels(struct realm *realm,
+ u_register_t map_addr,
+ long level, long max_level,
+ u_register_t tree_index)
+{
+ u_register_t rtt, ret, ipa_align;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ while (level++ < max_level) {
+ rtt = (u_register_t)page_alloc(PAGE_SIZE);
+ if (rtt == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for rtt\n");
+ return REALM_ERROR;
+ } else {
+ ret = host_rmi_granule_delegate(rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_delegate", rtt, ret);
+ return REALM_ERROR;
+ }
+ }
+ ipa_align = ALIGN_DOWN(map_addr, RTT_MAP_SIZE(level - 1));
+ ret = host_rmi_rtt_aux_create(realm->rd, rtt, ipa_align, (u_register_t)level,
+ tree_index);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+ "host_realm_rtt_aux_create", rtt, ret);
+ host_rmi_granule_undelegate(rtt);
+ page_free(rtt);
+ return REALM_ERROR;
+ }
+ }
+
+ return REALM_SUCCESS;
+}
+
u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr,
long level)
{
@@ -379,6 +525,93 @@
}
+u_register_t host_realm_aux_map_protected_data(struct realm *realm,
+ u_register_t target_pa,
+ u_register_t map_size,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state,
+ u_register_t *ripas)
+{
+ u_register_t ret, top;
+ long level;
+ int8_t ulevel;
+ u_register_t size = 0UL;
+ u_register_t map_addr = target_pa;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_map_protected(realm->rd, map_addr, tree_index,
+ fail_index, level_pri, state, ripas);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT_AUX) {
+ /* Create missing RTTs till L3 and retry */
+ ulevel = RMI_RETURN_INDEX(ret);
+ level = (long)ulevel;
+
+ ret = host_realm_create_rtt_aux_levels(realm, map_addr,
+ (u_register_t)level,
+ 3U, tree_index);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx line=%u\n",
+ "host_realm_create_rtt_aux_levels",
+ ret, __LINE__);
+ goto err;
+ }
+ ret = host_rmi_rtt_aux_map_protected(realm->rd, target_pa, tree_index,
+ fail_index, level_pri, state, ripas);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx\n",
+ "host_rmi_data_create", ret);
+ goto err;
+ }
+ } else if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_rtt_aux_map_protected failed ret = 0x%lx", ret);
+ goto err;
+ }
+ map_addr += PAGE_SIZE;
+ }
+ return REALM_SUCCESS;
+
+err:
+ while (size >= PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_unmap_protected(realm->rd, target_pa, tree_index,
+ &top, (u_register_t *)&level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+ "host_rmi_rtt_aux_unmap_protected", map_addr, ret);
+ }
+ size -= PAGE_SIZE;
+ map_addr -= PAGE_SIZE;
+ }
+ return REALM_ERROR;
+}
+
+u_register_t host_realm_aux_unmap_protected_data(struct realm *realm,
+ u_register_t target_ipa,
+ u_register_t map_size,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ u_register_t ret, size = 0UL, map_addr = target_ipa;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_unmap_protected(realm->rd, map_addr, tree_index,
+ top, level);
+ if (ret != RMI_SUCCESS) {
+ WARN("%s() failed, ret=0x%lx line=%u\n",
+ "host_rmi_rtt_aux_unmap_protected",
+ ret, __LINE__);
+ return REALM_ERROR;
+ }
+ map_addr += PAGE_SIZE;
+ }
+ return REALM_SUCCESS;
+}
+
u_register_t host_realm_delegate_map_protected_data(bool unknown,
struct realm *realm,
u_register_t target_pa,
@@ -392,7 +625,7 @@
u_register_t phys = target_pa;
u_register_t map_addr = target_pa;
- if (!IS_ALIGNED(map_addr, map_size)) {
+ if (!IS_ALIGNED(map_addr, PAGE_SIZE)) {
return REALM_ERROR;
}
@@ -562,6 +795,50 @@
return REALM_SUCCESS;
}
+static u_register_t host_realm_destroy_free_aux_rtt(struct realm *realm,
+ u_register_t addr,
+ long level)
+{
+ u_register_t rtt2, top, ret;
+
+ /* Destroy and undelegate RTT entry for all trees */
+ for (unsigned int tree_index = 1U;
+ tree_index <= realm->num_aux_planes;
+ tree_index++) {
+
+ ret = host_rmi_rtt_aux_destroy(realm->rd, ALIGN_DOWN(addr,
+ RTT_MAP_SIZE(level)),
+ level + 1L,
+ tree_index, &rtt2, &top);
+
+ if (ret != RMI_SUCCESS) {
+ /*
+ * IPA might not be mapped on all AUX RTTs
+ * ignore error
+ */
+ VERBOSE("%s() failed, map_addr=0x%lx ret=0x%lx \
+ rtt2=0x%lx \
+ top=0x%lx level=0x%lx\n",
+ "host_rmi_rtt_aux_destroy",
+ addr, ret, rtt2,
+ top, level + 1L);
+ }
+
+ if (rtt2 != 0UL) {
+ ret = host_rmi_granule_undelegate(rtt2);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate",
+ rtt2, ret);
+ return REALM_ERROR;
+ }
+
+ page_free(rtt2);
+ }
+ }
+ return REALM_SUCCESS;
+}
+
static u_register_t host_realm_destroy_undelegate_range(struct realm *realm,
u_register_t ipa,
u_register_t addr,
@@ -573,6 +850,29 @@
while (size >= PAGE_SIZE) {
ret = host_rmi_data_destroy(rd, ipa, &data, &top);
+
+ if (ret == RMI_ERROR_RTT_AUX) {
+ /* Unmap from all Aux RTTs */
+ for (unsigned int tree_index = 1U; tree_index <= realm->num_aux_planes;
+ tree_index++) {
+ u_register_t top1, level1;
+
+ /* IPA might not be mapped in all Aux RTTs ignore error */
+ ret = host_rmi_rtt_aux_unmap_protected(
+ rd,
+ ipa,
+ tree_index,
+ &top1, &level1);
+ if (ret != RMI_SUCCESS) {
+ VERBOSE("%s() failed, addr=0x%lx ret=0x%lx tree=0x%x\n",
+ "host_rmi_rtt_aux_unmap_protected",
+ ipa, ret, tree_index);
+ }
+ }
+ /* Retry DATA_DESTROY */
+ continue;
+ }
+
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
"host_rmi_data_destroy", ipa, ret);
@@ -622,6 +922,28 @@
case RMI_ASSIGNED:
if (host_ipa_is_ns(map_addr, realm->rmm_feat_reg0)) {
+ u_register_t level1;
+
+ /* Unmap from all Aux RTT */
+ if (!realm->rtt_tree_single) {
+ for (unsigned int tree_index = 1U;
+ tree_index <= realm->num_aux_planes;
+ tree_index++) {
+
+ ret = host_rmi_rtt_aux_unmap_unprotected(
+ rd,
+ map_addr,
+ tree_index,
+ &top, &level1);
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+ "host_rmi_rtt_unmap_unprotected",
+ map_addr, ret);
+ }
+ }
+ }
+
ret = host_rmi_rtt_unmap_unprotected(
rd,
map_addr,
@@ -669,6 +991,19 @@
map_addr, ret);
return REALM_ERROR;
}
+
+ /* RTT_AUX_DESTROY */
+ if (!realm->rtt_tree_single) {
+ ret = host_realm_destroy_free_aux_rtt(realm, map_addr,
+ level);
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, map_addr=0x%lx ret=0x%lx\n",
+ "host_realm_destroy_free_aux_rtt",
+ map_addr, ret);
+ return REALM_ERROR;
+ }
+ }
break;
default:
return REALM_ERROR;
@@ -700,11 +1035,28 @@
return ret.ret1;
}
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+ u_register_t rec,
+ u_register_t base,
+ u_register_t top,
+ u_register_t *out_top,
+ u_register_t *rtt_tree)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_SET_S2AP,
+ rd, rec, base, top,
+ (u_register_t)&rets}, 6U);
+ *out_top = rets.ret1;
+ *rtt_tree = rets.ret2;
+ return rets.ret0;
+}
+
u_register_t host_realm_create(struct realm *realm)
{
struct rmi_realm_params *params;
u_register_t ret;
- unsigned int count;
+ unsigned int count, rtt_page_count = 0U;
realm->par_size = REALM_MAX_LOAD_IMG_SIZE;
@@ -724,11 +1076,16 @@
}
}
+ assert(realm->num_aux_planes <= MAX_AUX_PLANE_COUNT);
+
/*
- * Allocate memory for PAR - Realm image. Granule delegation
+ * Allocate memory for PAR - Realm image for each Plane.
+ * Granule delegation
* of PAR will be performed during rtt creation.
*/
- realm->par_base = (u_register_t)page_alloc(realm->par_size);
+ realm->par_base = (u_register_t)page_alloc((realm->par_size) *
+ (realm->num_aux_planes + 1U));
+
if (realm->par_base == HEAP_NULL_PTR) {
ERROR("page_alloc failed, base=0x%lx, size=0x%lx\n",
realm->par_base, realm->par_size);
@@ -737,6 +1094,15 @@
INFO("Realm start adr=0x%lx\n", realm->par_base);
+ /* Allocate memory for params */
+ params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
+ if (params == NULL) {
+ ERROR("Failed to allocate memory for params\n");
+ goto pool_reset;
+ }
+
+ memset(params, 0, PAGE_SIZE);
+
/* Allocate and delegate RD */
realm->rd = (u_register_t)page_alloc(PAGE_SIZE);
if (realm->rd == HEAP_NULL_PTR) {
@@ -752,24 +1118,39 @@
}
/* Allocate and delegate RTT */
- realm->rtt_addr = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->rtt_tree_single) {
+ rtt_page_count = 1U;
+ } else {
+ /* Primary + AUX RTT Tree */
+ rtt_page_count = (realm->num_aux_planes + 1U);
+ }
+
+ realm->rtt_addr = (u_register_t)page_alloc(rtt_page_count * PAGE_SIZE);
+
if (realm->rtt_addr == HEAP_NULL_PTR) {
ERROR("Failed to allocate memory for rtt_addr\n");
goto err_undelegate_rd;
} else {
- ret = host_rmi_granule_delegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
- "host_rmi_granule_delegate", realm->rtt_addr, ret);
- goto err_free_rtt;
- }
- }
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_delegate(realm->rtt_addr + (i * PAGE_SIZE));
- /* Allocate memory for params */
- params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
- if (params == NULL) {
- ERROR("Failed to allocate memory for params\n");
- goto err_undelegate_rtt;
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_delegate", realm->rtt_addr, ret);
+
+ for (unsigned int j = 0U; j < i; j++) {
+ host_rmi_granule_undelegate(realm->rtt_addr
+ + (i * PAGE_SIZE));
+ }
+
+ goto err_free_rtt;
+ }
+
+ if (i > 0U && !realm->rtt_tree_single) {
+ realm->aux_rtt_addr[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+ params->aux_rtt_base[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+ }
+ }
}
/* Populate params */
@@ -780,16 +1161,16 @@
/* SVE enable and vector length */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_SVE_EN) != 0UL) {
- params->flags = RMI_REALM_FLAGS_SVE;
+ params->flags0 = RMI_REALM_FLAGS0_SVE;
params->sve_vl = realm->sve_vl;
} else {
- params->flags = 0UL;
+ params->flags0 = 0UL;
params->sve_vl = 0U;
}
/* PMU enable and number of event counters */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_PMU_EN) != 0UL) {
- params->flags |= RMI_REALM_FLAGS_PMU;
+ params->flags0 |= RMI_REALM_FLAGS0_PMU;
params->pmu_num_ctrs = realm->pmu_num_ctrs;
} else {
params->pmu_num_ctrs = 0U;
@@ -797,21 +1178,32 @@
/* LPA2 enable */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_LPA2) != 0UL) {
- params->flags |= RMI_REALM_FLAGS_LPA2;
+ params->flags0 |= RMI_REALM_FLAGS0_LPA2;
}
params->rtt_level_start = realm->start_level;
- params->hash_algo = RMI_HASH_SHA_256;
+ params->algorithm = RMI_HASH_SHA_256;
params->vmid = vmid++;
params->rtt_base = realm->rtt_addr;
params->rtt_num_start = 1U;
+ if (!realm->rtt_tree_single) {
+ params->flags1 = RMI_REALM_FLAGS1_RTT_TREE_PP;
+ }
+ params->num_aux_planes = realm->num_aux_planes;
+
+ /* Allocate VMID for all planes */
+ for (unsigned int i = 0U; i < realm->num_aux_planes; i++) {
+ params->aux_vmid[i] = (unsigned short)(vmid++);
+ realm->aux_vmid[i] = params->aux_vmid[i];
+ }
+
/* Create Realm */
ret = host_rmi_realm_create(realm->rd, (u_register_t)params);
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_realm_create", realm->rd, ret);
- goto err_free_params;
+ goto err_free_vmid;
}
realm->vmid = params->vmid;
@@ -820,7 +1212,7 @@
ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_rec_aux_count", realm->rd, ret);
host_rmi_realm_destroy(realm->rd);
- goto err_free_params;
+ goto err_free_vmid;
}
realm->state = REALM_STATE_NEW;
@@ -829,14 +1221,10 @@
page_free((u_register_t)params);
return REALM_SUCCESS;
-err_free_params:
- page_free((u_register_t)params);
-
-err_undelegate_rtt:
- ret = host_rmi_granule_undelegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
- "host_rmi_granule_undelegate", realm->rtt_addr, ret);
+err_free_vmid:
+ /* Free VMID */
+ for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+ vmid--;
}
err_free_rtt:
@@ -848,9 +1236,20 @@
WARN("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_granule_undelegate", realm->rd, ret);
}
+
err_free_rd:
page_free(realm->rd);
+ page_free((u_register_t)params);
+
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+ if (ret != RMI_SUCCESS) {
+ WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+ }
+ }
+
err_free_par:
page_free(realm->par_base);
@@ -873,22 +1272,23 @@
u_register_t realm_payload_adr)
{
u_register_t src_pa = realm_payload_adr;
- u_register_t i = 0UL;
u_register_t ret;
/* MAP image regions */
- while (i < (realm->par_size / PAGE_SIZE)) {
+ /* Copy Plane 0-N Images */
+
+ for (unsigned int j = 0U; j <= realm->num_aux_planes; j++) {
ret = host_realm_delegate_map_protected_data(false, realm,
- realm->par_base + i * PAGE_SIZE,
- PAGE_SIZE,
- src_pa + i * PAGE_SIZE);
+ realm->par_base + (j * realm->par_size),
+ realm->par_size,
+ src_pa);
+
if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
- "host_realm_delegate_map_protected_data",
- realm->par_base, ret);
+ ERROR("%s() failed par_base=0x%lx size=0x%lx j=%u ret=0x%lx\n",
+ "host_realm_delegate_map_protected_data",
+ realm->par_base, realm->par_size, j, ret);
return REALM_ERROR;
}
- i++;
}
return REALM_SUCCESS;
@@ -1129,6 +1529,7 @@
u_register_t host_realm_destroy(struct realm *realm)
{
u_register_t ret;
+ unsigned int rtt_page_count;
long rtt_start_level = realm->start_level;
if (realm->state == REALM_STATE_NULL) {
@@ -1207,11 +1608,24 @@
return REALM_ERROR;
}
- ret = host_rmi_granule_undelegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
- "host_rmi_granule_undelegate", realm->rtt_addr, ret);
- return REALM_ERROR;
+ if (realm->rtt_tree_single) {
+ rtt_page_count = 1U;
+ } else {
+ rtt_page_count = realm->num_aux_planes + 1U;
+ }
+
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+ return REALM_ERROR;
+ }
+ }
+
+ /* Free VMID */
+ for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+ vmid--;
}
page_free(realm->rd);
@@ -1299,3 +1713,55 @@
*exit_reason = run->exit.exit_reason;
return ret;
}
+
+u_register_t host_rmi_pdev_aux_count(u_register_t pdev_ptr, u_register_t *count)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_AUX_COUNT, pdev_ptr},
+ 2U);
+ *count = rets.ret1;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_pdev_create(u_register_t pdev_ptr, u_register_t params_ptr)
+{
+ return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_CREATE, pdev_ptr,
+ params_ptr}, 3U).ret0;
+}
+
+u_register_t host_rmi_pdev_get_state(u_register_t pdev_ptr, u_register_t *state)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_GET_STATE, pdev_ptr},
+ 2U);
+ *state = rets.ret1;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_pdev_communicate(u_register_t pdev_ptr,
+ u_register_t data_ptr)
+{
+ return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_COMMUNICATE, pdev_ptr,
+ data_ptr}, 3U).ret0;
+}
+
+u_register_t host_rmi_pdev_set_pubkey(u_register_t pdev_ptr, u_register_t key,
+ u_register_t len, uint8_t algo)
+{
+ return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_SET_PUBKEY, pdev_ptr,
+ key, len, algo}, 5U).ret0;
+}
+
+u_register_t host_rmi_pdev_stop(u_register_t pdev_ptr)
+{
+ return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_STOP, pdev_ptr},
+ 2U).ret0;
+}
+
+u_register_t host_rmi_pdev_destroy(u_register_t pdev_ptr)
+{
+ return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_DESTROY, pdev_ptr},
+ 2U).ret0;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
new file mode 100644
index 0000000..c43c374
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <heap/page_alloc.h>
+#include <host_crypto_utils.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+#include <mmio.h>
+#include <pcie.h>
+#include <pcie_doe.h>
+#include <pcie_spec.h>
+#include <platform.h>
+#include <spdm.h>
+#include <test_helpers.h>
+
+/* SPDM_MAX_CERTIFICATE_CHAIN_SIZE is 64KB */
+#define HOST_PDEV_CERT_LEN_MAX (64 * 1024)
+
+/*
+ * Measurement max supported is 4KB.
+ * todo: This will be increased if device supports returning more measurements
+ */
+#define HOST_PDEV_MEAS_LEN_MAX (4 * 1024)
+
+#define DEV_OBJ_CERT 0U
+#define DEV_OBJ_MEASUREMENTS 2U
+#define DEV_OBJ_INTERFACE_REPORT 3U
+
+struct host_tdi {
+ /* PDEV related fields */
+ void *pdev;
+ unsigned long pdev_flags;
+ void *pdev_aux[PDEV_PARAM_AUX_GRANULES_MAX];
+ uint32_t pdev_aux_num;
+ struct rmi_dev_comm_data *dev_comm_data;
+
+ /* Algorithm used to generate device digests */
+ uint8_t pdev_hash_algo;
+
+ /* Certificate, public key fields */
+ uint8_t cert_slot_id;
+ uint8_t *cert_chain;
+ size_t cert_chain_len;
+ void *public_key;
+ size_t public_key_len;
+ void *public_key_metadata;
+ size_t public_key_metadata_len;
+ unsigned char public_key_sig_algo;
+
+ /*
+ * Fields related to cached device measurements.
+ * todo: This will be moved to vdev scope
+ */
+ uint8_t *meas;
+ size_t meas_len;
+
+ /* PCIe details: bdf, DOE, Stream id, IO range */
+ uint32_t bdf;
+ uint32_t doe_cap_base;
+};
+
+static struct host_tdi g_tdi;
+
+static const char * const pdev_state_str[] = {
+ "PDEV_STATE_NEW",
+ "PDEV_STATE_NEEDS_KEY",
+ "PDEV_STATE_HAS_KEY",
+ "PDEV_STATE_READY",
+ "PDEV_STATE_COMMUNICATING",
+ "PDEV_STATE_STOPPED",
+ "RMI_PDEV_STATE_ERROR"
+};
+
+static int host_tdi_pdev_get_state(struct host_tdi *tdi, u_register_t *state)
+{
+ u_register_t ret;
+
+ ret = host_rmi_pdev_get_state((u_register_t)tdi->pdev, state);
+ if (ret != RMI_SUCCESS) {
+ return -1;
+ }
+ return 0;
+}
+
+static bool is_host_tdi_pdev_state(struct host_tdi *tdi, u_register_t exp_state)
+{
+ u_register_t cur_state;
+
+ if (host_tdi_pdev_get_state(tdi, &cur_state) != 0) {
+ return false;
+ }
+
+ if (cur_state != exp_state) {
+ return false;
+ }
+
+ return true;
+}
+
+static int host_tdi_pdev_create(struct host_tdi *tdi)
+{
+ struct rmi_pdev_params *pdev_params;
+ u_register_t ret;
+ uint32_t i;
+
+ pdev_params = (struct rmi_pdev_params *)page_alloc(PAGE_SIZE);
+ memset(pdev_params, 0, GRANULE_SIZE);
+
+ pdev_params->flags = tdi->pdev_flags;
+ pdev_params->cert_id = tdi->cert_slot_id;
+ pdev_params->pdev_id = tdi->bdf;
+ pdev_params->num_aux = tdi->pdev_aux_num;
+ pdev_params->hash_algo = tdi->pdev_hash_algo;
+ for (i = 0; i < tdi->pdev_aux_num; i++) {
+ pdev_params->aux[i] = (uintptr_t)tdi->pdev_aux[i];
+ }
+
+ ret = host_rmi_pdev_create((u_register_t)tdi->pdev,
+ (u_register_t)pdev_params);
+ if (ret != RMI_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int host_tdi_pdev_set_pubkey(struct host_tdi *tdi)
+{
+ u_register_t ret;
+
+ ret = host_rmi_pdev_set_pubkey((u_register_t)tdi->pdev,
+ (u_register_t)tdi->public_key,
+ (u_register_t)tdi->public_key_len,
+ (u_register_t)tdi->public_key_sig_algo);
+ if (ret != RMI_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int host_tdi_pdev_stop(struct host_tdi *tdi)
+{
+ u_register_t ret;
+
+ ret = host_rmi_pdev_stop((u_register_t)tdi->pdev);
+ if (ret != RMI_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int host_tdi_pdev_destroy(struct host_tdi *tdi)
+{
+ u_register_t ret;
+
+ ret = host_rmi_pdev_destroy((u_register_t)tdi->pdev);
+ if (ret != RMI_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int host_tdi_pdev_cache_device_object(struct host_tdi *tdi,
+ uint8_t obj_type,
+ const uint8_t *obj_buf,
+ size_t obj_len)
+{
+ int rc = -1;
+
+ if (obj_type == DEV_OBJ_CERT) {
+ if ((tdi->cert_chain_len + obj_len) > HOST_PDEV_CERT_LEN_MAX) {
+ return -1;
+ }
+
+ INFO("%s: cache_cert: offset: 0x%lx, len: 0x%lx\n",
+ __func__, tdi->cert_chain_len, obj_len);
+
+ memcpy((void *)(tdi->cert_chain + tdi->cert_chain_len),
+ obj_buf, obj_len);
+ tdi->cert_chain_len += obj_len;
+ rc = 0;
+ } else if (obj_type == DEV_OBJ_MEASUREMENTS) {
+ if ((tdi->meas_len + obj_len) > HOST_PDEV_MEAS_LEN_MAX) {
+ return -1;
+ }
+
+ INFO("%s: cache_meas: offset: 0x%lx, len: 0x%lx\n",
+ __func__, tdi->meas_len, obj_len);
+
+ memcpy((void *)(tdi->meas + tdi->meas_len), obj_buf, obj_len);
+ tdi->meas_len += obj_len;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+/* Call RMI PDEV communicate until the target state is reached */
+static int host_tdi_pdev_communicate(struct host_tdi *tdi,
+ unsigned char target_state)
+{
+ int rc;
+ u_register_t state;
+ u_register_t ret;
+ struct rmi_dev_comm_enter *dev_comm_enter;
+ struct rmi_dev_comm_exit *dev_comm_exit;
+ size_t resp_len;
+
+ dev_comm_enter = &tdi->dev_comm_data->enter;
+ dev_comm_exit = &tdi->dev_comm_data->exit;
+
+ dev_comm_enter->status = RMI_DEV_COMM_ENTER_STATUS_NONE;
+ dev_comm_enter->resp_len = 0;
+
+ if (host_tdi_pdev_get_state(tdi, &state) != 0) {
+ return -1;
+ }
+
+ do {
+ ret = host_rmi_pdev_communicate((u_register_t)tdi->pdev,
+ (u_register_t)tdi->dev_comm_data);
+ if (ret != RMI_SUCCESS) {
+ INFO("rmi_pdev_communicate failed\n");
+ rc = -1;
+ break;
+ }
+
+ /*
+ * If cache is set, then response buffer has the device object
+ * to be cached.
+ */
+ if (EXTRACT(RMI_DEV_COMM_EXIT_FLAGS_CACHE,
+ dev_comm_exit->flags)) {
+ uint8_t *obj_buf;
+ uint8_t obj_type;
+
+ if (dev_comm_exit->cache_len == 0 ||
+ (dev_comm_exit->cache_offset +
+ dev_comm_exit->cache_len) >
+ GRANULE_SIZE) {
+ INFO("Invalid cache offset/length\n");
+ rc = -1;
+ break;
+ }
+
+ if (state == RMI_PDEV_STATE_NEW) {
+ obj_type = DEV_OBJ_CERT;
+ } else if (state == RMI_PDEV_STATE_HAS_KEY) {
+ /* todo: replace with RMI_PDEV_STATE_READY */
+ obj_type = DEV_OBJ_MEASUREMENTS;
+ } else {
+ rc = -1;
+ break;
+ }
+
+ obj_buf = (uint8_t *)dev_comm_enter->resp_addr +
+ dev_comm_exit->cache_offset;
+ rc = host_tdi_pdev_cache_device_object(tdi, obj_type,
+ obj_buf,
+ dev_comm_exit->cache_len);
+ if (rc != 0) {
+ INFO("host_pdev_cache_device_object failed\n");
+ rc = -1;
+ break;
+ }
+ }
+
+ /* Send request to spdm responder */
+ if (EXTRACT(RMI_DEV_COMM_EXIT_FLAGS_SEND,
+ dev_comm_exit->flags)) {
+ uint32_t doe_header;
+
+ /* todo: validate DevCommExit flags */
+ if (dev_comm_exit->protocol ==
+ RMI_DEV_COMM_PROTOCOL_SPDM) {
+ doe_header = DOE_HEADER_1;
+ } else if (dev_comm_exit->protocol ==
+ RMI_DEV_COMM_PROTOCOL_SECURE_SPDM) {
+ doe_header = DOE_HEADER_2;
+ } else {
+ INFO("Invalid dev_comm_exit.protocol\n");
+ rc = -1;
+ break;
+ }
+
+ rc = pcie_doe_communicate(doe_header, tdi->bdf, tdi->doe_cap_base,
+ (void *)dev_comm_enter->req_addr,
+ dev_comm_exit->req_len,
+ (void *)dev_comm_enter->resp_addr,
+ &resp_len);
+
+ /*
+ * Set IoEnter args for next pdev_communicate. Upon
+ * success or error call pdev_communicate
+ */
+ if (rc == 0) {
+ dev_comm_enter->status =
+ RMI_DEV_COMM_ENTER_STATUS_SUCCESS;
+ dev_comm_enter->resp_len = resp_len;
+ } else {
+ dev_comm_enter->status =
+ RMI_DEV_COMM_ENTER_STATUS_ERROR;
+ dev_comm_enter->resp_len = 0;
+ }
+ }
+
+ rc = host_tdi_pdev_get_state(tdi, &state);
+ if (rc != 0) {
+ break;
+ }
+ } while ((state != target_state) && (state != RMI_PDEV_STATE_ERROR));
+
+ return rc;
+}
+
+/*
+ * Invoke RMI handler to transition PDEV state to 'to_state'
+ */
+static int host_tdi_pdev_transition(struct host_tdi *tdi, unsigned char to_state)
+{
+ int rc;
+
+ switch (to_state) {
+ case RMI_PDEV_STATE_NEW:
+ rc = host_tdi_pdev_create(tdi);
+ break;
+ case RMI_PDEV_STATE_NEEDS_KEY:
+ rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_NEEDS_KEY);
+ break;
+ case RMI_PDEV_STATE_HAS_KEY:
+ rc = host_tdi_pdev_set_pubkey(tdi);
+ break;
+ case RMI_PDEV_STATE_READY:
+ rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_READY);
+ break;
+ case RMI_PDEV_STATE_STOPPING:
+ rc = host_tdi_pdev_stop(tdi);
+ break;
+ case RMI_PDEV_STATE_STOPPED:
+ rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_STOPPED);
+ break;
+ default:
+ rc = -1;
+ }
+
+ if (rc != 0) {
+ INFO("RMI command failed\n");
+ return -1;
+ }
+
+ if (!is_host_tdi_pdev_state(tdi, to_state)) {
+ ERROR("PDEV state not [%s]\n", pdev_state_str[to_state]);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate granules needed for a PDEV object like device communication data,
+ * response buffer, PDEV AUX granules and memory required to store cert_chain
+ */
+static int host_tdi_pdev_setup(struct host_tdi *tdi)
+{
+ u_register_t ret, count;
+ int i;
+
+ memset(tdi, 0, sizeof(struct host_tdi));
+
+ /* Allocate granule for PDEV and delegate */
+ tdi->pdev = page_alloc(PAGE_SIZE);
+ memset(tdi->pdev, 0, GRANULE_SIZE);
+ ret = host_rmi_granule_delegate((u_register_t)tdi->pdev);
+ if (ret != RMI_SUCCESS) {
+ ERROR("PDEV delegate failed 0x%lx\n", ret);
+ return -1;
+ }
+
+ /* Set flags as IO coherent device protected by end to end IDE. */
+ tdi->pdev_flags = INPLACE(RMI_PDEV_FLAGS_PROT_CONFIG,
+ RMI_PDEV_IOCOH_E2E_IDE);
+
+ /* Get num of aux granules required for this PDEV */
+ ret = host_rmi_pdev_aux_count(tdi->pdev_flags, &count);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_pdev_aux_count() failed 0x%lx\n", ret);
+ return -1;
+ }
+ tdi->pdev_aux_num = count;
+
+ /* Allocate aux granules for PDEV and delegate */
+ INFO("PDEV create requires %u aux pages\n", tdi->pdev_aux_num);
+ for (i = 0; i < tdi->pdev_aux_num; i++) {
+ tdi->pdev_aux[i] = page_alloc(PAGE_SIZE);
+ ret = host_rmi_granule_delegate((u_register_t)tdi->pdev_aux[i]);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Aux granule delegate failed 0x%lx\n", ret);
+ return -1;
+ }
+ }
+
+ /* Allocate dev_comm_data and send/recv buffer for Dev communication */
+ tdi->dev_comm_data = (struct rmi_dev_comm_data *)page_alloc(PAGE_SIZE);
+ memset(tdi->dev_comm_data, 0, sizeof(struct rmi_dev_comm_data));
+ tdi->dev_comm_data->enter.req_addr = (unsigned long)
+ page_alloc(PAGE_SIZE);
+ tdi->dev_comm_data->enter.resp_addr = (unsigned long)
+ page_alloc(PAGE_SIZE);
+
+ /* Allocate buffer to cache device certificate */
+ tdi->cert_slot_id = 0;
+ tdi->cert_chain = (uint8_t *)page_alloc(HOST_PDEV_CERT_LEN_MAX);
+ tdi->cert_chain_len = 0;
+ if (tdi->cert_chain == NULL) {
+ return -1;
+ }
+
+ /* Allocate buffer to store extracted public key */
+ tdi->public_key = (void *)page_alloc(PAGE_SIZE);
+ if (tdi->public_key == NULL) {
+ return -1;
+ }
+ tdi->public_key_len = PAGE_SIZE;
+
+ /* Allocate buffer to store public key metadata */
+ tdi->public_key_metadata = (void *)page_alloc(PAGE_SIZE);
+ if (tdi->public_key_metadata == NULL) {
+ return -1;
+ }
+ tdi->public_key_metadata_len = PAGE_SIZE;
+
+ /* Allocate buffer to cache device measurements */
+ tdi->meas = (uint8_t *)page_alloc(HOST_PDEV_MEAS_LEN_MAX);
+ tdi->meas_len = 0;
+ if (tdi->meas == NULL) {
+ return -1;
+ }
+
+ /* Set algorithm to use for device digests */
+ tdi->pdev_hash_algo = RMI_HASH_SHA_512;
+
+ return 0;
+}
+
+/*
+ * Stop PDEV and ternimate secure session and call PDEV destroy
+ */
+static int host_tdi_pdev_reclaim(struct host_tdi *tdi)
+{
+ int rc;
+
+ /* Move the device to STOPPING state */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_STOPPING);
+ if (rc != 0) {
+ INFO("PDEV transition: to PDEV_STATE_STOPPING failed\n");
+ return -1;
+ }
+
+ /* Do pdev_communicate to terminate secure session */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_STOPPED);
+ if (rc != 0) {
+ INFO("PDEV transition: to PDEV_STATE_STOPPED failed\n");
+ return -1;
+ }
+
+ rc = host_tdi_pdev_destroy(tdi);
+ if (rc != 0) {
+ INFO("PDEV transition: to STATE_NULL failed\n");
+ return -1;
+ }
+
+ /* Undelegate all the delegated pages */
+ for (int i = 0; i < tdi->pdev_aux_num; i++) {
+ host_rmi_granule_undelegate((u_register_t)tdi->pdev_aux[i]);
+ }
+ host_rmi_granule_undelegate((u_register_t)tdi->pdev);
+
+ return rc;
+}
+
+/*
+ * This invokes various RMI calls related to PDEV management that does
+ * PDEV create/communicate/set_key/abort/stop/destroy on a device.
+ */
+test_result_t host_test_rmi_pdev_calls(void)
+{
+ u_register_t rmi_feat_reg0;
+ uint32_t pdev_bdf, doe_cap_base;
+ struct host_tdi *tdi;
+ uint8_t public_key_algo;
+ int ret, rc;
+
+ CHECK_DA_SUPPORT_IN_RMI(rmi_feat_reg0);
+ SKIP_TEST_IF_DOE_NOT_SUPPORTED(pdev_bdf, doe_cap_base);
+
+ /* Initialize Host NS heap memory */
+ ret = page_pool_init((u_register_t)PAGE_POOL_BASE,
+ (u_register_t)PAGE_POOL_MAX_SIZE);
+ if (ret != HEAP_INIT_SUCCESS) {
+ ERROR("Failed to init heap pool %d\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ tdi = &g_tdi;
+
+ /* Allocate granules. Skip DA ABIs if host_pdev_setup fails */
+ rc = host_tdi_pdev_setup(tdi);
+ if (rc == -1) {
+ INFO("host_pdev_setup failed. skipping DA ABIs...\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* todo: move to tdi_pdev_setup */
+ tdi->bdf = pdev_bdf;
+ tdi->doe_cap_base = doe_cap_base;
+
+ /* Call rmi_pdev_create to transition PDEV to STATE_NEW */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_NEW);
+ if (rc != 0) {
+ ERROR("PDEV transition: NULL -> STATE_NEW failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Call rmi_pdev_communicate to transition PDEV to NEEDS_KEY */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_NEEDS_KEY);
+ if (rc != 0) {
+ ERROR("PDEV transition: PDEV_NEW -> PDEV_NEEDS_KEY failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Get public key. Verifying cert_chain not done by host but by Realm? */
+ rc = host_get_public_key_from_cert_chain(tdi->cert_chain,
+ tdi->cert_chain_len,
+ tdi->public_key,
+ &tdi->public_key_len,
+ tdi->public_key_metadata,
+ &tdi->public_key_metadata_len,
+ &public_key_algo);
+ if (rc != 0) {
+ ERROR("Get public key failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ if (public_key_algo == PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256) {
+ tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_ECDSA_P256;
+ } else if (public_key_algo == PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384) {
+ tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_ECDSA_P384;
+ } else {
+ tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_RSASSA_3072;
+ }
+ INFO("DEV public key len/sig_algo: %ld/%d\n", tdi->public_key_len,
+ tdi->public_key_sig_algo);
+
+ /* Call rmi_pdev_set_key transition PDEV to HAS_KEY */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_HAS_KEY);
+ if (rc != 0) {
+ INFO("PDEV transition: PDEV_NEEDS_KEY -> PDEV_HAS_KEY failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Call rmi_pdev_comminucate to transition PDEV to READY state */
+ rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_READY);
+ if (rc != 0) {
+ INFO("PDEV transition: PDEV_HAS_KEY -> PDEV_READY failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ host_tdi_pdev_reclaim(tdi);
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
index 34c684c..43d9f01 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
@@ -22,7 +22,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- 0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U)) {
+ 0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
@@ -41,7 +41,7 @@
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 50UL),
- RTT_MIN_LEVEL, rec_flag, 1U)) {
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
@@ -67,7 +67,7 @@
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
- RTT_MIN_LEVEL, rec_flag, 1U)) {
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -80,6 +80,62 @@
}
/*
+ * @Test_Aim@ Create a Realm with LPA2 disabled but FEAT_LPA2 present
+ * on the platform.
+ * Test that RMI_RTT_MAP_UNPROTECTED and RMI_RTT_CREATE commands fails if PA >= 48 bits
+ */
+test_result_t host_test_data_bound_non_lpa2_realm_on_lpa2plat(void)
+{
+ u_register_t rec_flag[1] = {RMI_RUNNABLE};
+ struct realm realm;
+ u_register_t ret, base, base_ipa;
+ test_result_t result = TEST_RESULT_FAIL;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (is_feat_52b_on_4k_2_supported() == false) {
+ return TEST_RESULT_SKIPPED;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Can choose any unprotected IPA adr, TFTF_BASE chosen for convenience */
+ base = TFTF_BASE;
+ base = base | (1UL << 48UL);
+
+ ret = host_realm_map_unprotected(&realm, base, PAGE_SIZE);
+
+ if (ret == REALM_SUCCESS) {
+ ERROR("host_realm_map_unprotected should have failed\n");
+ goto destroy_realm;
+ }
+
+ base_ipa = base | (1UL <<
+ (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, realm.rmm_feat_reg0) - 1UL));
+
+ ret = host_rmi_create_rtt_levels(&realm, base_ipa, RTT_MIN_LEVEL, 3);
+
+ if (ret == REALM_SUCCESS) {
+ ERROR("host_rmi_create_rtt_levels should have failed\n");
+ goto destroy_realm;
+ }
+
+ result = TEST_RESULT_SUCCESS;
+
+destroy_realm:
+ if (!host_destroy_realm(&realm)) {
+ ERROR("%s(): failed to destroy realm\n", __func__);
+ return TEST_RESULT_FAIL;
+ }
+
+ return result;
+}
+
+/*
* @Test_Aim@ Test creating a Realm payload with LPA2 enabled on a platform
* which does not implement FEAT_LPA2.
* Realm creation must fail.
@@ -99,7 +155,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, RTT_MIN_LEVEL, rec_flag, 1U)) {
+ feature_flag, RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
index e3ee23b..151e871 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
@@ -47,7 +47,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -112,7 +112,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 3U)) {
+ feature_flag, sl, rec_flag, 3U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -257,7 +257,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -361,7 +361,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -499,12 +499,12 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
if (!host_create_activate_realm_payload(&realm2, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ret2 = host_destroy_realm(&realm);
return TEST_RESULT_FAIL;
}
@@ -661,7 +661,7 @@
/* Request more PMU counter than total, expect failure */
if (host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm create should have failed\n");
host_destroy_realm(&realm);
return TEST_RESULT_FAIL;
@@ -676,7 +676,7 @@
}
ret1 = host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U);
+ feature_flag, sl, rec_flag, 1U, 0U);
if (!get_feat_hpmn0_supported()) {
if (ret1) {
@@ -702,7 +702,7 @@
/* Prepare realm0, create recs for realm0 later */
if (!host_prepare_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
goto test_exit;
return TEST_RESULT_FAIL;
}
@@ -716,7 +716,7 @@
}
if (!host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
goto test_exit2;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index e22a9f1..c25c58d 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -59,7 +59,7 @@
unsigned int run_num = (unsigned int)rand() % MAX_REC_COUNT;
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -97,7 +97,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -141,7 +141,7 @@
pauth_test_lib_fill_regs_and_template(pauth_keys_before);
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -203,7 +203,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -281,17 +281,25 @@
static test_result_t host_test_realm_pmuv3(uint8_t cmd)
{
struct realm realm;
- u_register_t feature_flag;
+ u_register_t feature_flag, rmm_feat_reg0;
+ unsigned int num_cnts;
long sl = RTT_MIN_LEVEL;
u_register_t rec_flag[1] = {RMI_RUNNABLE};
bool ret1, ret2;
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+ /* Get Max PMU counter implemented through RMI_FEATURES */
+ if (host_rmi_features(0UL, &rmm_feat_reg0) != REALM_SUCCESS) {
+ ERROR("%s() failed\n", "host_rmi_features");
+ return TEST_RESULT_FAIL;
+ }
+
+ num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
host_set_pmu_state();
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, (unsigned long long)(-1));
+ INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts);
if (is_feat_52b_on_4k_2_supported() == true) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
@@ -299,7 +307,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -412,7 +420,8 @@
ret = host_create_activate_realm_payload(&realm[num],
(u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT);
+ feature_flag, sl, rec_flag,
+ MAX_REC_COUNT, 0U);
if (!ret) {
goto destroy_realms;
}
@@ -476,7 +485,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -575,7 +584,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -647,7 +656,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -773,7 +782,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -882,7 +891,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1017,7 +1026,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 4U)) {
+ feature_flag, sl, rec_flag, 4U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1159,7 +1168,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1267,7 +1276,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1497,7 +1506,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1683,7 +1692,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
goto destroy_realm;
}
@@ -1729,7 +1738,7 @@
feature_flag = INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 0x2CU);
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, RTT_MIN_LEVEL, rec_flag, 4U)) {
+ feature_flag, RTT_MIN_LEVEL, rec_flag, 4U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1876,7 +1885,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2033,7 +2042,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2208,7 +2217,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2323,7 +2332,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2436,7 +2445,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2525,3 +2534,151 @@
}
return res;
}
+
+/*
+ * Test aims to test that TF-RMM takes SCTLR2_EL1.EASE bit into account
+ * when injecting a SEA (Feat_DoubleFault2).
+ */
+test_result_t host_test_feat_doublefault2(void)
+{
+ bool ret;
+ u_register_t rec_flag;
+ u_register_t base;
+ struct realm realm;
+ struct rtt_entry rtt;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+ SKIP_TEST_IF_DOUBLE_FAULT2_NOT_SUPPORTED();
+
+ if (is_feat_52b_on_4k_2_supported() == true) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ rec_flag = RMI_RUNNABLE;
+
+ if (!host_create_activate_realm_payload(&realm,
+ (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, &rec_flag, 1U, 0U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * Allocate a page so we pass its address as first argument of
+ * the test command. The test will attempt an instruction fetch
+ * from that address, which will fail as the address will not
+ * be mapped into the Realm.
+ */
+ base = (u_register_t)page_alloc(PAGE_SIZE);
+
+ (void)host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
+ if (rtt.state != RMI_UNASSIGNED ||
+ (rtt.ripas != RMI_EMPTY)) {
+ ERROR("wrong initial state\n");
+ host_destroy_realm(&realm);
+ return TEST_RESULT_FAIL;
+ }
+
+ host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+
+ for (unsigned int i = 0U; i < 2U; i++) {
+ host_shared_data_set_host_val(&realm, 0U, HOST_ARG2_INDEX,
+ (unsigned long)i);
+
+ /* Rec0 expect IA due to SEA unassigned empty page */
+ ret = host_enter_realm_execute(&realm, REALM_FEAT_DOUBLEFAULT2_TEST,
+ RMI_EXIT_HOST_CALL, 0U);
+
+ if (!ret) {
+ host_destroy_realm(&realm);
+ return TEST_RESULT_FAIL;
+ }
+ }
+
+ host_destroy_realm(&realm);
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Create realm with a single REC
+ * Test attestation process for REC
+ */
+test_result_t host_realm_test_attestation(void)
+{
+ bool ret1, ret2;
+ u_register_t rec_flag[] = {RMI_RUNNABLE};
+ struct realm realm;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (is_feat_52b_on_4k_2_supported() == true) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, 0U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret1 = host_enter_realm_execute(&realm, REALM_ATTESTATION,
+ RMI_EXIT_HOST_CALL, 0U);
+ if (!ret1) {
+ ERROR("Realm attestation test failed\n");
+ }
+
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret1 || !ret2) {
+ ERROR("%s(): enter=%d destroy=%d\n",
+ __func__, ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Create realm with a single REC
+ * Test attestation fault for REC
+ */
+test_result_t host_realm_test_attestation_fault(void)
+{
+ bool ret1, ret2;
+ u_register_t rec_flag[] = {RMI_RUNNABLE};
+ struct realm realm;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (is_feat_52b_on_4k_2_supported() == true) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, 0U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret1 = host_enter_realm_execute(&realm, REALM_ATTESTATION_FAULT,
+ RMI_EXIT_HOST_CALL, 0U);
+ if (!ret1) {
+ ERROR("Realm attestation fault test failed\n");
+ }
+
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret1 || !ret2) {
+ ERROR("%s(): enter=%d destroy=%d\n",
+ __func__, ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
index 02c5d0f..235e093 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
@@ -39,7 +39,7 @@
/* Initialise Realm payload */
if (!host_create_activate_realm_payload(realm,
(u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
index 377c85b..6ab45c3 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
@@ -4,7 +4,7 @@
*/
#ifndef HOST_REALM_COMMON_H
-#define HOST_REALM_COMMON_h
+#define HOST_REALM_COMMON_H
#define NS_NORMAL_SVE 0x1U
#define NS_STREAMING_SVE 0x2U
diff --git a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
index 054e774..09482f2 100644
--- a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
@@ -106,23 +106,3 @@
return TEST_RESULT_SUCCESS;
}
-
-bool spm_core_sp_init(ffa_id_t sp_id)
-{
- /*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (sp_id != SP_ID(1)) {
- uint32_t core_pos = get_current_core_id();
- struct ffa_value ret = ffa_run(sp_id, core_pos);
-
- if (ffa_func_id(ret) != FFA_MSG_WAIT) {
- ERROR("Failed to run SP%x on core %u\n",
- sp_id, core_pos);
- return false;
- }
- }
-
- return true;
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 1f8e81c..4686e4c 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -185,19 +185,6 @@
}
/*
- * Secure Partitions beyond the first SP only have their first
- * EC (or vCPU0) woken up at boot time by the SPMC.
- * Other ECs need one round of ffa_run to reach the message loop.
- */
- ffa_ret = ffa_run(SP_ID(2), core_pos);
- if (ffa_func_id(ffa_ret) != FFA_MSG_WAIT) {
- ERROR("Failed to run SP%x on core %u\n", SP_ID(2),
- core_pos);
- ret = TEST_RESULT_FAIL;
- goto out;
- }
-
- /*
* Send a direct message request to SP2 (MP SP) from current physical
* CPU. The SPMC uses the MP pinned context corresponding to the
* physical CPU emitting the request.
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
index 5a60a21..47b4ad9 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
@@ -32,12 +32,17 @@
static __aligned(PAGE_SIZE) uint8_t vm1_rx_buffer[PAGE_SIZE];
static __aligned(PAGE_SIZE) uint8_t vm1_tx_buffer[PAGE_SIZE];
+static int schedule_receiver_interrupt_handler(void *data)
+{
+ return 0;
+}
+
test_result_t test_ffa_indirect_message_sp_to_vm(void)
{
struct ffa_value ret;
struct mailbox_buffers mb;
ffa_id_t header_sender;
- const ffa_id_t vm_id = 1;
+ const ffa_id_t vm_id = VM_ID(1);
const ffa_id_t sender = SP_ID(1);
char msg[300];
@@ -48,6 +53,9 @@
GET_TFTF_MAILBOX(mb);
+ tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
+ schedule_receiver_interrupt_handler);
+
ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
vm1_tx_buffer);
@@ -89,6 +97,15 @@
return TEST_RESULT_FAIL;
}
+ /*
+ * Managed exit occured while SP was running and it is left in its
+ * fiq handler, resume the SP to reach the FF-A message loop again.
+ */
+ ret = cactus_resume_after_managed_exit(HYP_ID, SPM_VM_ID_FIRST);
+ if (!is_ffa_direct_response(ret)) {
+ return TEST_RESULT_FAIL;
+ }
+
ret = ffa_notification_bitmap_destroy(vm_id);
if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
return TEST_RESULT_FAIL;
@@ -99,6 +116,8 @@
return TEST_RESULT_FAIL;
}
+ tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
+
return TEST_RESULT_SUCCESS;
}
@@ -110,7 +129,7 @@
{
struct ffa_value ret;
struct mailbox_buffers mb;
- const ffa_id_t vm_id = 1;
+ const ffa_id_t vm_id = VM_ID(1);
const ffa_id_t sender = SP_ID(1);
ffa_id_t header_sender;
u_register_t ret_rmm;
@@ -148,6 +167,9 @@
return TEST_RESULT_FAIL;
}
+ tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
+ schedule_receiver_interrupt_handler);
+
/*
* Delegate RX buffer of VM to realm.
*/
@@ -201,6 +223,15 @@
return TEST_RESULT_FAIL;
}
+ /*
+ * Managed exit occured while SP was running and it is left in its
+ * fiq handler, resume the SP to reach the FF-A message loop again.
+ */
+ ret = cactus_resume_after_managed_exit(HYP_ID, SPM_VM_ID_FIRST);
+ if (!is_ffa_direct_response(ret)) {
+ return TEST_RESULT_FAIL;
+ }
+
if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
return TEST_RESULT_FAIL;
@@ -213,6 +244,7 @@
}
/* Cleaning up after the test: */
+ tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
/* Destroy bitmap of VM. */
ret = ffa_notification_bitmap_destroy(vm_id);
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index b402c58..d80a052 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -1713,7 +1713,11 @@
goto exit;
}
- /* This time test should pass. */
+ /* Undelegate operation scrubbed the TX buffer, re-init the fragment. */
+ remaining_constituent_count = ffa_memory_fragment_init(
+ mb.send, PAGE_SIZE, &constituents[1], 1, &fragment_length);
+
+ /* This time the test is expected to pass. */
ffa_ret = ffa_mem_frag_tx(handle, fragment_length);
if (is_ffa_call_error(ffa_ret)) {
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index af338fb..fe04751 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -679,8 +679,6 @@
{
tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
schedule_receiver_interrupt_handler);
-
- tftf_irq_enable(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, 0xA);
}
/**
@@ -689,7 +687,6 @@
*/
static void schedule_receiver_interrupt_deinit(void)
{
- tftf_irq_disable(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
schedule_receiver_interrupt_received = 0;
}
@@ -984,14 +981,6 @@
per_vcpu_receiver, core_pos);
/*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (!spm_core_sp_init(per_vcpu_receiver)) {
- goto out;
- }
-
- /*
* Request to get notifications sent to the respective vCPU.
* Check also if NPI was handled by the receiver. It should have been
* pended at notifications set, in the respective vCPU.
@@ -1005,6 +994,8 @@
result = TEST_RESULT_SUCCESS;
out:
+ INFO("Request get per-vCPU notification to %x, core: %u.\n",
+ per_vcpu_receiver, core_pos);
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1019,17 +1010,8 @@
VERBOSE("Request SP %x to enable NPI in core %u\n",
per_vcpu_receiver, core_pos);
- /*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (!spm_core_sp_init(per_vcpu_receiver)) {
- goto out;
- }
-
result = TEST_RESULT_SUCCESS;
-out:
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1086,6 +1068,7 @@
per_vcpu_receiver = receiver;
per_vcpu_sender = sender;
+ INFO("Execute npi_enable_per_vcpu_on_handler\n");
/* Boot all cores and enable the NPI in all of them. */
if (spm_run_multi_core_test(
(uintptr_t)npi_enable_per_vcpu_on_handler,
@@ -1137,6 +1120,7 @@
result = TEST_RESULT_FAIL;
}
+ INFO("Execute request_notification_get_per_vcpu_on_handler\n");
/*
* Bring up all the cores, and request the receiver to get notifications
* in each one of them.
@@ -1148,6 +1132,7 @@
}
out:
+ INFO("UNbind message on CPU:%lx\n", read_mpidr_el1());
/* As a clean-up, unbind notifications. */
if (!request_notification_unbind(receiver, receiver,
sender,
@@ -1156,6 +1141,7 @@
result = TEST_RESULT_FAIL;
}
+ INFO("Execute npi_disable_per_vcpu_on_handler\n");
/* Boot all cores and DISABLE the NPI in all of them. */
if (spm_run_multi_core_test(
(uintptr_t)npi_disable_per_vcpu_on_handler,
@@ -1190,10 +1176,6 @@
VERBOSE("Getting per-vCPU notifications from %x, core: %u.\n",
per_vcpu_receiver, core_pos);
- if (!spm_core_sp_init(per_vcpu_sender)) {
- goto out;
- }
-
if (!notification_get_and_validate(per_vcpu_receiver,
FFA_NOTIFICATION(core_pos), 0,
core_pos,
@@ -1202,7 +1184,6 @@
result = TEST_RESULT_FAIL;
}
-out:
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1501,10 +1482,6 @@
unsigned int core_pos = get_current_core_id();
test_result_t result = TEST_RESULT_FAIL;
- if (!spm_core_sp_init(per_vcpu_sender)) {
- goto out;
- }
-
if (!notification_set(per_vcpu_receiver, per_vcpu_sender,
FFA_NOTIFICATIONS_FLAG_DELAY_SRI |
FFA_NOTIFICATIONS_FLAG_PER_VCPU |
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 144694e..7375633 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -8,20 +8,24 @@
extensions/afp/test_afp.c \
extensions/amu/test_amu.c \
extensions/brbe/test_brbe.c \
+ extensions/d128/test_d128.c \
extensions/debugv8p9/test_debugv8p9.c \
extensions/ecv/test_ecv.c \
extensions/fgt/test_fgt.c \
+ extensions/fpmr/test_fpmr.c \
extensions/ls64/test_ls64.c \
extensions/ls64/ls64_operations.S \
extensions/mpam/test_mpam.c \
extensions/mte/test_mte.c \
extensions/pauth/test_pauth.c \
extensions/pmuv3/test_pmuv3.c \
+ extensions/sctlr2/test_sctlr2.c \
extensions/sme/test_sme.c \
extensions/sme/test_sme2.c \
extensions/spe/test_spe.c \
extensions/sve/test_sve.c \
extensions/sys_reg_trace/test_sys_reg_trace.c \
+ extensions/the/test_the.c \
extensions/trbe/test_trbe.c \
extensions/trf/test_trf.c \
extensions/wfxt/test_wfxt.c \
@@ -29,4 +33,5 @@
runtime_services/arm_arch_svc/smccc_arch_workaround_1.c \
runtime_services/arm_arch_svc/smccc_arch_workaround_2.c \
runtime_services/arm_arch_svc/smccc_arch_workaround_3.c \
+ runtime_services/arm_arch_svc/smccc_feature_availability.c \
)
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 34ac0b6..51aa27c 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -23,6 +23,7 @@
<testcase name="Check for MTE register leakage" function="test_mte_leakage" />
<testcase name="Use FGT Registers" function="test_fgt_enabled" />
<testcase name="Use FGT2 Registers" function="test_fgt2_enabled" />
+ <testcase name="Use FPMR Register" function="test_fpmr_enabled" />
<testcase name="Use ECV Registers" function="test_ecv_enabled" />
<testcase name="Use trace buffer control Registers" function="test_trbe_enabled" />
<testcase name="Use branch record buffer control registers" function="test_brbe_enabled" />
@@ -39,6 +40,9 @@
<testcase name="PMUv3 SMC counter preservation" function="test_pmuv3_el3_preserves" />
<testcase name="LS64 support" function="test_ls64_instructions" />
<testcase name="LS64-ACCDATA support" function="test_ls64_accdata_sysreg" />
+ <testcase name="SCTLR2 support" function="test_sctlr2_support" />
+ <testcase name="THE support" function="test_the_support" />
+ <testcase name="D128 support" function="test_d128_support" />
</testsuite>
<testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">
@@ -46,6 +50,7 @@
<testcase name="SMCCC_ARCH_WORKAROUND_2 test" function="test_smccc_arch_workaround_2" />
<testcase name="SMCCC_ARCH_WORKAROUND_3 test" function="test_smccc_arch_workaround_3" />
<testcase name="SMCCC_ARCH_SOC_ID test" function="test_smccc_arch_soc_id" />
+ <testcase name="SMCCC_ARCH_FEATURE_AVAILABILITY test" function="test_smccc_arch_feature_availability" />
</testsuite>
</testsuites>
diff --git a/tftf/tests/tests-pcie-doe.mk b/tftf/tests/tests-pcie-doe.mk
deleted file mode 100644
index 14bc9cf..0000000
--- a/tftf/tests/tests-pcie-doe.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (c) 2024, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-TESTS_SOURCES += \
- $(addprefix plat/arm/fvp/, \
- fvp_pcie.c \
- )
-
-TESTS_SOURCES += \
- $(addprefix tftf/tests/doe_tests/, \
- doe_helpers.c \
- test_doe.c \
- )
-
-TESTS_SOURCES += \
- $(addprefix lib/pcie/, \
- pcie.c \
- pcie_doe.c \
- )
diff --git a/tftf/tests/tests-pcie-doe.xml b/tftf/tests/tests-pcie-doe.xml
deleted file mode 100644
index ed8b7cb..0000000
--- a/tftf/tests/tests-pcie-doe.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- Copyright (c) 2024, Arm Limited. All rights reserved.
-
- SPDX-License-Identifier: BSD-3-Clause
--->
-
-<testsuites>
- <testsuite name="PCI Data Object Exchange" description="Check PCI DOE support">
- <testcase name="PCI DOE Discovery" function="doe_discovery_test" />
- <testcase name="SPDM Get Version" function="spdm_version_test" />
- </testsuite>
-</testsuites>
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index ae4b20a..b6833e1 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -25,6 +25,8 @@
host_realm_helper.c \
host_shared_data.c \
rmi_delegate_tests.c \
+ host_rmi_pdev.c \
+ host_crypto_utils.c \
)
TESTS_SOURCES += \
@@ -44,4 +46,19 @@
$(addprefix lib/extensions/fpu/, \
fpu.c \
)
+
+TESTS_SOURCES += \
+ $(addprefix tftf/tests/doe_tests/, \
+ doe_helpers.c \
+ test_doe.c \
+ )
+
+TESTS_SOURCES += \
+ $(addprefix lib/pcie/, \
+ pcie.c \
+ pcie_doe.c \
+ )
+
+include lib/ext_mbedtls/mbedtls.mk
+
endif
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index f359e72..da88701 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ Copyright (c) 2021-2024, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
-->
@@ -76,6 +76,8 @@
function="host_realm_set_ripas" />
<testcase name="Realm reject set_ripas"
function="host_realm_reject_set_ripas" />
+ <testcase name="Realm FEAT_DoubleFault2"
+ function="host_test_feat_doublefault2" />
<!-- Test case related to SVE support and SIMD state -->
<testcase name="Check RMI reports proper SVE VL"
function="host_check_rmi_reports_proper_sve_vl" />
@@ -122,7 +124,21 @@
function="host_test_realm_no_lpa2_invalid_s2sz" />
<testcase name="Test Realm creation with LPA2 disabled but FEAT_LPA2 present on platform"
function="host_test_non_lpa2_realm_on_lpa2plat" />
+ <testcase name="Test Data bound with LPA2 disabled but FEAT_LPA2 present on platform"
+ function="host_test_data_bound_non_lpa2_realm_on_lpa2plat" />
<testcase name="Test Realm creation with LPA2 enabled but FEAT_LPA2 absent on platform"
function="host_test_lpa2_realm_on_non_lpa2plat" />
+ <!-- Test cases related to Attestation -->
+ <testcase name="Test realm attestation" function="host_realm_test_attestation" />
+ <testcase name="Test realm attestation fault"
+ function="host_realm_test_attestation_fault" />
+ <!-- Test case related to PCIE-DOE -->
+ <testcase name="PCI DOE Discovery"
+ function="doe_discovery_test" />
+ <testcase name="SPDM Get Version"
+ function="spdm_version_test" />
+ <!-- Invoke RMI calls related to PDEV management -->
+ <testcase name="Invoke RMI PDEV calls "
+ function="host_test_rmi_pdev_calls" />
</testsuite>
</testsuites>