Merge "feat: tftf realm extension"
diff --git a/Makefile b/Makefile
index 55f9690..4af1b2a 100644
--- a/Makefile
+++ b/Makefile
@@ -119,6 +119,7 @@
ifeq (${ARCH}-${PLAT},aarch64-fvp)
include spm/cactus_mm/cactus_mm.mk
include spm/quark/quark.mk
+include realm/realm.mk
endif
# cactus and ivy are supported on platforms: fvp, tc0
@@ -306,6 +307,11 @@
QUARK_ASFLAGS += ${COMMON_ASFLAGS}
QUARK_LDFLAGS += ${COMMON_LDFLAGS}
+REALM_SOURCES += ${LIBC_SRCS}
+REALM_CFLAGS += ${COMMON_CFLAGS} -fpie
+REALM_ASFLAGS += ${COMMON_ASFLAGS}
+REALM_LDFLAGS += ${COMMON_LDFLAGS} $(PIE_LDFLAGS)
+
.PHONY: locate-checkpatch
locate-checkpatch:
ifndef CHECKPATCH
@@ -382,6 +388,16 @@
quark:
@echo "ERROR: $@ is supported only on AArch64 FVP."
@exit 1
+
+.PHONY: realm
+realm:
+ @echo "ERROR: $@ is supported only on AArch64 FVP."
+ @exit 1
+
+.PHONY: pack_realm
+pack_realm:
+ @echo "Nothing to be done"
+ @exit 1
endif
ifneq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-tc0))
@@ -531,6 +547,15 @@
$(eval $(call MAKE_IMG,cactus))
$(eval $(call MAKE_IMG,ivy))
$(eval $(call MAKE_IMG,quark))
+ $(eval $(call MAKE_IMG,realm))
+endif
+
+ifeq (${ARCH}-${PLAT},aarch64-fvp)
+.PHONY : pack_realm
+pack_realm: realm tftf
+ @echo " PACK REALM PAYLOAD"
+ $(shell dd if=$(BUILD_PLAT)/realm.bin of=$(BUILD_PLAT)/tftf.bin obs=1 \
+ seek=$(TFTF_MAX_IMAGE_SIZE))
endif
ifeq (${ARCH}-${PLAT},aarch64-tc0)
@@ -569,7 +594,7 @@
.SILENT: help
help:
echo "usage: ${MAKE} PLAT=<${PLATFORMS}> \
-<all|tftf|ns_bl1u|ns_bl2u|cactus|ivy|quark|el3_payload|distclean|clean|checkcodebase|checkpatch|help_tests>"
+<all|tftf|ns_bl1u|ns_bl2u|cactus|ivy|quark|realm|pack_realm|el3_payload|distclean|clean|checkcodebase|checkpatch|help_tests>"
echo ""
echo "PLAT is used to specify which platform you wish to build."
echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
@@ -581,6 +606,8 @@
echo " ns_bl1u Build the NS_BL1U image"
echo " ns_bl2u Build the NS_BL2U image"
echo " cactus Build the Cactus image (Test S-EL0 payload) and resource description."
+ echo " realm Build the Realm image (Test R-EL1 payload)."
+ echo " pack_realm Pack the realm image to tftf.bin."
echo " cactus_mm Build the Cactus-MM image (Test S-EL0 payload)."
echo " ivy Build the Ivy image (Test S-EL0 payload) and resource description."
echo " quark Build the Quark image (Test S-EL0 payload) and resource description."
diff --git a/include/common/debug.h b/include/common/debug.h
index 4b30175..6025590 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2014-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,6 +24,11 @@
void mp_printf(const char *fmt, ...);
#endif /* IMAGE_CACTUS_MM */
+#ifdef IMAGE_REALM
+void realm_printf(const char *fmt, ...);
+#define mp_printf realm_printf
+#endif
+
/*
* The log output macros print output to the console. These macros produce
* compiled log output only if the LOG_LEVEL defined in the makefile (or the
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index a4b7d7d..230d69a 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -505,6 +505,50 @@
#define CNTP_CTL_IMASK_MASK U(1)
#define CNTP_CTL_ISTATUS_MASK U(1)
+/* Exception Syndrome register bits and bobs */
+#define ESR_EC_SHIFT U(26)
+#define ESR_EC_MASK U(0x3f)
+#define ESR_EC_LENGTH U(6)
+#define ESR_ISS_SHIFT U(0x0)
+#define ESR_ISS_MASK U(0x1ffffff)
+#define EC_UNKNOWN U(0x0)
+#define EC_WFE_WFI U(0x1)
+#define EC_CP15_MRC_MCR U(0x3)
+#define EC_CP15_MRRC_MCRR U(0x4)
+#define EC_CP14_MRC_MCR U(0x5)
+#define EC_CP14_LDC_STC U(0x6)
+#define EC_FP_SIMD U(0x7)
+#define EC_CP10_MRC U(0x8)
+#define EC_CP14_MRRC_MCRR U(0xc)
+#define EC_ILLEGAL U(0xe)
+#define EC_SVC U(0x11)
+#define EC_HVC U(0x12)
+#define EC_SMC U(0x13)
+#define EC_IABORT_LOWER_EL U(0x20)
+#define EC_IABORT_CUR_EL U(0x21)
+#define EC_PC_ALIGN U(0x22)
+#define EC_DABORT_LOWER_EL U(0x24)
+#define EC_DABORT_CUR_EL U(0x25)
+#define EC_SP_ALIGN U(0x26)
+#define EC_FP U(0x28)
+#define EC_SERROR U(0x2f)
+/* Data Fault Status code, not all error codes listed */
+#define ISS_DFSC_MASK U(0x3f)
+#define DFSC_EXT_DABORT U(0x10)
+#define DFSC_GPF_DABORT U(0x28)
+/* ISS encoding an exception from HVC or SVC instruction execution */
+#define ISS_HVC_SMC_IMM16_MASK U(0xffff)
+
+/*
+ * External Abort bit in Instruction and Data Aborts synchronous exception
+ * syndromes.
+ */
+#define ESR_ISS_EABORT_EA_BIT U(9)
+
+#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK)
+#define ISS_BITS(x) (((x) >> ESR_ISS_SHIFT) & ESR_ISS_MASK)
+
+
/* MAIR macros */
#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << U(3)))
#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << U(3)))
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 534e1cf..e436e6b 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -717,6 +717,8 @@
#define ISS_DFSC_MASK U(0x3f)
#define DFSC_EXT_DABORT U(0x10)
#define DFSC_GPF_DABORT U(0x28)
+/* ISS encoding an exception from HVC or SVC instruction execution */
+#define ISS_HVC_SMC_IMM16_MASK U(0xffff)
/*
* External Abort bit in Instruction and Data Aborts synchronous exception
diff --git a/include/lib/heap/page_alloc.h b/include/lib/heap/page_alloc.h
new file mode 100644
index 0000000..7580b78
--- /dev/null
+++ b/include/lib/heap/page_alloc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PAGE_ALLOC_H
+#define PAGE_ALLOC_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define HEAP_NULL_PTR 0U
+#define HEAP_INVALID_LEN -1
+#define HEAP_OUT_OF_RANGE -2
+#define HEAP_INIT_FAILED -3
+#define HEAP_INIT_SUCCESS 0
+
+/*
+ * Initialize the memory heap space to be used
+ * @heap_base: heap base address
+ * @heap_len: heap size for use
+ */
+int page_pool_init(uint64_t heap_base, uint64_t heap_len);
+
+/*
+ * Return the pointer to the allocated pages
+ * @bytes_size: pages to allocate in byte unit
+ */
+void *page_alloc(u_register_t bytes_size);
+
+/*
+ * Reset heap memory usage cursor to heap base address
+ */
+void page_pool_reset(void);
+void page_free(u_register_t ptr);
+
+#endif /* PAGE_ALLOC_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 78d4131..9638495 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -162,4 +162,20 @@
#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory")
+#define MASK(regfield) \
+ ((~0ULL >> (64ULL - (regfield##_WIDTH))) << (regfield##_SHIFT))
+
+#define EXTRACT(regfield, reg) \
+ (((reg) & MASK(regfield)) >> (regfield##_SHIFT))
+
+/*
+ * Defines member of structure and reserves space
+ * for the next member with specified offset.
+ */
+#define SET_MEMBER(member, start, end) \
+ union { \
+ member; \
+ unsigned char reserved##end[end - start]; \
+ }
+
#endif /* UTILS_DEF_H */
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 1fd3c83..ba0559c 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -179,4 +179,24 @@
#define XN_SHIFT 54
#define UXN_SHIFT XN_SHIFT
+/*
+ * Stage 2 translation Lower attributes
+ */
+#define S2TTE_AP_SHIFT 6
+#define S2TTE_AP_RW (3UL << S2TTE_AP_SHIFT)
+
+#define S2TTE_SH_SHIFT 8
+#define S2TTE_SH_MASK (3UL << S2TTE_SH_SHIFT)
+#define S2TTE_SH_NS (0UL << S2TTE_SH_SHIFT)
+#define S2TTE_SH_OS (2UL << S2TTE_SH_SHIFT)
+#define S2TTE_SH_IS (3UL << S2TTE_SH_SHIFT)
+
+/*
+ * Attributes when FEAT_S2FWB is enabled at EL2 (HCR_EL2.FWB == 1).
+ * For Normal WB cacheability attribute, set bit[4] to 1 and bits[3:2] to 0b10.
+ */
+#define S2TTE_MEMATTR_FWB_NORMAL_WB ((1UL << 4) | (2UL << 2))
+#define S2TTE_ATTR_FWB_WB_RW (S2TTE_MEMATTR_FWB_NORMAL_WB | S2TTE_AP_RW | \
+ S2TTE_SH_IS)
+
#endif /* XLAT_TABLES_DEFS_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
new file mode 100644
index 0000000..a103630
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_realm_helper.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef HOST_REALM_HELPER_H
+#define HOST_REALM_HELPER_H
+
+#include <host_realm_rmi.h>
+
+bool host_create_realm_payload(u_register_t realm_payload_adr,
+ u_register_t plat_mem_pool_adr,
+ u_register_t plat_mem_pool_size,
+ u_register_t realm_pages_size);
+bool host_create_shared_mem(
+ u_register_t ns_shared_mem_adr,
+ u_register_t ns_shared_mem_size);
+bool host_destroy_realm(void);
+bool host_enter_realm_execute(uint8_t cmd);
+
+#endif /* HOST_REALM_HELPER_H */
+
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
new file mode 100644
index 0000000..2c5a605
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HOST_REALM_MEM_LAYOUT_H
+#define HOST_REALM_MEM_LAYOUT_H
+
+#include <realm_def.h>
+
+#include <platform_def.h>
+
+/*
+ * Realm payload Memory Usage Layout
+ *
+ * +--------------------------+ +---------------------------+
+ * | | | Host Image |
+ * | TFTF | | (TFTF_MAX_IMAGE_SIZE) |
+ * | Normal World | ==> +---------------------------+
+ * | Image | | Realm Image |
+ * | (MAX_NS_IMAGE_SIZE) | | (REALM_MAX_LOAD_IMG_SIZE |
+ * +--------------------------+ +---------------------------+
+ * | Memory Pool | | Heap Memory |
+ * | (NS_REALM_SHARED_MEM_SIZE| | (PAGE_POOL_MAX_SIZE) |
+ * | + PAGE_POOL_MAX_SIZE) | ==> | |
+ * | | | |
+ * | | +---------------------------+
+ * | | | Shared Region |
+ * | | | (NS_REALM_SHARED_MEM_SIZE)|
+ * +--------------------------+ +---------------------------+
+ *
+ */
+
+/*
+ * Default values defined in platform.mk, and can be provided as build arguments
+ * TFTF_MAX_IMAGE_SIZE: 1mb
+ */
+
+#ifdef TFTF_MAX_IMAGE_SIZE
+/* 1MB for shared buffer between Realm and Host*/
+ #define NS_REALM_SHARED_MEM_SIZE U(0x100000)
+/* 3MB of memory used as a pool for realm's objects creation*/
+ #define PAGE_POOL_MAX_SIZE U(0x300000)
+/* Base address of each section */
+ #define REALM_IMAGE_BASE (TFTF_BASE + TFTF_MAX_IMAGE_SIZE)
+ #define PAGE_POOL_BASE (REALM_IMAGE_BASE + REALM_MAX_LOAD_IMG_SIZE)
+ #define NS_REALM_SHARED_MEM_BASE (PAGE_POOL_BASE + PAGE_POOL_MAX_SIZE)
+#else
+ #define NS_REALM_SHARED_MEM_SIZE 0U
+ #define PAGE_POOL_MAX_SIZE 0U
+ #define TFTF_MAX_IMAGE_SIZE DRAM_SIZE
+/* Base address of each section */
+ #define REALM_IMAGE_BASE 0U
+ #define PAGE_POOL_BASE 0U
+ #define NS_REALM_SHARED_MEM_BASE 0U
+#endif
+
+#endif /* HOST_REALM_MEM_LAYOUT_H */
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
new file mode 100644
index 0000000..4e5f8c6
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HOST_REALM_RMI_H
+#define HOST_REALM_RMI_H
+
+#include <stdint.h>
+
+#include <realm_rsi.h>
+#include <smccc.h>
+#include <utils_def.h>
+
+#define RMI_FNUM_MIN_VALUE U(0x150)
+#define RMI_FNUM_MAX_VALUE U(0x18F)
+
+/* Get RMI fastcall std FID from offset */
+#define SMC64_RMI_FID(_offset) \
+ ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ (SMC_64 << FUNCID_CC_SHIFT) | \
+ (OEN_STD_START << FUNCID_OEN_SHIFT) | \
+ (((RMI_FNUM_MIN_VALUE + (_offset)) & FUNCID_NUM_MASK) \
+ << FUNCID_NUM_SHIFT))
+
+#define RMI_ABI_VERSION_GET_MAJOR(_version) (((_version) >> 16U) & 0x8FFF)
+#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1U)
+#define ALIGN(x, a) __ALIGN((x), (a))
+
+/*
+ * SMC_RMM_INIT_COMPLETE is the only function in the RMI that originates from
+ * the Realm world and is handled by the RMMD. The remaining functions are
+ * always invoked by the Normal world, forwarded by RMMD and handled by the
+ * RMM
+ */
+/* RMI SMC64 FIDs handled by the RMMD */
+/* no parameters */
+#define RMI_VERSION SMC64_RMI_FID(U(0x0))
+
+/*
+ * arg0 == target granule address
+ */
+#define RMI_GRANULE_DELEGATE SMC64_RMI_FID(U(0x1))
+
+/*
+ * arg0 == target granule address
+ */
+#define RMI_GRANULE_UNDELEGATE SMC64_RMI_FID(U(0x2))
+
+/*
+ * arg0 == data address
+ * arg1 == RD address
+ * arg2 == map address
+ * arg3 == SRC address
+ */
+#define RMI_DATA_CREATE SMC64_RMI_FID(U(0x3))
+
+/*
+ * arg0 == data address
+ * arg1 == RD address
+ * arg2 == map address
+ */
+#define RMI_DATA_CREATE_UNKNOWN SMC64_RMI_FID(U(0x4))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ */
+#define RMI_DATA_DESTROY SMC64_RMI_FID(U(0x5))
+
+/*
+ * arg0 == RD address
+ */
+#define RMI_REALM_ACTIVATE SMC64_RMI_FID(U(0x7))
+
+/*
+ * arg0 == RD address
+ * arg1 == struct rmi_realm_params addr
+ */
+#define RMI_REALM_CREATE SMC64_RMI_FID(U(0x8))
+
+/*
+ * arg0 == RD address
+ */
+#define RMI_REALM_DESTROY SMC64_RMI_FID(U(0x9))
+
+/*
+ * arg0 == REC address
+ * arg1 == RD address
+ * arg2 == struct rmm_rec address
+ */
+#define RMI_REC_CREATE SMC64_RMI_FID(U(0xA))
+
+/*
+ * arg0 == REC address
+ */
+#define RMI_REC_DESTROY SMC64_RMI_FID(U(0xB))
+
+/*
+ * arg0 == rec address
+ * arg1 == rec_run address
+ */
+#define RMI_REC_ENTER SMC64_RMI_FID(U(0xC))
+
+/*
+ * arg0 == RTT address
+ * arg1 == RD address
+ * arg2 == map address
+ * arg3 == level
+ */
+#define RMI_RTT_CREATE SMC64_RMI_FID(U(0xD))
+
+/*
+ * arg0 == RTT address
+ * arg1 == RD address
+ * arg2 == map address
+ * arg3 == level
+ */
+#define RMI_RTT_DESTROY SMC64_RMI_FID(U(0xE))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == s2tte
+ */
+#define RMI_RTT_MAP_UNPROTECTED SMC64_RMI_FID(U(0xF))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * ret1 == level
+ * ret2 == s2tte type
+ * ret3 == s2tte
+ * ret4 == ripas
+ */
+#define RMI_RTT_READ_ENTRY SMC64_RMI_FID(U(0x11))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ */
+#define RMI_RTT_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x12))
+
+/*
+ * arg0 == calling rec address
+ * arg1 == target rec address
+ */
+#define RMI_PSCI_COMPLETE SMC64_RMI_FID(U(0x14))
+
+/*
+ * arg0 == Feature register index
+ */
+#define RMI_FEATURES SMC64_RMI_FID(U(0x15))
+
+/*
+ * arg0 == RTT address
+ * arg1 == RD address
+ * arg2 == map address
+ * arg3 == level
+ */
+#define RMI_RTT_FOLD SMC64_RMI_FID(U(0x16))
+
+/*
+ * arg0 == RD address
+ */
+#define RMI_REC_AUX_COUNT SMC64_RMI_FID(U(0x17))
+
+/*
+ * arg1 == RD address
+ * arg2 == map address
+ * arg3 == level
+ */
+#define RMI_RTT_INIT_RIPAS SMC64_RMI_FID(U(0x18))
+
+/*
+ * arg0 == RD address
+ * arg1 == REC address
+ * arg2 == map address
+ * arg3 == level
+ * arg4 == ripas
+ */
+#define RMI_RTT_SET_RIPAS SMC64_RMI_FID(U(0x19))
+
+#define GRANULE_SIZE PAGE_SIZE_4KB
+
+/* Maximum number of auxiliary granules required for a REC */
+#define MAX_REC_AUX_GRANULES 16U
+#define REC_PARAMS_AUX_GRANULES 16U
+#define REC_EXIT_NR_GPRS 31U
+/* Size of Realm Personalization Value */
+#define RPV_SIZE 64U
+/* RmiDisposeResponse types */
+#define RMI_DISPOSE_ACCEPT 0U
+#define RMI_DISPOSE_REJECT 1U
+
+/* RmiFeatureLpa2 types */
+#define RMI_NO_LPA2 0U
+#define RMI_LPA2 1U
+
+/* RmiInterfaceVersion type */
+#define RMI_MAJOR_VERSION 0U
+#define RMI_MINOR_VERSION 0U
+
+/* RmiRealmMeasurementAlgorithm types */
+#define RMI_HASH_SHA_256 0U
+#define RMI_HASH_SHA_512 1U
+
+/* RmiRecEmulatedMmio types */
+#define RMI_NOT_EMULATED_MMIO 0U
+#define RMI_EMULATED_MMIO 1U
+
+/*
+ * RmiRecExitReason represents the reason for a REC exit.
+ * This is returned to NS hosts via RMI_REC_ENTER::run_ptr.
+ */
+#define RMI_EXIT_SYNC 0U
+#define RMI_EXIT_IRQ 1U
+#define RMI_EXIT_FIQ 2U
+#define RMI_EXIT_PSCI 3U
+#define RMI_EXIT_RIPAS_CHANGE 4U
+#define RMI_EXIT_HOST_CALL 5U
+#define RMI_EXIT_SERROR 6U
+#define RMI_EXIT_INVALID 0xFFFFFU
+
+/* RmiRecRunnable types */
+#define RMI_NOT_RUNNABLE 0U
+#define RMI_RUNNABLE 1U
+
+/* RttEntryState: represents the state of an RTTE */
+#define RMI_UNASSIGNED 0U
+#define RMI_DESTROYED 1U
+#define RMI_ASSIGNED 2U
+#define RMI_TABLE 3U
+#define RMI_VALID_NS 4U
+
+#define RMI_FEATURE_REGISTER_0_S2SZ GENMASK(7, 0)
+#define RMI_FEATURE_REGISTER_0_LPA2 BIT(8)
+#define RMI_FEATURE_REGISTER_0_SVE_EN BIT(9)
+#define RMI_FEATURE_REGISTER_0_SVE_VL GENMASK(13, 10)
+#define RMI_FEATURE_REGISTER_0_NUM_BPS GENMASK(17, 14)
+#define RMI_FEATURE_REGISTER_0_NUM_WPS GENMASK(21, 18)
+#define RMI_FEATURE_REGISTER_0_PMU_EN BIT(22)
+#define RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS GENMASK(27, 23)
+#define RMI_FEATURE_REGISTER_0_HASH_SHA_256 BIT(28)
+#define RMI_FEATURE_REGISTER_0_HASH_SHA_512 BIT(29)
+
+#define RMM_FEATURE_MIN_IPA_SIZE 32U
+#define RMM_FEATURE_REGISTER_0_INDEX 0UL
+#define RMM_FEATURE_REGISTER_0_S2SZ_SHIFT 0UL
+#define RMM_FEATURE_REGISTER_0_S2SZ_WIDTH 8UL
+#define RMM_FEATURE_REGISTER_0_LPA2_SHIFT 8UL
+#define RMM_FEATURE_REGISTER_0_LPA2_WIDTH 1UL
+
+/* RmiStatusCode types */
+/*
+ * Status codes which can be returned from RMM commands.
+ *
+ * For each code, the meaning of return_code_t::index is stated.
+ */
+typedef enum {
+ /*
+ * Command completed successfully.
+ *
+ * index is zero.
+ */
+ RMI_SUCCESS = 0,
+ /*
+ * The value of a command input value caused the command to fail.
+ *
+ * index is zero.
+ */
+ RMI_ERROR_INPUT = 1,
+ /*
+ * An attribute of a Realm does not match the expected value.
+ *
+ * index varies between usages.
+ */
+ RMI_ERROR_REALM = 2,
+ /*
+ * An attribute of a REC does not match the expected value.
+ *
+ * index is zero.
+ */
+ RMI_ERROR_REC = 3,
+ /*
+ * An RTT walk terminated before reaching the target RTT level,
+ * or reached an RTTE with an unexpected value.
+ *
+ * index: RTT level at which the walk terminated
+ */
+ RMI_ERROR_RTT = 4,
+ /*
+ * An operation cannot be completed because a resource is in use.
+ *
+ * index is zero.
+ */
+ RMI_ERROR_IN_USE = 5,
+ RMI_ERROR_COUNT
+} status_t;
+
+#define RMI_RETURN_STATUS(ret) ((ret) & 0xFF)
+#define RMI_RETURN_INDEX(ret) (((ret) >> 8U) & 0xFF)
+#define RTT_MAX_LEVEL 3U
+#define ALIGN_DOWN(x, a) ((uint64_t)(x) & ~(((uint64_t)(a)) - 1ULL))
+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1U)) == 0U)
+#define PAGE_SHIFT FOUR_KB_SHIFT
+#define RTT_LEVEL_SHIFT(l) XLAT_ADDR_SHIFT(l)
+#define RTT_L2_BLOCK_SIZE (1UL << RTT_LEVEL_SHIFT(2U))
+
+#define REC_CREATE_NR_GPRS 8U
+#define REC_HVC_NR_GPRS 7U
+#define REC_GIC_NUM_LRS 16U
+
+/*
+ * The error code 0x201 is the packed version of the
+ * rmm error {RMM_STATUS_ERROR_INPUT,2U}
+ * happened when Granule(params_ptr).pas != NS
+ */
+#define RMM_STATUS_ERROR_INPUT 0x201UL
+
+/*
+ * The Realm attribute parameters are shared by the Host via
+ * RMI_REALM_CREATE::params_ptr. The values can be observed or modified
+ * either by the Host or by the Realm.
+ */
+struct rmi_realm_params {
+ /* Realm feature register 0 */
+ SET_MEMBER(u_register_t features_0, 0, 0x100); /* Offset 0 */
+ /* Measurement algorithm */
+ SET_MEMBER(unsigned char hash_algo, 0x100, 0x400); /* 0x100 */
+ /* Realm Personalization Value */
+ 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);
+};
+
+/*
+ * The REC attribute parameters are shared by the Host via
+ * MI_REC_CREATE::params_ptr. The values can be observed or modified
+ * either by the Host or by the Realm which owns the REC.
+ */
+struct rmi_rec_params {
+ /* Flags */
+ SET_MEMBER(u_register_t flags, 0, 0x100); /* Offset 0 */
+ /* MPIDR of the REC */
+ SET_MEMBER(u_register_t mpidr, 0x100, 0x200); /* 0x100 */
+ /* Program counter */
+ SET_MEMBER(u_register_t pc, 0x200, 0x300); /* 0x200 */
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[REC_CREATE_NR_GPRS], 0x300, 0x800); /* 0x300 */
+ SET_MEMBER(struct {
+ /* Number of auxiliary Granules */
+ u_register_t num_aux; /* 0x800 */
+ /* Addresses of auxiliary Granules */
+ u_register_t aux[MAX_REC_AUX_GRANULES]; /* 0x808 */
+ }, 0x800, 0x1000);
+};
+
+/*
+ * Structure contains data passed from the Host to the RMM on REC entry
+ */
+struct rmi_rec_entry {
+ /* Flags */
+ SET_MEMBER(u_register_t flags, 0, 0x200); /* Offset 0 */
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[REC_EXIT_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[REC_GIC_NUM_LRS]; /* 0x308 */
+ }, 0x300, 0x800);
+};
+
+/*
+ * Structure contains data passed from the RMM to the Host on REC exit
+ */
+struct rmi_rec_exit {
+ /* Exit reason */
+ SET_MEMBER(u_register_t exit_reason, 0, 0x100);/* Offset 0 */
+ SET_MEMBER(struct {
+ /* Exception Syndrome Register */
+ u_register_t esr; /* 0x100 */
+ /* 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[REC_EXIT_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[REC_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, 0x400);
+ SET_MEMBER(struct {
+ /* Counter-timer Physical Timer Control Register */
+ u_register_t cntp_ctl; /* 0x400 */
+ /* Counter-timer Physical Timer CompareValue Register */
+ u_register_t cntp_cval; /* 0x408 */
+ /* Counter-timer Virtual Timer Control Register */
+ u_register_t cntv_ctl; /* 0x410 */
+ /* Counter-timer Virtual Timer CompareValue Register */
+ u_register_t cntv_cval; /* 0x418 */
+ }, 0x400, 0x500);
+ SET_MEMBER(struct {
+ /* Base address of pending RIPAS change */
+ u_register_t ripas_base; /* 0x500 */
+ /* Size of pending RIPAS change */
+ u_register_t ripas_size; /* 0x508 */
+ /* RIPAS value of pending RIPAS change */
+ unsigned char ripas_value; /* 0x510 */
+ }, 0x500, 0x600);
+ /* Host call immediate value */
+ SET_MEMBER(unsigned int imm, 0x600, 0x800); /* 0x600 */
+};
+
+/*
+ * Structure contains shared information between RMM and Host
+ * during REC entry and REC exit.
+ */
+struct rmi_rec_run {
+ /* Entry information */
+ SET_MEMBER(struct rmi_rec_entry entry, 0, 0x800); /* Offset 0 */
+ /* Exit information */
+ SET_MEMBER(struct rmi_rec_exit exit, 0x800, 0x1000); /* 0x800 */
+};
+
+struct rtt_entry {
+ uint64_t walk_level;
+ uint64_t out_addr;
+ int state;
+};
+
+enum realm_state {
+ REALM_STATE_NULL,
+ REALM_STATE_NEW,
+ REALM_STATE_ACTIVE,
+ REALM_STATE_SYSTEM_OFF
+};
+
+struct realm {
+ u_register_t par_base;
+ u_register_t par_size;
+ u_register_t rd;
+ u_register_t rtt_addr;
+ u_register_t rec;
+ u_register_t run;
+ u_register_t num_aux;
+ u_register_t rmm_feat_reg0;
+ u_register_t ipa_ns_buffer;
+ u_register_t ns_buffer_size;
+ u_register_t aux_pages[REC_PARAMS_AUX_GRANULES];
+ enum realm_state state;
+};
+
+/* RMI/SMC */
+u_register_t rmi_version(void);
+u_register_t rmi_granule_delegate(u_register_t addr);
+u_register_t rmi_granule_undelegate(u_register_t addr);
+u_register_t rmi_realm_create(u_register_t rd, u_register_t params_ptr);
+u_register_t rmi_realm_destroy(u_register_t rd);
+u_register_t rmi_features(u_register_t index, u_register_t *features);
+
+/* Realm management */
+u_register_t realm_map_protected_data_unknown(struct realm *realm,
+ u_register_t target_pa,
+ u_register_t map_size);
+u_register_t realm_create(struct realm *realm);
+u_register_t realm_map_payload_image(struct realm *realm,
+ u_register_t realm_payload_adr);
+u_register_t realm_map_ns_shared(struct realm *realm,
+ u_register_t ns_shared_mem_adr,
+ u_register_t ns_shared_mem_size);
+u_register_t realm_rec_create(struct realm *realm);
+u_register_t realm_activate(struct realm *realm);
+u_register_t realm_destroy(struct realm *realm);
+u_register_t realm_rec_enter(struct realm *realm, u_register_t *exit_reason,
+ unsigned int *test_result);
+u_register_t realm_init_ipa_state(struct realm *realm,
+ u_register_t level,
+ u_register_t start,
+ uint64_t end);
+
+
+#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
new file mode 100644
index 0000000..9c9cc8c
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HOST_SHARED_DATA_H
+#define HOST_SHARED_DATA_H
+
+#include <stdint.h>
+#include <spinlock.h>
+
+#define MAX_BUF_SIZE 10240U
+#define MAX_DATA_SIZE 5U
+
+/*
+ * This structure maps the shared memory to be used between the Host and Realm
+ * payload
+ */
+typedef struct host_shared_data {
+ /* Buffer used from Realm for logging*/
+ uint8_t log_buffer[MAX_BUF_SIZE];
+
+ /* Command set from Host and used by Realm*/
+ uint8_t realm_cmd;
+
+ /* array of params passed from Host to Realm*/
+ u_register_t host_param_val[MAX_DATA_SIZE];
+
+ /* array of output results passed from Realm to Host*/
+ u_register_t realm_out_val[MAX_DATA_SIZE];
+
+ /* Lock to avoid concurrent accesses to log_buffer */
+ spinlock_t printf_lock;
+} host_shared_data_t;
+
+/*
+ * Different commands that the Host can requests the Realm to perform
+ */
+enum realm_cmd {
+ REALM_SLEEP_CMD = 1U,
+ REALM_GET_RSI_VERSION
+};
+
+/*
+ * Index values for each parameter in the host_param_val array.
+ */
+enum host_param_index {
+ HOST_CMD_INDEX = 0U,
+ HOST_SLEEP_INDEX
+};
+/*
+ * Return shared buffer pointer mapped as host_shared_data_t structure
+ */
+host_shared_data_t *host_get_shared_structure(void);
+/*
+ * Set data to be shared from Host to realm
+ */
+void realm_shared_data_set_host_val(uint8_t index, u_register_t val);
+
+/*
+ * Set guest mapped shared buffer pointer
+ */
+void realm_set_shared_structure(host_shared_data_t *ptr);
+
+/*
+ * Get guest mapped shared buffer pointer
+ */
+host_shared_data_t *realm_get_shared_structure(void);
+
+/*
+ * Set data to be shared from Realm to Host
+ */
+void realm_shared_data_set_realm_val(uint8_t index, u_register_t val);
+
+/*
+ * Return Host's data at index
+ */
+u_register_t realm_shared_data_get_host_val(uint8_t index);
+
+/*
+ * Return Realm's data at index
+ */
+u_register_t realm_shared_data_get_realm_val(uint8_t index);
+
+/*
+ * Clear shared realm data
+ */
+void realm_shared_data_clear_realm_val(void);
+
+/*
+ * Clear shared Host data
+ */
+void realm_shared_data_clear_host_val(void);
+
+/*
+ * Get command sent from Host to realm
+ */
+uint8_t realm_shared_data_get_realm_cmd(void);
+
+/*
+ * Set command to be send from Host to realm
+ */
+void realm_shared_data_set_realm_cmd(uint8_t cmd);
+
+#endif /* HOST_SHARED_DATA_H */
diff --git a/include/runtime_services/host_realm_managment/realm_def.h b/include/runtime_services/host_realm_managment/realm_def.h
new file mode 100644
index 0000000..22cd380
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/realm_def.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REALM_DEF_H
+#define REALM_DEF_H
+
+#include <xlat_tables_defs.h>
+
+/* 1mb 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
+#define DATA_PATTERN_2 0x11223344U
+#define REALM_SUCCESS 0U
+#define REALM_ERROR 1U
+
+/* Only support 4KB at the moment */
+
+#if (PAGE_SIZE == PAGE_SIZE_4KB)
+#define PAGE_ALIGNMENT PAGE_SIZE_4KB
+#define TCR_TG0 TCR_TG0_4K
+#else
+#error "Undefined value for PAGE_SIZE"
+#endif
+
+#endif /* REALM_DEF_H */
diff --git a/include/runtime_services/host_realm_managment/rmi_spm_tests.h b/include/runtime_services/host_realm_managment/rmi_spm_tests.h
new file mode 100644
index 0000000..11c8c12
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/rmi_spm_tests.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef REALM_PAYLOAD_TEST_H
+#define REALM_PAYLOAD_TEST_H
+
+#define NUM_GRANULES 5U
+#define NUM_RANDOM_ITERATIONS 7U
+#define B_DELEGATED 0U
+#define B_UNDELEGATED 1U
+#define NUM_CPU_DED_SPM PLATFORM_CORE_COUNT / 2U
+
+#endif /* REALM_PAYLOAD_TEST_H */
diff --git a/include/runtime_services/realm_payload/realm_payload_test.h b/include/runtime_services/realm_payload/realm_payload_test.h
deleted file mode 100644
index 048dda1..0000000
--- a/include/runtime_services/realm_payload/realm_payload_test.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <smccc.h>
-#include <tftf_lib.h>
-
-#define RMI_FNUM_MIN_VALUE U(0x150)
-#define RMI_FNUM_MAX_VALUE U(0x18F)
-
-/* Get RMI fastcall std FID from offset */
-#define SMC64_RMI_FID(_offset) \
- ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
- (SMC_64 << FUNCID_CC_SHIFT) | \
- (OEN_STD_START << FUNCID_OEN_SHIFT) | \
- (((RMI_FNUM_MIN_VALUE + (_offset)) & FUNCID_NUM_MASK) \
- << FUNCID_NUM_SHIFT))
-
-/* RMI SMC64 FIDs handled by the RMMD */
-#define RMI_RMM_REQ_VERSION SMC64_RMI_FID(U(0))
-#define SMC_RMM_GRANULE_DELEGATE SMC64_RMI_FID(U(1))
-#define SMC_RMM_GRANULE_UNDELEGATE SMC64_RMI_FID(U(2))
-#define SMC_RMM_REALM_CREATE SMC64_RMI_FID(U(8))
-#define SMC_RMM_REALM_DESTROY SMC64_RMI_FID(U(9))
-
-#define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
-#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
-
-#define NUM_GRANULES 5
-#define NUM_RANDOM_ITERATIONS 7
-#define GRANULE_SIZE 4096
-
-#define B_DELEGATED 0
-#define B_UNDELEGATED 1
-
-#define NUM_CPU_DED_SPM PLATFORM_CORE_COUNT / 2
-/*
- * The error code 513 is the packed version of the
- * rmm error {RMM_STATUS_ERROR_INPUT,2}
- * happened when Granule(params_ptr).pas != NS
- */
-#define RMM_STATUS_ERROR_INPUT 513UL
-u_register_t realm_version(void);
-u_register_t realm_granule_delegate(uintptr_t);
-u_register_t realm_granule_undelegate(uintptr_t);
-u_register_t realm_create(uintptr_t, uintptr_t);
-u_register_t realm_destroy(uintptr_t);
\ No newline at end of file
diff --git a/lib/heap/page_alloc.c b/lib/heap/page_alloc.c
new file mode 100644
index 0000000..c1b54c8
--- /dev/null
+++ b/lib/heap/page_alloc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <debug.h>
+#include <heap/page_alloc.h>
+#include <spinlock.h>
+#include <utils_def.h>
+
+#include <platform_def.h>
+
+static uint64_t memory_used;
+static uint64_t heap_base_addr;
+static u_register_t heap_addr;
+static uint64_t heap_size;
+static bool heap_initialised = HEAP_INIT_FAILED;
+static spinlock_t mem_lock;
+
+/*
+ * Initialize the memory heap space to be used
+ * @heap_base: heap base address
+ * @heap_len: heap size for use
+ */
+int page_pool_init(uint64_t heap_base, uint64_t heap_len)
+{
+ const uint64_t plat_max_addr = (uint64_t)DRAM_BASE + (uint64_t)DRAM_SIZE;
+ uint64_t max_addr = heap_base + heap_len;
+
+ if (heap_len == 0ULL) {
+ ERROR("heap_len must be non-zero value\n");
+ heap_initialised = HEAP_INVALID_LEN;
+ } else if (max_addr >= plat_max_addr) {
+ ERROR("heap_base + heap[0x%llx] must not exceed platform"
+ "max address[0x%llx]\n", max_addr, plat_max_addr);
+
+ heap_initialised = HEAP_OUT_OF_RANGE;
+ } else {
+ heap_base_addr = heap_base;
+ memory_used = heap_base;
+ heap_size = heap_len;
+ heap_initialised = HEAP_INIT_SUCCESS;
+ }
+ return heap_initialised;
+}
+
+/*
+ * Return the pointer to the allocated pages
+ * @bytes_size: pages to allocate in byte unit
+ */
+void *page_alloc(u_register_t bytes_size)
+{
+ if (heap_initialised != HEAP_INIT_SUCCESS) {
+ ERROR("heap need to be initialised first\n");
+ return HEAP_NULL_PTR;
+ }
+ if (bytes_size == 0UL) {
+ ERROR("bytes_size must be non-zero value\n");
+ return HEAP_NULL_PTR;
+ }
+
+ spin_lock(&mem_lock);
+
+ if ((memory_used + bytes_size) >= (heap_base_addr + heap_size)) {
+ ERROR("Reached to max KB allowed[%llu]\n", (heap_size/1024U));
+ goto unlock_failed;
+ }
+ /* set pointer to current used heap memory cursor */
+ heap_addr = memory_used;
+ /* move used memory cursor by bytes_size */
+ memory_used += bytes_size;
+ spin_unlock(&mem_lock);
+
+ return (void *)heap_addr;
+
+unlock_failed:/* failed allocation */
+ spin_unlock(&mem_lock);
+ return HEAP_NULL_PTR;
+}
+
+/*
+ * Reset heap memory usage cursor to heap base address
+ */
+void page_pool_reset(void)
+{
+ /*
+ * No race condition here, only lead cpu running TFTF test case can
+ * reset the memory allocation
+ */
+ memory_used = heap_base_addr;
+}
+
+void page_free(u_register_t address)
+{
+ /* No memory free is needed in current TFTF test scenarios */
+}
diff --git a/lib/libc/snprintf.c b/lib/libc/snprintf.c
index 29c50df..6ad284f 100644
--- a/lib/libc/snprintf.c
+++ b/lib/libc/snprintf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,7 +9,6 @@
#include <stdlib.h>
#include <common/debug.h>
-#include <plat/common/platform.h>
#define get_num_va_args(_args, _lcount) \
(((_lcount) > 1) ? va_arg(_args, long long int) : \
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index e467cd6..cb1a37b 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -1,9 +1,12 @@
#
-# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
+# If not specified as build arguments, set default to 10 MB
+TFTF_MAX_IMAGE_SIZE:=10485760
+
# Default number of threads per CPU on FVP
FVP_MAX_PE_PER_CPU := 1
@@ -79,6 +82,7 @@
$(eval $(call add_define,TFTF_DEFINES,FVP_CLUSTER_COUNT))
$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_PE_PER_CPU))
+$(eval $(call add_define,TFTF_DEFINES,TFTF_MAX_IMAGE_SIZE))
# Default PA size for FVP platform
PA_SIZE := 34
@@ -88,6 +92,7 @@
$(eval $(call add_define,NS_BL1U_DEFINES,PA_SIZE))
$(eval $(call add_define,NS_BL2U_DEFINES,PA_SIZE))
$(eval $(call add_define,TFTF_DEFINES,PA_SIZE))
+$(eval $(call add_define,REALM_DEFINES,PA_SIZE))
PLAT_INCLUDES += -Iplat/arm/fvp/include/
diff --git a/realm/aarch64/realm_entrypoint.S b/realm/aarch64/realm_entrypoint.S
new file mode 100644
index 0000000..97c4ff5
--- /dev/null
+++ b/realm/aarch64/realm_entrypoint.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <realm_def.h>
+
+ .globl realm_entrypoint
+
+.section .bss.stacks
+ .fill REALM_STACK_SIZE
+stacks_end:
+
+func realm_entrypoint
+ /* Setup the stack pointer. */
+ adr x1, stacks_end
+ mov sp, x1
+
+ /* Clear BSS */
+ ldr x0, =__REALM_BSS_START__
+ adr x1, realm_entrypoint
+ add x0, x1, x0
+ ldr x1, =__REALM_BSS_SIZE__
+ bl zeromem16
+
+ /*
+ * Invalidate the data cache for the whole Realm.
+ * This prevents re-use of stale data cache entries from
+ * prior bootloader stages.
+ */
+ adrp x0, __REALM_TEXT_START__
+ add x0, x0, realm_entrypoint
+ adrp x1, __REALM_BSS_END__
+ add x1, x1, realm_entrypoint
+ sub x1, x1, x0
+ bl inv_dcache_range
+
+ /* Initialize architectural state. */
+ bl arch_init
+
+ /* Relocate symbols */
+pie_fixup:
+ ldr x0, =pie_fixup
+ and x0, x0, #~(PAGE_ALIGNMENT - 1)
+ mov x1, REALM_MAX_LOAD_IMG_SIZE
+ add x1, x1, x0
+ bl fixup_gdt_reloc
+
+ /* And jump to the C entrypoint. */
+ b realm_payload_main
+endfunc realm_entrypoint
+
+/* Initialize architectural state. */
+func arch_init
+ /* Set the exception vectors. */
+ adr x0, realm_vector
+ add x1, x1, :lo12:realm_vector
+ msr vbar_el1, x0
+ isb
+
+ /* Enable the instruction cache and stack pointer alignment checks. */
+ mov_imm x0, (SCTLR_EL1_RES1 | SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+ msr sctlr_el1, x0
+
+ /*
+ * Set CPACR_EL1.FPEN=11 no EL1/0 trapping of
+ * SVE/Adv. SIMD/FP instructions.
+ */
+ mov x1, CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)
+ mrs x0, cpacr_el1
+ orr x0, x0, x1
+ msr cpacr_el1, x0
+ isb
+
+ ret
+endfunc arch_init
diff --git a/realm/aarch64/realm_exceptions.S b/realm/aarch64/realm_exceptions.S
new file mode 100644
index 0000000..6ce8810
--- /dev/null
+++ b/realm/aarch64/realm_exceptions.S
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .globl realm_vector
+
+/*
+ * Exception vector code for unhandled exceptions.
+ * Print a crash dump on the UART and loops forever.
+ */
+.macro unhandled_exception name
+ vector_entry \name
+ b crash_dump
+ end_vector_entry \name
+.endm
+
+vector_base realm_vector
+
+ /*
+ * Current EL with SP0 : 0x0 - 0x200.
+ */
+unhandled_exception sync_sp0
+unhandled_exception irq_sp0
+unhandled_exception fiq_sp0
+unhandled_exception serr_sp0
+
+ /*
+ * Current EL with SPx : 0x200 - 0x400.
+ */
+vector_entry sync_spx
+ b sync_exception_vector_entry
+end_vector_entry sync_spx
+
+vector_entry irq_spx
+ b interrupt_vector_entry
+end_vector_entry irq_spx
+
+vector_entry fiq_spx
+ b interrupt_vector_entry
+end_vector_entry fiq_spx
+
+unhandled_exception serr_spx
+
+ /*
+ * Lower EL using AArch64 : 0x400 - 0x600.
+ */
+unhandled_exception sync_a64
+unhandled_exception irq_a64
+unhandled_exception fiq_a64
+unhandled_exception serr_a64
+
+ /*
+ * Lower EL using AArch32 : 0x600 - 0x800.
+ */
+unhandled_exception sync_a32
+unhandled_exception irq_a32
+unhandled_exception fiq_a32
+unhandled_exception serr_a32
+
+.macro save_gp_regs
+ stp x0, x1, [sp, #0x0]
+ stp x2, x3, [sp, #0x10]
+ stp x4, x5, [sp, #0x20]
+ stp x6, x7, [sp, #0x30]
+ stp x8, x9, [sp, #0x40]
+ stp x10, x11, [sp, #0x50]
+ stp x12, x13, [sp, #0x60]
+ stp x14, x15, [sp, #0x70]
+ stp x16, x17, [sp, #0x80]
+ stp x18, x19, [sp, #0x90]
+ stp x20, x21, [sp, #0xa0]
+ stp x22, x23, [sp, #0xb0]
+ stp x24, x25, [sp, #0xc0]
+ stp x26, x27, [sp, #0xd0]
+ stp x28, x29, [sp, #0xe0]
+ /* We push xzr simply to keep the stack 16-byte aligned. */
+ stp x30, xzr, [sp, #0xf0]
+.endm
+
+.macro restore_gp_regs
+ ldp x30, xzr, [sp, #0xf0]
+ ldp x28, x29, [sp, #0xe0]
+ ldp x26, x27, [sp, #0xd0]
+ ldp x24, x25, [sp, #0xc0]
+ ldp x22, x23, [sp, #0xb0]
+ ldp x20, x21, [sp, #0xa0]
+ ldp x18, x19, [sp, #0x90]
+ ldp x16, x17, [sp, #0x80]
+ ldp x14, x15, [sp, #0x70]
+ ldp x12, x13, [sp, #0x60]
+ ldp x10, x11, [sp, #0x50]
+ ldp x8, x9, [sp, #0x40]
+ ldp x6, x7, [sp, #0x30]
+ ldp x4, x5, [sp, #0x20]
+ ldp x2, x3, [sp, #0x10]
+ ldp x0, x1, [sp, #0x0]
+.endm
+
+func sync_exception_vector_entry
+ sub sp, sp, #0x100
+ save_gp_regs
+ mov x19, sp
+ bl tftf_sync_exception_handler
+ cbnz x0, 0f
+ mov x0, x19
+ /* Save original stack pointer value on the stack */
+ add x1, x0, #0x100
+ str x1, [x0, #0xf8]
+ b print_exception
+0: restore_gp_regs
+ add sp, sp, #0x100
+ eret
+endfunc sync_exception_vector_entry
+
+func interrupt_vector_entry
+ sub sp, sp, #0x100
+ save_gp_regs
+ bl realm_interrupt_handler
+ restore_gp_regs
+ add sp, sp, #0x100
+ eret
+endfunc interrupt_vector_entry
+
+func crash_dump
+ /* Save general-purpose registers on the stack. */
+ sub sp, sp, #0x100
+ save_gp_regs
+
+ /* Save original stack pointer value on the stack. */
+ add x1, sp, #0x100
+ str x1, [sp, #0xf8]
+
+ /* Print the saved CPU context on the UART. */
+ mov x0, sp
+ b print_exception
+endfunc crash_dump
diff --git a/realm/platform.h b/realm/platform.h
new file mode 100644
index 0000000..2c6ad27
--- /dev/null
+++ b/realm/platform.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REALM_PLATFORM_H
+#define REALM_PLATFORM_H
+
+/*
+ * Helper that returns a linear core ID from a MPID
+ * Need to provide a RSI_HOST_CALL to request this from Host platform.
+ */
+unsigned int platform_get_core_pos(u_register_t mpid)
+{
+ return 0U;
+}
+
+#endif /* REALM_PLATFORM_H */
diff --git a/realm/realm.ld.S b/realm/realm.ld.S
new file mode 100644
index 0000000..ca3b809
--- /dev/null
+++ b/realm/realm.ld.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+ENTRY(realm_entrypoint)
+
+#include <realm_def.h>
+
+MEMORY {
+
+ RAM (rwx): ORIGIN = 0x0, LENGTH = REALM_MAX_LOAD_IMG_SIZE
+}
+
+SECTIONS
+{
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "TEXT_START address is not aligned to PAGE_SIZE.")
+ .text : {
+ __REALM_TEXT_START__ = .;
+ *realm_entrypoint.o(.text*)
+ *(.text*)
+ *(.vectors)
+ . = NEXT(PAGE_SIZE);
+ __REALM_TEXT_END__ = .;
+ }> RAM
+
+ .rodata : {
+ . = ALIGN(PAGE_SIZE);
+ __REALM_RODATA_START__ = .;
+ *(.rodata*)
+
+ /*
+ * Keep the .got section in the RO section as it is patched
+ * prior to enabling the MMU and having the .got in RO is better for
+ * security. GOT is a table of addresses so ensure 8-byte alignment.
+ */
+ . = ALIGN(8);
+ __GOT_START__ = .;
+ *(.got)
+ __GOT_END__ = .;
+
+ . = NEXT(PAGE_SIZE);
+ __REALM_RODATA_END__ = .;
+
+ }> RAM
+
+ .data : {
+ . = ALIGN(PAGE_SIZE);
+ __REALM_DATA_START__ = .;
+ *(.data*)
+ . = ALIGN(PAGE_SIZE);
+ . = NEXT(PAGE_SIZE);
+ __REALM_DATA_END__ = .;
+ }> RAM
+
+ /*
+ * .rela.dyn needs to come after .data for the read-elf utility to parse
+ * this section correctly. Ensure 8-byte alignment so that the fields of
+ * RELA data structure are aligned.
+ */
+ . = ALIGN(8);
+ __RELA_START__ = .;
+ .rela.dyn . : {
+ }> RAM
+ __RELA_END__ = .;
+
+ .bss (NOLOAD) : {
+ . = ALIGN(PAGE_SIZE);
+ __REALM_BSS_START__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ . = NEXT(PAGE_SIZE);
+ __REALM_BSS_END__ = .;
+ }> RAM
+ __REALM_BSS_SIZE__ = SIZEOF(.bss);
+}
diff --git a/realm/realm.mk b/realm/realm.mk
new file mode 100644
index 0000000..638f02e
--- /dev/null
+++ b/realm/realm.mk
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include branch_protection.mk
+
+REALM_INCLUDES := \
+ -Itftf/framework/include \
+ -Iinclude \
+ -Iinclude/common \
+ -Iinclude/common/${ARCH} \
+ -Iinclude/lib \
+ -Iinclude/lib/${ARCH} \
+ -Iinclude/lib/utils \
+ -Iinclude/lib/xlat_tables \
+ -Iinclude/runtime_services \
+ -Iinclude/runtime_services/host_realm_managment \
+ -Irealm \
+ -Irealm/aarch64
+
+REALM_SOURCES:= \
+ $(addprefix realm/, \
+ aarch64/realm_entrypoint.S \
+ aarch64/realm_exceptions.S \
+ realm_debug.c \
+ realm_payload_main.c \
+ realm_interrupt.c \
+ realm_rsi.c \
+ realm_shared_data.c \
+ )
+
+REALM_SOURCES += lib/${ARCH}/cache_helpers.S \
+ lib/${ARCH}/misc_helpers.S \
+ lib/smc/${ARCH}/asm_smc.S \
+ lib/smc/${ARCH}/smc.c \
+ lib/exceptions/${ARCH}/sync.c \
+ lib/locks/${ARCH}/spinlock.S \
+ lib/delay/delay.c
+
+# TODO: Remove dependency on TFTF files.
+REALM_SOURCES += \
+ tftf/framework/${ARCH}/exception_report.c
+
+REALM_LINKERFILE:= realm/realm.ld.S
+
+REALM_DEFINES:=
+$(eval $(call add_define,REALM_DEFINES,ARM_ARCH_MAJOR))
+$(eval $(call add_define,REALM_DEFINES,ARM_ARCH_MINOR))
+$(eval $(call add_define,REALM_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,REALM_DEFINES,ENABLE_PAUTH))
+$(eval $(call add_define,REALM_DEFINES,LOG_LEVEL))
+$(eval $(call add_define,REALM_DEFINES,IMAGE_REALM))
diff --git a/realm/realm_debug.c b/realm/realm_debug.c
new file mode 100644
index 0000000..e9eb61e
--- /dev/null
+++ b/realm/realm_debug.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <host_shared_data.h>
+
+/*
+ * A printf formatted function used in the Realm world to log messages
+ * in the shared buffer.
+ * Locate the shared logging buffer and print its content
+ */
+void realm_printf(const char *fmt, ...)
+{
+ host_shared_data_t *guest_shared_data = realm_get_shared_structure();
+ char *log_buffer = (char *)guest_shared_data->log_buffer;
+ va_list args;
+
+ va_start(args, fmt);
+ spin_lock((spinlock_t *)&guest_shared_data->printf_lock);
+ if (strnlen((const char *)log_buffer, MAX_BUF_SIZE) == MAX_BUF_SIZE) {
+ (void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
+ }
+ (void)vsnprintf((char *)log_buffer +
+ strnlen((const char *)log_buffer, MAX_BUF_SIZE),
+ MAX_BUF_SIZE, fmt, args);
+ spin_unlock((spinlock_t *)&guest_shared_data->printf_lock);
+ va_end(args);
+}
+
+void __attribute__((__noreturn__)) do_panic(const char *file, int line)
+{
+ realm_printf("PANIC in file: %s line: %d\n", file, line);
+ while (true) {
+ continue;
+ }
+}
+
+/* This is used from printf() when crash dump is reached */
+int console_putc(int c)
+{
+ host_shared_data_t *guest_shared_data = realm_get_shared_structure();
+ char *log_buffer = (char *)guest_shared_data->log_buffer;
+
+ if ((c < 0) || (c > 127)) {
+ return -1;
+ }
+ spin_lock((spinlock_t *)&guest_shared_data->printf_lock);
+ if (strnlen((const char *)log_buffer, MAX_BUF_SIZE) == MAX_BUF_SIZE) {
+ (void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
+ }
+ *((char *)log_buffer + strnlen((const char *)log_buffer, MAX_BUF_SIZE)) = c;
+ spin_unlock((spinlock_t *)&guest_shared_data->printf_lock);
+
+ return c;
+}
diff --git a/realm/realm_interrupt.c b/realm/realm_interrupt.c
new file mode 100644
index 0000000..02ab55c
--- /dev/null
+++ b/realm/realm_interrupt.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+
+/* dummy interrupt handler as for now*/
+void realm_interrupt_handler(void)
+{
+ INFO("%s\n", __func__);
+}
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
new file mode 100644
index 0000000..bd4dec7
--- /dev/null
+++ b/realm/realm_payload_main.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+
+#include <debug.h>
+#include <host_realm_helper.h>
+#include <host_shared_data.h>
+#include "realm_def.h"
+#include <realm_rsi.h>
+#include <tftf_lib.h>
+
+/*
+ * This function reads sleep time in ms from shared buffer and spins PE in a loop
+ * for that time period.
+ */
+static void realm_sleep_cmd(void)
+{
+ uint64_t sleep = realm_shared_data_get_host_val(HOST_SLEEP_INDEX);
+
+ INFO("REALM_PAYLOAD: Realm payload going to sleep for %llums\n", sleep);
+ waitms(sleep);
+}
+
+/*
+ * This function requests RSI/ABI version from RMM.
+ */
+static void realm_get_rsi_version(void)
+{
+ u_register_t version;
+
+ version = rsi_get_version();
+ if (version == (u_register_t)SMC_UNKNOWN) {
+ ERROR("SMC_RSI_ABI_VERSION failed (%ld)", (long)version);
+ return;
+ }
+
+ INFO("RSI ABI version %u.%u (expected: %u.%u)",
+ RSI_ABI_VERSION_GET_MAJOR(version),
+ RSI_ABI_VERSION_GET_MINOR(version),
+ RSI_ABI_VERSION_GET_MAJOR(RSI_ABI_VERSION),
+ RSI_ABI_VERSION_GET_MINOR(RSI_ABI_VERSION));
+}
+
+/*
+ * 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,
+ * performs the request, and returns to Host with the execution state SUCCESS/FAILED
+ *
+ * Host in NS world requests Realm to execute certain operations using command
+ * depending on the test case the Host wants to perform.
+ */
+void realm_payload_main(void)
+{
+ uint8_t cmd = 0U;
+ bool test_succeed = false;
+
+ realm_set_shared_structure((host_shared_data_t *)rsi_get_ns_buffer());
+ if (realm_get_shared_structure() != NULL) {
+ cmd = realm_shared_data_get_realm_cmd();
+ switch (cmd) {
+ case REALM_SLEEP_CMD:
+ realm_sleep_cmd();
+ test_succeed = true;
+ break;
+ case REALM_GET_RSI_VERSION:
+ realm_get_rsi_version();
+ test_succeed = true;
+ break;
+ default:
+ INFO("REALM_PAYLOAD: %s invalid cmd=%hhu", __func__, cmd);
+ break;
+ }
+ }
+
+ if (test_succeed) {
+ rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+ } else {
+ rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+ }
+}
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
new file mode 100644
index 0000000..c805514
--- /dev/null
+++ b/realm/realm_rsi.c
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <host_realm_rmi.h>
+#include <lib/aarch64/arch_features.h>
+#include <realm_rsi.h>
+#include <smccc.h>
+
+static struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
+
+/* This function return RSI_ABI_VERSION */
+u_register_t rsi_get_version(void)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_ABI_VERSION, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+
+ return res.ret0;
+}
+
+/* This function will call the Host to request IPA of the NS shared buffer */
+u_register_t rsi_get_ns_buffer(void)
+{
+ smc_ret_values res = {};
+
+ host_cal.imm = HOST_CALL_GET_SHARED_BUFF_CMD;
+ res = tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+ if (res.ret0 != RSI_SUCCESS) {
+ return 0U;
+ }
+ return host_cal.gprs[0];
+}
+
+/* This function call Host and request to exit Realm with proper exit code */
+void rsi_exit_to_host(enum host_call_cmd exit_code)
+{
+ host_cal.imm = exit_code;
+ tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+}
diff --git a/realm/realm_rsi.h b/realm/realm_rsi.h
new file mode 100644
index 0000000..34721cd
--- /dev/null
+++ b/realm/realm_rsi.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REALM_RSI_H
+#define REALM_RSI_H
+
+#include <stdint.h>
+#include <tftf_lib.h>
+
+#define SMC_RSI_CALL_BASE 0xC4000190
+#define SMC_RSI_FID(_x) (SMC_RSI_CALL_BASE + (_x))
+/*
+ * This file describes the Realm Services Interface (RSI) Application Binary
+ * Interface (ABI) for SMC calls made from within the Realm to the RMM and
+ * serviced by the RMM.
+ *
+ * See doc/rmm_interface.md for more details.
+ */
+
+/*
+ * The major version number of the RSI implementation. Increase this whenever
+ * the binary format or semantics of the SMC calls change.
+ */
+#define RSI_ABI_VERSION_MAJOR 12U
+
+/*
+ * The minor version number of the RSI implementation. Increase this when
+ * a bug is fixed, or a feature is added without breaking binary compatibility.
+ */
+#define RSI_ABI_VERSION_MINOR 0U
+
+#define RSI_ABI_VERSION_VAL ((RSI_ABI_VERSION_MAJOR << 16U) | \
+ RSI_ABI_VERSION_MINOR)
+
+#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16U)
+#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFFU)
+
+
+/* RSI Status code enumeration as per Section D4.3.6 of the RMM Spec */
+typedef enum {
+ /* Command completed successfully */
+ RSI_SUCCESS = 0U,
+
+ /*
+ * The value of a command input value
+ * caused the command to fail
+ */
+ RSI_ERROR_INPUT = 1U,
+
+ /*
+ * The state of the current Realm or current REC
+ * does not match the state expected by the command
+ */
+ RSI_ERROR_STATE = 2U,
+
+ /* The operation requested by the command is not complete */
+ RSI_INCOMPLETE = 3U,
+
+ RSI_ERROR_COUNT
+} rsi_status_t;
+
+enum host_call_cmd {
+ HOST_CALL_GET_SHARED_BUFF_CMD = 1U,
+ HOST_CALL_EXIT_SUCCESS_CMD,
+ HOST_CALL_EXIT_FAILED_CMD
+};
+
+struct rsi_realm_config {
+ /* IPA width in bits */
+ SET_MEMBER(unsigned long ipa_width, 0, 0x1000); /* Offset 0 */
+};
+
+/*
+ * arg0 == IPA address of target region
+ * arg1 == Size of target region in bytes
+ * arg2 == RIPAS value
+ * ret0 == Status / error
+ * ret1 == Top of modified IPA range
+ */
+
+#define RSI_HOST_CALL_NR_GPRS 7U
+
+struct rsi_host_call {
+ SET_MEMBER(struct {
+ /* Immediate value */
+ unsigned int imm; /* Offset 0 */
+ /* Registers */
+ unsigned long gprs[RSI_HOST_CALL_NR_GPRS];
+ }, 0, 0x100);
+};
+
+/*
+ * arg0 == struct rsi_host_call addr
+ */
+#define RSI_HOST_CALL SMC_RSI_FID(9U)
+
+
+#define RSI_ABI_VERSION SMC_RSI_FID(0U)
+/*
+ * arg0 == struct rsi_realm_config address
+ */
+#define RSI_REALM_CONFIG SMC_RSI_FID(6U)
+
+/* This function return RSI_ABI_VERSION */
+u_register_t rsi_get_version(void);
+
+/* This function will call the Host to request IPA of the NS shared buffer */
+u_register_t rsi_get_ns_buffer(void);
+
+/* This function call Host and request to exit Realm with proper exit code */
+void rsi_exit_to_host(enum host_call_cmd exit_code);
+
+#endif /* REALM_RSI_H */
diff --git a/realm/realm_shared_data.c b/realm/realm_shared_data.c
new file mode 100644
index 0000000..da09b53
--- /dev/null
+++ b/realm/realm_shared_data.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <host_shared_data.h>
+
+/**
+ * @brief - Returns the base address of the shared region
+ * @param - Void
+ * @return - Base address of the shared region
+ **/
+
+static host_shared_data_t *guest_shared_data;
+
+/*
+ * Set guest mapped shared buffer pointer
+ */
+void realm_set_shared_structure(host_shared_data_t *ptr)
+{
+ guest_shared_data = ptr;
+}
+
+/*
+ * Get guest mapped shared buffer pointer
+ */
+host_shared_data_t *realm_get_shared_structure(void)
+{
+ return guest_shared_data;
+}
+
+/*
+ * Return Host's data at index
+ */
+u_register_t realm_shared_data_get_host_val(uint8_t index)
+{
+ return guest_shared_data->host_param_val[(index >= MAX_DATA_SIZE) ?
+ (MAX_DATA_SIZE - 1) : index];
+}
+
+/*
+ * Get command sent from Host to realm
+ */
+uint8_t realm_shared_data_get_realm_cmd(void)
+{
+ return guest_shared_data->realm_cmd;
+}
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index 11026f2..a2c2a66 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -28,6 +28,7 @@
-Ispm/cactus \
-Ispm/ivy \
-Ispm/quark \
+ -Irealm \
-Ismc_fuzz/include
FRAMEWORK_SOURCES := ${AUTOGEN_DIR}/tests_list.c
diff --git a/tftf/framework/tftf.ld.S b/tftf/framework/tftf.ld.S
index 9374206..e403af0 100644
--- a/tftf/framework/tftf.ld.S
+++ b/tftf/framework/tftf.ld.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,8 +11,12 @@
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
ENTRY(tftf_entrypoint)
+#ifndef TFTF_MAX_IMAGE_SIZE
+#define TFTF_MAX_IMAGE_SIZE DRAM_SIZE
+#endif
+
MEMORY {
- RAM (rwx): ORIGIN = DRAM_BASE, LENGTH = DRAM_SIZE
+ RAM (rwx): ORIGIN = TFTF_BASE, LENGTH = TFTF_MAX_IMAGE_SIZE
}
diff --git a/tftf/tests/misc_tests/test_invalid_access.c b/tftf/tests/misc_tests/test_invalid_access.c
index 14be340..7e4a861 100644
--- a/tftf/tests/misc_tests/test_invalid_access.c
+++ b/tftf/tests/misc_tests/test_invalid_access.c
@@ -13,17 +13,15 @@
#ifdef __aarch64__
#include <sync.h>
#endif
-#include <test_helpers.h>
+#include <host_realm_helper.h>
#include <lib/aarch64/arch_features.h>
-#include <runtime_services/realm_payload/realm_payload_test.h>
+#include <test_helpers.h>
#include <tftf_lib.h>
#include <xlat_tables_v2.h>
-
#include <platform_def.h>
#include <cactus_test_cmds.h>
#include <ffa_endpoints.h>
-
/*
* Using "__aarch64__" here looks weird but its unavoidable because of following reason
* This test is part of standard test which runs on all platforms but pre-requisite
@@ -143,7 +141,7 @@
}
/* Delegate the shared page to Realm. */
- retmm = realm_granule_delegate((u_register_t)&share_page);
+ retmm = rmi_granule_delegate((u_register_t)&share_page);
if (retmm != 0UL) {
ERROR("Granule delegate failed!\n");
goto out_unregister;
@@ -161,7 +159,7 @@
out_undelegate:
/* Undelegate the shared page. */
- retmm = realm_granule_undelegate((u_register_t)&share_page);
+ retmm = rmi_granule_undelegate((u_register_t)&share_page);
if (retmm != 0UL) {
ERROR("Granule undelegate failed!\n");
}
@@ -233,7 +231,7 @@
return TEST_RESULT_SKIPPED;
}
- retrmm = realm_version();
+ retrmm = rmi_version();
VERBOSE("RMM version is: %lu.%lu\n",
RMI_ABI_VERSION_GET_MAJOR(retrmm),
@@ -247,17 +245,17 @@
return TEST_RESULT_SKIPPED;
}
- retrmm = realm_granule_delegate((u_register_t)&rd[0]);
+ retrmm = rmi_granule_delegate((u_register_t)&rd[0]);
if (retrmm != 0UL) {
ERROR("Delegate operation returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
}
/* Create a realm using a parameter in a secure physical address space should fail. */
- retrmm = realm_create((u_register_t)&rd[0], params);
+ retrmm = rmi_realm_create((u_register_t)&rd[0], params);
if (retrmm == 0UL) {
ERROR("Realm create operation should fail, %lx\n", retrmm);
- retrmm = realm_destroy((u_register_t)&rd[0]);
+ retrmm = rmi_realm_destroy((u_register_t)&rd[0]);
if (retrmm != 0UL) {
ERROR("Realm destroy operation returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
@@ -269,7 +267,7 @@
return TEST_RESULT_FAIL;
}
- retrmm = realm_granule_undelegate((u_register_t)&rd[0]);
+ retrmm = rmi_granule_undelegate((u_register_t)&rd[0]);
if (retrmm != 0UL) {
INFO("Undelegate operation returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
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
new file mode 100644
index 0000000..4b50b5a
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <events.h>
+#include <heap/page_alloc.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_realm_rmi.h>
+#include <host_shared_data.h>
+#include <plat_topology.h>
+#include <power_management.h>
+#include <realm_def.h>
+#include <test_helpers.h>
+#include <xlat_tables_v2.h>
+
+static struct realm realm;
+static bool realm_payload_created;
+static bool shared_mem_created;
+static bool realm_payload_mmaped;
+static u_register_t exit_reason = RMI_EXIT_INVALID;
+static unsigned int test_result = TEST_RESULT_FAIL;
+static volatile bool timer_enabled;
+
+/* From the TFTF_BASE offset, memory used by TFTF + Shared + Realm + POOL should
+ * not exceed DRAM_END offset
+ * NS_REALM_SHARED_MEM_BASE + NS_REALM_SHARED_MEM_SIZE is considered last offset
+ */
+CASSERT((((uint64_t)NS_REALM_SHARED_MEM_BASE + (uint64_t)NS_REALM_SHARED_MEM_SIZE)\
+ < ((uint64_t)DRAM_BASE + (uint64_t)DRAM_SIZE)),\
+ error_ns_memory_and_realm_payload_exceed_DRAM_SIZE);
+
+/*
+ * The function handler to print the Realm logged buffer,
+ * executed by the secondary core
+ */
+static inline test_result_t timer_handler(void)
+{
+ size_t str_len = 0UL;
+ host_shared_data_t *host_shared_data = host_get_shared_structure();
+ char *log_buffer = (char *)host_shared_data->log_buffer;
+
+ do {
+ spin_lock((spinlock_t *)&host_shared_data->printf_lock);
+ str_len = strlen((const char *)log_buffer);
+
+ /*
+ * Read Realm message from shared printf location and print
+ * them using uart
+ */
+ if (str_len != 0UL) {
+ /* Avoid memory overflow */
+ log_buffer[MAX_BUF_SIZE - 1] = 0U;
+
+ mp_printf("%s", log_buffer);
+ (void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
+ }
+ spin_unlock((spinlock_t *)&host_shared_data->printf_lock);
+
+ } while ((timer_enabled || (str_len != 0UL)));
+
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * Initialisation function which will clear the shared region,
+ * and try to find another CPU other than the lead one to
+ * handle the Realm message logging
+ */
+void host_init_realm_print_buffer(void)
+{
+ u_register_t other_mpidr, my_mpidr;
+ int ret;
+ host_shared_data_t *host_shared_data = host_get_shared_structure();
+
+ (void)memset((char *)host_shared_data, 0, sizeof(host_shared_data_t));
+ /* Program timer */
+ timer_enabled = false;
+
+ /* Find a valid CPU to power on */
+ my_mpidr = read_mpidr_el1() & MPID_MASK;
+ other_mpidr = tftf_find_any_cpu_other_than(my_mpidr);
+ if (other_mpidr == INVALID_MPID) {
+ ERROR("Couldn't find a valid other CPU\n");
+ return;
+ }
+
+ /* Power on the other CPU */
+ ret = tftf_cpu_on(other_mpidr, (uintptr_t)timer_handler, 0);
+ if (ret != PSCI_E_SUCCESS) {
+ ERROR("powering on %llx failed",
+ (unsigned long long)other_mpidr);
+ return;
+ }
+ timer_enabled = true;
+}
+
+/**
+ * @brief - Add regions assigned to Host into its translation table data
+ * structure.
+ **/
+static test_result_t host_mmap_realm_payload(u_register_t realm_payload_adr,
+ u_register_t plat_mem_pool_adr,
+ u_register_t plat_mem_pool_size)
+{
+ if (realm_payload_mmaped) {
+ return REALM_SUCCESS;
+ }
+
+ /* Memory Pool region */
+ int rc = mmap_add_dynamic_region(plat_mem_pool_adr,
+ plat_mem_pool_adr,
+ plat_mem_pool_size,
+ MT_RW_DATA | MT_NS);
+
+ if (rc != 0) {
+ ERROR("%d: mmap_add_dynamic_region() = %d\n", __LINE__, rc);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Realm Image region */
+ rc = mmap_add_dynamic_region(realm_payload_adr,
+ realm_payload_adr,
+ REALM_MAX_LOAD_IMG_SIZE,
+ MT_RW_DATA | MT_NS);
+
+ if (rc != 0) {
+ ERROR("%d: mmap_add_dynamic_region() = %d\n", __LINE__, rc);
+ return TEST_RESULT_FAIL;
+ }
+ realm_payload_mmaped = true;
+ return REALM_SUCCESS;
+}
+
+static bool host_enter_realm(u_register_t *exit_reason, unsigned int *test_result)
+{
+ u_register_t ret;
+
+ if (!realm_payload_created) {
+ ERROR("%s failed, Realm not created\n", __func__);
+ return false;
+ }
+ if (!shared_mem_created) {
+ ERROR("%s failed, shared memory not created\n", __func__);
+ return false;
+ }
+
+ /* Enter Realm */
+ ret = realm_rec_enter(&realm, exit_reason, test_result);
+ if (ret != REALM_SUCCESS) {
+ ERROR("Rec enter failed something went wrong, ret=%lx\n", ret);
+
+ /* Free test resources */
+ if (realm_destroy(&realm) != REALM_SUCCESS) {
+ ERROR("%s\n", "realm_destroy failed");
+ }
+ realm_payload_created = false;
+ return false;
+ }
+
+ return true;
+}
+
+bool host_create_realm_payload(u_register_t realm_payload_adr,
+ u_register_t plat_mem_pool_adr,
+ u_register_t plat_mem_pool_size,
+ u_register_t realm_pages_size)
+{
+ if (realm_payload_adr == TFTF_BASE) {
+ ERROR("realm_payload_adr should grater then TFTF_BASE\n");
+ return false;
+ }
+
+ if (plat_mem_pool_adr == 0UL ||
+ plat_mem_pool_size == 0UL ||
+ realm_pages_size == 0UL) {
+ ERROR("plat_mem_pool_size or "
+ "plat_mem_pool_size or realm_pages_size isNull\n");
+ return false;
+ }
+ /* Initialize Host NS heap memory to be used in Realm creation*/
+ if (page_pool_init(plat_mem_pool_adr, realm_pages_size)
+ != HEAP_INIT_SUCCESS) {
+ ERROR("page_pool_init() failed\n");
+ return false;
+ }
+
+ /* Mmap Realm payload region*/
+ if (host_mmap_realm_payload(realm_payload_adr,
+ plat_mem_pool_adr,
+ plat_mem_pool_size) != REALM_SUCCESS) {
+ ERROR("host_mmap_realm_payload() failed\n");
+ return false;
+ }
+
+ /* Read Realm feature Regs*/
+ if (rmi_features(0UL, &realm.rmm_feat_reg0) != REALM_SUCCESS) {
+ ERROR("rmi_features() Read Realm feature failed\n");
+ goto destroy_realm;
+ }
+
+ /* Create Realm */
+ if (realm_create(&realm) != REALM_SUCCESS) {
+ ERROR("realm_create() failed\n");
+ goto destroy_realm;
+ }
+
+ if (realm_init_ipa_state(&realm, 0U, 0U, 1ULL << 32)
+ != RMI_SUCCESS) {
+ ERROR("realm_init_ipa_state\n");
+ goto destroy_realm;
+ }
+ /* RTT map Realm image */
+ if (realm_map_payload_image(&realm, realm_payload_adr) !=
+ REALM_SUCCESS) {
+ ERROR("realm_map_payload_image() failed\n");
+ goto destroy_realm;
+ }
+
+ /* Create REC */
+ if (realm_rec_create(&realm) != REALM_SUCCESS) {
+ ERROR("REC create failed\n");
+ goto destroy_realm;
+ }
+
+ /* Activate Realm */
+ if (realm_activate(&realm) != REALM_SUCCESS) {
+ ERROR("Realm activate failed\n");
+ goto destroy_realm;
+ }
+
+ realm_payload_created = true;
+
+ return realm_payload_created;
+
+ /* Free test resources */
+destroy_realm:
+ if (realm_destroy(&realm) != REALM_SUCCESS) {
+ ERROR("%s\n", "realm_destroy failed");
+ }
+ realm_payload_created = false;
+
+ return realm_payload_created;
+}
+
+bool host_create_shared_mem(u_register_t ns_shared_mem_adr,
+ u_register_t ns_shared_mem_size)
+{
+ /* RTT map NS shared region */
+ if (realm_map_ns_shared(&realm, ns_shared_mem_adr, ns_shared_mem_size) !=
+ REALM_SUCCESS) {
+ ERROR("realm_map_ns_shared() failed\n");
+ shared_mem_created = false;
+ return false;
+ }
+
+ host_init_realm_print_buffer();
+ realm_shared_data_clear_realm_val();
+ shared_mem_created = true;
+
+ return shared_mem_created;
+}
+
+bool host_destroy_realm(void)
+{
+ /* Free test resources */
+ timer_enabled = false;
+ page_pool_reset();
+
+ if (!realm_payload_created) {
+ ERROR("realm_destroy failed, Realm not created\n");
+ return false;
+ }
+
+ realm_payload_created = false;
+ if (realm_destroy(&realm) != REALM_SUCCESS) {
+ ERROR("%s\n", "realm_destroy failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool host_enter_realm_execute(uint8_t cmd)
+{
+ exit_reason = RMI_EXIT_INVALID;
+ test_result = TEST_RESULT_FAIL;
+
+ realm_shared_data_set_realm_cmd(cmd);
+ if (!host_enter_realm(&exit_reason, &test_result)) {
+ return false;
+ }
+
+ if (exit_reason == RMI_EXIT_HOST_CALL &&
+ test_result == TEST_RESULT_SUCCESS) {
+ return true;
+ }
+ ERROR("host_enter_realm_execute exit_reason:[0x%lx],test_result:[0x%x]\n",
+ exit_reason,
+ test_result);
+ return false;
+}
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
new file mode 100644
index 0000000..898e22a
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+
+#include <debug.h>
+#include <heap/page_alloc.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_realm_rmi.h>
+#include <plat/common/platform.h>
+#include <realm_def.h>
+#include <tftf_lib.h>
+
+static inline u_register_t rmi_data_create(bool unknown, u_register_t data,
+ u_register_t rd, u_register_t map_addr, u_register_t src)
+{
+ if (unknown) {
+ return ((smc_ret_values)(tftf_smc(&(smc_args)
+ {RMI_DATA_CREATE_UNKNOWN, data, rd, map_addr,
+ 0UL, 0UL, 0UL, 0UL}))).ret0;
+ } else {
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_DATA_CREATE,
+ data, rd, map_addr, src, 0UL, 0UL, 0UL}))).ret0;
+ }
+}
+
+static inline u_register_t rmi_realm_activate(u_register_t rd)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REALM_ACTIVATE,
+ rd, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t rmi_realm_create(u_register_t rd, u_register_t params_ptr)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REALM_CREATE,
+ rd, params_ptr, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t rmi_realm_destroy(u_register_t rd)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REALM_DESTROY,
+ rd, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_data_destroy(u_register_t rd,
+ u_register_t map_addr)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_DATA_DESTROY,
+ rd, map_addr, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rec_create(u_register_t rec, u_register_t rd,
+ u_register_t params_ptr)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REC_CREATE,
+ rec, rd, params_ptr, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rec_destroy(u_register_t rec)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REC_DESTROY,
+ rec, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rtt_create(u_register_t rtt, u_register_t rd,
+ u_register_t map_addr, u_register_t level)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_CREATE,
+ rtt, rd, map_addr, level, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rtt_destroy(u_register_t rtt, u_register_t rd,
+ u_register_t map_addr, u_register_t level)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_DESTROY,
+ rtt, rd, map_addr, level, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t rmi_features(u_register_t index, u_register_t *features)
+{
+ smc_ret_values rets;
+
+ rets = tftf_smc(&(smc_args) {RMI_FEATURES, index, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+ *features = rets.ret1;
+ return rets.ret0;
+}
+
+static inline u_register_t rmi_rtt_init_ripas(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t level)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_INIT_RIPAS,
+ rd, map_addr, level, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rtt_fold(u_register_t rtt, u_register_t rd,
+ u_register_t map_addr, u_register_t level)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_FOLD,
+ rtt, rd, map_addr, level, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rec_aux_count(u_register_t rd,
+ u_register_t *aux_count)
+{
+ smc_ret_values rets;
+
+ rets = tftf_smc(&(smc_args) {RMI_REC_AUX_COUNT, rd, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+ *aux_count = rets.ret1;
+ return rets.ret0;
+}
+
+static inline u_register_t rmi_rtt_set_ripas(u_register_t rd, u_register_t rec,
+ u_register_t map_addr, u_register_t level,
+ u_register_t ripas)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_SET_RIPAS,
+ rd, rec, map_addr, level, ripas, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rmi_rtt_mapunprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t level, u_register_t ns_pa)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_MAP_UNPROTECTED,
+ rd, map_addr, level, ns_pa, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static u_register_t rmi_rtt_readentry(u_register_t rd, u_register_t map_addr,
+ u_register_t level, struct rtt_entry *rtt)
+{
+ smc_ret_values rets;
+
+ rets = tftf_smc(&(smc_args) {RMI_RTT_READ_ENTRY,
+ rd, map_addr, level, 0UL, 0UL, 0UL, 0UL});
+
+ rtt->walk_level = rets.ret1;
+ rtt->state = rets.ret2 & 0xFF;
+ rtt->out_addr = rets.ret3;
+ return rets.ret0;
+}
+
+static inline u_register_t rmi_rtt_unmap_unprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t level, u_register_t ns_pa)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_RTT_UNMAP_UNPROTECTED,
+ rd, map_addr, level, ns_pa, 0UL, 0UL, 0UL}))).ret0;
+}
+
+static inline u_register_t rtt_level_mapsize(u_register_t level)
+{
+ if (level > RTT_MAX_LEVEL) {
+ return PAGE_SIZE;
+ }
+
+ return (1UL << RTT_LEVEL_SHIFT(level));
+}
+
+static inline u_register_t realm_rtt_create(struct realm *realm,
+ u_register_t addr,
+ u_register_t level,
+ u_register_t phys)
+{
+ addr = ALIGN_DOWN(addr, rtt_level_mapsize(level - 1U));
+ return rmi_rtt_create(phys, realm->rd, addr, level);
+}
+
+static u_register_t rmi_create_rtt_levels(struct realm *realm,
+ u_register_t map_addr,
+ u_register_t level,
+ u_register_t max_level)
+{
+ u_register_t rtt, ret;
+
+ 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 = rmi_granule_delegate(rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Rtt delegation failed,"
+ "rtt=0x%lx ret=0x%lx\n", rtt, ret);
+ return REALM_ERROR;
+ }
+ }
+ ret = realm_rtt_create(realm, map_addr, level, rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Rtt create failed,"
+ "rtt=0x%lx ret=0x%lx\n", rtt, ret);
+ rmi_granule_undelegate(rtt);
+ page_free(rtt);
+ return REALM_ERROR;
+ }
+ }
+
+ return REALM_SUCCESS;
+}
+
+static u_register_t realm_fold_rtt(u_register_t rd, u_register_t addr,
+ u_register_t level)
+{
+ struct rtt_entry rtt;
+ u_register_t ret;
+
+ ret = rmi_rtt_readentry(rd, addr, level, &rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Rtt readentry failed,"
+ "level=0x%lx addr=0x%lx ret=0x%lx\n",
+ level, addr, ret);
+ return REALM_ERROR;
+ }
+
+ if (rtt.state != RMI_TABLE) {
+ ERROR("Rtt readentry failed, rtt.state=0x%x\n", rtt.state);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_rtt_fold(rtt.out_addr, rd, addr, level + 1U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Rtt destroy failed,"
+ "rtt.out_addr=0x%llx addr=0x%lx ret=0x%lx\n",
+ rtt.out_addr, addr, ret);
+ return REALM_ERROR;
+ }
+
+ page_free(rtt.out_addr);
+
+ return REALM_SUCCESS;
+
+}
+
+static u_register_t realm_map_protected_data(bool unknown, struct realm *realm,
+ u_register_t target_pa,
+ u_register_t map_size,
+ u_register_t src_pa)
+{
+ u_register_t rd = realm->rd;
+ u_register_t map_level, level;
+ u_register_t ret = 0UL;
+ u_register_t size;
+ u_register_t phys = target_pa;
+ u_register_t map_addr = target_pa;
+
+ if (!IS_ALIGNED(map_addr, map_size)) {
+ return REALM_ERROR;
+ }
+
+ switch (map_size) {
+ case PAGE_SIZE:
+ map_level = 3UL;
+ break;
+ case RTT_L2_BLOCK_SIZE:
+ map_level = 2UL;
+ break;
+ default:
+ ERROR("Unknown map_size=0x%lx\n", map_size);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_rtt_init_ripas(rd, map_addr, map_level);
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
+ ret = rmi_create_rtt_levels(realm, map_addr,
+ RMI_RETURN_INDEX(ret), map_level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_create_rtt_levels failed,"
+ "ret=0x%lx line:%d\n",
+ ret, __LINE__);
+ goto err;
+ }
+ ret = rmi_rtt_init_ripas(rd, map_addr, map_level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_create_rtt_levels failed,"
+ "ret=0x%lx line:%d\n",
+ ret, __LINE__);
+ goto err;
+ }
+ }
+ for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+ ret = rmi_granule_delegate(phys);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Granule delegation failed, PA=0x%lx ret=0x%lx\n",
+ phys, ret);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_data_create(unknown, phys, rd, map_addr, src_pa);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
+ /* Create missing RTTs and retry */
+ level = RMI_RETURN_INDEX(ret);
+ ret = rmi_create_rtt_levels(realm, map_addr, level,
+ map_level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_create_rtt_levels failed,"
+ "ret=0x%lx line:%d\n",
+ ret, __LINE__);
+ goto err;
+ }
+
+ ret = rmi_data_create(unknown, phys, rd, map_addr, src_pa);
+ }
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_data_create failed, ret=0x%lx\n", ret);
+ goto err;
+ }
+
+ phys += PAGE_SIZE;
+ src_pa += PAGE_SIZE;
+ map_addr += PAGE_SIZE;
+ }
+
+ if (map_size == RTT_L2_BLOCK_SIZE) {
+ ret = realm_fold_rtt(rd, target_pa, map_level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("fold_rtt failed, ret=0x%lx\n", ret);
+ goto err;
+ }
+ }
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_rtt_mapprotected failed, ret=0x%lx\n", ret);
+ goto err;
+ }
+
+ return REALM_SUCCESS;
+
+err:
+ while (size >= PAGE_SIZE) {
+ ret = rmi_data_destroy(rd, map_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_rtt_mapprotected failed, ret=0x%lx\n", ret);
+ }
+
+ ret = rmi_granule_undelegate(phys);
+ if (ret != RMI_SUCCESS) {
+ /* Page can't be returned to NS world so is lost */
+ ERROR("rmi_granule_undelegate failed\n");
+ }
+ phys -= PAGE_SIZE;
+ size -= PAGE_SIZE;
+ map_addr -= PAGE_SIZE;
+ }
+
+ return REALM_ERROR;
+}
+
+u_register_t realm_map_unprotected(struct realm *realm,
+ u_register_t ns_pa,
+ u_register_t map_size)
+{
+ u_register_t rd = realm->rd;
+ u_register_t map_level, level;
+ u_register_t ret = 0UL;
+ u_register_t phys = ns_pa;
+ u_register_t map_addr = ns_pa |
+ (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
+ realm->rmm_feat_reg0) - 1UL)) ;
+
+
+ if (!IS_ALIGNED(map_addr, map_size)) {
+ return REALM_ERROR;
+ }
+
+ switch (map_size) {
+ case PAGE_SIZE:
+ map_level = 3UL;
+ break;
+ case RTT_L2_BLOCK_SIZE:
+ map_level = 2UL;
+ break;
+ default:
+ ERROR("Unknown map_size=0x%lx\n", map_size);
+ return REALM_ERROR;
+ }
+
+ u_register_t desc = phys | S2TTE_ATTR_FWB_WB_RW;
+
+ ret = rmi_rtt_mapunprotected(rd, map_addr, map_level, desc);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
+ /* Create missing RTTs and retry */
+ level = RMI_RETURN_INDEX(ret);
+ ret = rmi_create_rtt_levels(realm, map_addr, level, map_level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_create_rtt_levels failed, ret=0x%lx line:%d\n",
+ ret, __LINE__);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_rtt_mapunprotected(rd, map_addr, map_level, desc);
+ }
+ if (ret != RMI_SUCCESS) {
+ ERROR("al_rmi_rtt_mapunprotected failed, ret=0x%lx\n", ret);
+ return REALM_ERROR;
+ }
+
+ return REALM_SUCCESS;
+}
+
+static u_register_t realm_rtt_destroy(struct realm *realm, u_register_t addr,
+ u_register_t level,
+ u_register_t rtt_granule)
+{
+ addr = ALIGN_DOWN(addr, rtt_level_mapsize(level - 1U));
+ return rmi_rtt_destroy(rtt_granule, realm->rd, addr, level);
+}
+
+static u_register_t realm_destroy_free_rtt(struct realm *realm,
+ u_register_t addr,
+ u_register_t level, u_register_t rtt_granule)
+{
+ u_register_t ret;
+
+ ret = realm_rtt_destroy(realm, addr, level, rtt_granule);
+ if (ret != RMI_SUCCESS) {
+ ERROR("realm_rtt_destroy failed, rtt=0x%lx, ret=0x%lx\n",
+ rtt_granule, ret);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_granule_undelegate(rtt_granule);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_granule_undelegate failed, rtt=0x%lx, ret=0x%lx\n",
+ rtt_granule, ret);
+ return REALM_ERROR;
+ }
+
+ page_free(rtt_granule);
+ return REALM_SUCCESS;
+}
+
+static void realm_destroy_undelegate_range(struct realm *realm,
+ u_register_t ipa,
+ u_register_t addr,
+ u_register_t size)
+{
+ u_register_t rd = realm->rd;
+ u_register_t ret;
+
+ while (size >= PAGE_SIZE) {
+ ret = rmi_data_destroy(rd, ipa);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_data_destroy failed, addr=0x%lx, ret=0x%lx\n",
+ ipa, ret);
+ }
+
+ ret = rmi_granule_undelegate(addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("al_rmi_granule_undelegate failed, addr=0x%lx,"
+ "ret=0x%lx\n",
+ ipa, ret);
+ }
+
+ page_free(addr);
+
+ addr += PAGE_SIZE;
+ ipa += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+}
+
+static u_register_t realm_tear_down_rtt_range(struct realm *realm,
+ u_register_t level,
+ u_register_t start,
+ u_register_t end)
+{
+ u_register_t rd = realm->rd, ret;
+ u_register_t map_size = rtt_level_mapsize(level);
+ u_register_t map_addr, next_addr, rtt_out_addr, end_addr;
+ struct rtt_entry rtt;
+
+ for (map_addr = start; map_addr < end; map_addr = next_addr) {
+ next_addr = ALIGN(map_addr + 1U, map_size);
+ end_addr = MIN(next_addr, end);
+
+ ret = rmi_rtt_readentry(rd, ALIGN_DOWN(map_addr, map_size),
+ level, &rtt);
+ if (ret != RMI_SUCCESS) {
+ continue;
+ }
+
+ rtt_out_addr = rtt.out_addr;
+
+ switch (rtt.state) {
+ case RMI_ASSIGNED:
+ realm_destroy_undelegate_range(realm, map_addr,
+ rtt_out_addr, map_size);
+ break;
+ case RMI_UNASSIGNED:
+ case RMI_DESTROYED:
+ break;
+ case RMI_TABLE:
+ ret = realm_tear_down_rtt_range(realm, level + 1U,
+ map_addr, end_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("realm_tear_down_rtt_range failed, \
+ map_addr=0x%lx ret=0x%lx\n",
+ map_addr, ret);
+ return REALM_ERROR;
+ }
+
+ ret = realm_destroy_free_rtt(realm, map_addr, level + 1U,
+ rtt_out_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rrt destroy can't be performed failed, \
+ map_addr=0x%lx ret=0x%lx\n",
+ map_addr, ret);
+ return REALM_ERROR;
+ }
+ break;
+ case RMI_VALID_NS:
+ ret = rmi_rtt_unmap_unprotected(rd, map_addr, level,
+ rtt_out_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_rtt_unmap_unprotected failed,"
+ "addr=0x%lx, ret=0x%lx\n",
+ map_addr, ret);
+ return REALM_ERROR;
+ }
+ break;
+ default:
+ return REALM_ERROR;
+ }
+ }
+
+ return REALM_SUCCESS;
+}
+
+u_register_t rmi_granule_delegate(u_register_t addr)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_GRANULE_DELEGATE,
+ addr, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t rmi_granule_undelegate(u_register_t addr)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_GRANULE_UNDELEGATE,
+ addr, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t rmi_version(void)
+{
+ return ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_VERSION,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+}
+
+u_register_t realm_create(struct realm *realm)
+{
+ struct rmi_realm_params *params;
+ u_register_t ret;
+
+ realm->par_size = REALM_MAX_LOAD_IMG_SIZE;
+
+ realm->state = REALM_STATE_NULL;
+ /*
+ * Allocate memory for PAR - Realm image. Granule delegation
+ * of PAR will be performed during rtt creation.
+ */
+ realm->par_base = (u_register_t)page_alloc(realm->par_size);
+ if (realm->par_base == HEAP_NULL_PTR) {
+ ERROR("page_alloc failed, base=0x%lx, size=0x%lx\n",
+ realm->par_base, realm->par_size);
+ return REALM_ERROR;
+ }
+
+ /* Allocate and delegate RD */
+ realm->rd = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->rd == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for rd\n");
+ goto err_free_par;
+ } else {
+ ret = rmi_granule_delegate(realm->rd);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rd delegation failed, rd=0x%lx, ret=0x%lx\n",
+ realm->rd, ret);
+ goto err_free_rd;
+ }
+ }
+
+ /* Allocate and delegate RTT */
+ realm->rtt_addr = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->rtt_addr == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for rtt_addr\n");
+ goto err_undelegate_rd;
+ } else {
+ ret = rmi_granule_delegate(realm->rtt_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rtt delegation failed, rtt_addr=0x%lx, ret=0x%lx\n",
+ realm->rtt_addr, ret);
+ goto err_free_rtt;
+ }
+ }
+
+ /* 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;
+ }
+
+ /* Populate params */
+ params->features_0 = realm->rmm_feat_reg0;
+ params->rtt_level_start = 0L;
+ params->rtt_num_start = 1U;
+ params->rtt_base = realm->rtt_addr;
+ params->vmid = 1U;
+ params->hash_algo = RMI_HASH_SHA_256;
+
+ /* Create Realm */
+ ret = rmi_realm_create(realm->rd, (u_register_t)params);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Realm create failed, rd=0x%lx, ret=0x%lx\n", realm->rd,
+ ret);
+ goto err_free_params;
+ }
+
+ ret = rmi_rec_aux_count(realm->rd, &realm->num_aux);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_rec_aux_count failed, rd=0x%lx, ret=0x%lx\n", realm->rd,
+ ret);
+ rmi_realm_destroy(realm->rd);
+ goto err_free_params;
+ }
+
+ realm->state = REALM_STATE_NEW;
+
+ /* Free params */
+ page_free((u_register_t)params);
+ return REALM_SUCCESS;
+
+err_free_params:
+ page_free((u_register_t)params);
+
+err_undelegate_rtt:
+ ret = rmi_granule_undelegate(realm->rtt_addr);
+ if (ret != RMI_SUCCESS) {
+ WARN("rtt undelegation failed, rtt_addr=0x%lx, ret=0x%lx\n",
+ realm->rtt_addr, ret);
+ }
+
+err_free_rtt:
+ page_free(realm->rtt_addr);
+
+err_undelegate_rd:
+ ret = rmi_granule_undelegate(realm->rd);
+ if (ret != RMI_SUCCESS) {
+ WARN("rd undelegation failed, rd=0x%lx, ret=0x%lx\n", realm->rd,
+ ret);
+ }
+err_free_rd:
+ page_free(realm->rd);
+
+err_free_par:
+ page_free(realm->par_base);
+
+ return REALM_ERROR;
+}
+
+u_register_t realm_map_payload_image(struct realm *realm,
+ 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)) {
+ ret = realm_map_protected_data(false, realm,
+ realm->par_base + i * PAGE_SIZE,
+ PAGE_SIZE,
+ src_pa + i * PAGE_SIZE);
+ if (ret != RMI_SUCCESS) {
+ ERROR("realm_map_protected_data failed,"
+ "par_base=0x%lx ret=0x%lx\n",
+ realm->par_base, ret);
+ return REALM_ERROR;
+ }
+ i++;
+ }
+
+ return REALM_SUCCESS;
+}
+
+u_register_t realm_init_ipa_state(struct realm *realm,
+ u_register_t level,
+ u_register_t start,
+ uint64_t end)
+{
+ u_register_t rd = realm->rd, ret;
+ u_register_t map_size = rtt_level_mapsize(level);
+
+ while (start < end) {
+ ret = rmi_rtt_init_ripas(rd, start, level);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
+ int cur_level = RMI_RETURN_INDEX(ret);
+
+ if (cur_level < level) {
+ ret = rmi_create_rtt_levels(realm,
+ start,
+ cur_level,
+ level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rmi_create_rtt_levels failed,"
+ "ret=0x%lx line:%d\n",
+ ret, __LINE__);
+ return ret;
+ }
+ /* Retry with the RTT levels in place */
+ continue;
+ }
+
+ if (level >= RTT_MAX_LEVEL) {
+ return REALM_ERROR;
+ }
+
+ /* There's an entry at a lower level, recurse */
+ realm_init_ipa_state(realm, start, start + map_size,
+ level + 1);
+ } else if (ret != RMI_SUCCESS) {
+ return REALM_ERROR;
+ }
+
+ start += map_size;
+ }
+
+ return RMI_SUCCESS;
+}
+
+u_register_t realm_map_ns_shared(struct realm *realm,
+ u_register_t ns_shared_mem_adr,
+ u_register_t ns_shared_mem_size)
+{
+ u_register_t i = 0UL;
+ u_register_t ret;
+
+ realm->ipa_ns_buffer = ns_shared_mem_adr |
+ (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
+ realm->rmm_feat_reg0) - 1));
+ realm->ns_buffer_size = ns_shared_mem_size;
+ /* MAP SHARED_NS region */
+ while (i < ns_shared_mem_size / PAGE_SIZE) {
+ ret = realm_map_unprotected(realm,
+ ns_shared_mem_adr + i * PAGE_SIZE, PAGE_SIZE);
+ if (ret != RMI_SUCCESS) {
+ ERROR("\trealm_map_unprotected failepar"
+ "base=0x%lx ret=0x%lx\n",
+ (ns_shared_mem_adr + i * PAGE_SIZE), ret);
+ return REALM_ERROR;
+ }
+ i++;
+ }
+ return REALM_SUCCESS;
+}
+
+static void realm_free_rec_aux(u_register_t *aux_pages, unsigned int num_aux)
+{
+ u_register_t ret;
+
+ for (unsigned int i = 0U; i < num_aux; i++) {
+ ret = rmi_granule_undelegate(aux_pages[i]);
+ if (ret != RMI_SUCCESS) {
+ WARN("realm_free_rec_aux undelegation failed,"
+ "index=%u, ret=0x%lx\n",
+ i, ret);
+ }
+ page_free(aux_pages[i]);
+ }
+}
+
+static u_register_t realm_alloc_rec_aux(struct realm *realm,
+ struct rmi_rec_params *params)
+{
+ u_register_t ret;
+ unsigned int i;
+
+ for (i = 0; i < realm->num_aux; i++) {
+ params->aux[i] = (u_register_t)page_alloc(PAGE_SIZE);
+ if (params->aux[i] == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for aux rec\n");
+ goto err_free_mem;
+ }
+ ret = rmi_granule_delegate(params->aux[i]);
+ if (ret != RMI_SUCCESS) {
+ ERROR("aux rec delegation failed at index=%d, ret=0x%lx\n",
+ i, ret);
+ goto err_free_mem;
+ }
+
+ /* We need a copy in Realm object for final destruction */
+ realm->aux_pages[i] = params->aux[i];
+ }
+ return RMI_SUCCESS;
+err_free_mem:
+ realm_free_rec_aux(params->aux, i);
+ return ret;
+}
+
+u_register_t realm_rec_create(struct realm *realm)
+{
+ struct rmi_rec_params *rec_params = HEAP_NULL_PTR;
+ u_register_t ret;
+
+ /* Allocate memory for run object */
+ realm->run = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->run == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for run\n");
+ return REALM_ERROR;
+ }
+ (void)memset((void *)realm->run, 0x0, PAGE_SIZE);
+
+ /* Allocate and delegate REC */
+ realm->rec = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->rec == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for REC\n");
+ goto err_free_mem;
+ } else {
+ ret = rmi_granule_delegate(realm->rec);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rec delegation failed, rec=0x%lx, ret=0x%lx\n",
+ realm->rd, ret);
+ goto err_free_mem;
+ }
+ }
+
+ /* Allocate memory for rec_params */
+ rec_params = (struct rmi_rec_params *)page_alloc(PAGE_SIZE);
+ if (rec_params == NULL) {
+ ERROR("Failed to allocate memory for rec_params\n");
+ goto err_undelegate_rec;
+ }
+ (void)memset(rec_params, 0x0, PAGE_SIZE);
+
+ /* Populate rec_params */
+ for (unsigned int i = 0UL; i < (sizeof(rec_params->gprs) /
+ sizeof(rec_params->gprs[0]));
+ i++) {
+ rec_params->gprs[i] = 0x0UL;
+ }
+
+ /* Delegate the required number of auxiliary Granules */
+ ret = realm_alloc_rec_aux(realm, rec_params);
+ if (ret != RMI_SUCCESS) {
+ ERROR("REC realm_alloc_rec_aux, ret=0x%lx\n", ret);
+ goto err_free_mem;
+ }
+
+ rec_params->pc = realm->par_base;
+ rec_params->flags = RMI_RUNNABLE;
+ rec_params->mpidr = 0x0UL;
+ rec_params->num_aux = realm->num_aux;
+
+ /* Create REC */
+ ret = rmi_rec_create(realm->rec, realm->rd,
+ (u_register_t)rec_params);
+ if (ret != RMI_SUCCESS) {
+ ERROR("REC create failed, ret=0x%lx\n", ret);
+ goto err_free_rec_aux;
+ }
+
+ /* Free rec_params */
+ page_free((u_register_t)rec_params);
+ return REALM_SUCCESS;
+
+err_free_rec_aux:
+ realm_free_rec_aux(rec_params->aux, realm->num_aux);
+
+err_undelegate_rec:
+ ret = rmi_granule_undelegate(realm->rec);
+ if (ret != RMI_SUCCESS) {
+ WARN("rec undelegation failed, rec=0x%lx, ret=0x%lx\n",
+ realm->rec, ret);
+ }
+
+err_free_mem:
+ page_free(realm->run);
+ page_free(realm->rec);
+ page_free((u_register_t)rec_params);
+
+ return REALM_ERROR;
+}
+
+u_register_t realm_activate(struct realm *realm)
+{
+ u_register_t ret;
+
+ /* Activate Realm */
+ ret = rmi_realm_activate(realm->rd);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Realm activate failed, ret=0x%lx\n", ret);
+ return REALM_ERROR;
+ }
+
+ realm->state = REALM_STATE_ACTIVE;
+
+ return REALM_SUCCESS;
+}
+
+u_register_t realm_destroy(struct realm *realm)
+{
+ u_register_t ret;
+
+ if (realm->state == REALM_STATE_NULL) {
+ return REALM_SUCCESS;
+ }
+
+ if (realm->state == REALM_STATE_NEW) {
+ goto undo_from_new_state;
+ }
+
+ if (realm->state != REALM_STATE_ACTIVE) {
+ ERROR("Invalid realm state found =0x%x\n", realm->state);
+ return REALM_ERROR;
+ }
+
+ /* For each REC - Destroy, undelegate and free */
+ ret = rmi_rec_destroy(realm->rec);
+ if (ret != RMI_SUCCESS) {
+ ERROR("REC destroy failed, rec=0x%lx, ret=0x%lx\n",
+ realm->rec, ret);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_granule_undelegate(realm->rec);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rec undelegation failed, rec=0x%lx, ret=0x%lx\n",
+ realm->rec, ret);
+ return REALM_ERROR;
+ }
+
+ realm_free_rec_aux(realm->aux_pages, realm->num_aux);
+ page_free(realm->rec);
+
+ /* Free run object */
+ page_free(realm->run);
+
+ /*
+ * For each data granule - Destroy, undelegate and free
+ * RTTs (level 1U and below) must be destroyed leaf-upwards,
+ * using RMI_DATA_DESTROY, RMI_RTT_DESTROY and RMI_GRANULE_UNDELEGATE
+ * commands.
+ */
+ if (realm_tear_down_rtt_range(realm, 0UL, 0UL,
+ (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
+ realm->rmm_feat_reg0) - 1))) != RMI_SUCCESS) {
+ ERROR("realm_tear_down_rtt_range\n");
+ return REALM_ERROR;
+ }
+ if (realm_tear_down_rtt_range(realm, 0UL, realm->ipa_ns_buffer,
+ (realm->ipa_ns_buffer + realm->ns_buffer_size)) !=
+ RMI_SUCCESS) {
+ ERROR("realm_tear_down_rtt_range\n");
+ return REALM_ERROR;
+ }
+undo_from_new_state:
+
+ /*
+ * RD Destroy, undelegate and free
+ * RTT(L0) undelegate and free
+ * PAR free
+ */
+ ret = rmi_realm_destroy(realm->rd);
+ if (ret != RMI_SUCCESS) {
+ ERROR("Realm destroy failed, rd=0x%lx, ret=0x%lx\n",
+ realm->rd, ret);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_granule_undelegate(realm->rd);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rd undelegation failed, rd=0x%lx, ret=0x%lx\n",
+ realm->rd, ret);
+ return REALM_ERROR;
+ }
+
+ ret = rmi_granule_undelegate(realm->rtt_addr);
+ if (ret != RMI_SUCCESS) {
+ ERROR("rtt undelegation failed, rtt_addr=0x%lx, ret=0x%lx\n",
+ realm->rtt_addr, ret);
+ return REALM_ERROR;
+ }
+
+ page_free(realm->rd);
+ page_free(realm->rtt_addr);
+ page_free(realm->par_base);
+
+ return REALM_SUCCESS;
+}
+
+
+u_register_t realm_rec_enter(struct realm *realm, u_register_t *exit_reason,
+ unsigned int *test_result)
+{
+ struct rmi_rec_run *run = (struct rmi_rec_run *)realm->run;
+ u_register_t ret;
+ bool re_enter_rec;
+
+ do {
+ re_enter_rec = false;
+ ret = ((smc_ret_values)(tftf_smc(&(smc_args) {RMI_REC_ENTER,
+ realm->rec, realm->run,
+ 0UL, 0UL, 0UL, 0UL, 0UL}))).ret0;
+ VERBOSE("rmi_rec_enter, \
+ run->exit_reason=0x%lx, \
+ run->exit.esr=0x%llx, \
+ EC_BITS=%d, \
+ ISS_DFSC_MASK=0x%llx\n",
+ run->exit_reason,
+ run->exit.esr,
+ ((EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL)),
+ (ISS_BITS(run->exit.esr) & ISS_DFSC_MASK));
+
+ /* If a data abort because of a GPF. */
+
+ if (EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL) {
+ ERROR("EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL\n");
+ if ((ISS_BITS(run->exit.esr) & ISS_DFSC_MASK) ==
+ DFSC_GPF_DABORT) {
+ ERROR("DFSC_GPF_DABORT\n");
+ }
+ }
+
+
+ if (ret != RMI_SUCCESS) {
+ return ret;
+ }
+
+ if (run->exit.exit_reason == RMI_EXIT_HOST_CALL) {
+ switch (run->exit.imm) {
+ case HOST_CALL_GET_SHARED_BUFF_CMD:
+ run->entry.gprs[0] = realm->ipa_ns_buffer;
+ re_enter_rec = true;
+ break;
+ case HOST_CALL_EXIT_SUCCESS_CMD:
+ *test_result = TEST_RESULT_SUCCESS;
+ break;
+ case HOST_CALL_EXIT_FAILED_CMD:
+ *test_result = TEST_RESULT_FAIL;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ } while (re_enter_rec);
+
+ *exit_reason = run->exit.exit_reason;
+
+ return ret;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_shared_data.c b/tftf/tests/runtime_services/host_realm_managment/host_shared_data.c
new file mode 100644
index 0000000..bd571c7
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_shared_data.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+
+static host_shared_data_t *host_shared_data =
+ ((host_shared_data_t *)(NS_REALM_SHARED_MEM_BASE));
+static host_shared_data_t *guest_shared_data;
+/*
+ * Return shared buffer pointer mapped as host_shared_data_t structure
+ */
+host_shared_data_t *host_get_shared_structure(void)
+{
+ return host_shared_data;
+}
+
+/*
+ * Set guest mapped shared buffer pointer
+ */
+void realm_set_shared_structure(host_shared_data_t *ptr)
+{
+ guest_shared_data = ptr;
+}
+
+/*
+ * Get guest mapped shared buffer pointer
+ */
+host_shared_data_t *realm_get_shared_structure(void)
+{
+ return guest_shared_data;
+}
+
+/*
+ * Set data to be shared from Host to realm
+ */
+void realm_shared_data_set_host_val(uint8_t index, u_register_t val)
+{
+ host_shared_data->host_param_val[(index >= MAX_DATA_SIZE) ?
+ (MAX_DATA_SIZE - 1) : index] = val;
+}
+
+/*
+ * Set data to be shared from realm to Host
+ */
+void realm_shared_data_set_realm_val(uint8_t index, u_register_t val)
+{
+ host_shared_data->realm_out_val[(index >= MAX_DATA_SIZE) ?
+ (MAX_DATA_SIZE - 1) : index] = val;
+}
+
+/*
+ * Return Host's data at index
+ */
+u_register_t realm_shared_data_get_host_val(uint8_t index)
+{
+ return guest_shared_data->host_param_val[(index >= MAX_DATA_SIZE) ?
+ (MAX_DATA_SIZE - 1) : index];
+}
+
+/*
+ * Return Realm's data at index
+ */
+u_register_t realm_shared_data_get_realm_val(uint8_t index)
+{
+ return host_shared_data->realm_out_val[(index >= MAX_DATA_SIZE) ?
+ (MAX_DATA_SIZE - 1) : index];
+}
+
+/*
+ * Clear shared realm data
+ */
+void realm_shared_data_clear_realm_val(void)
+{
+ (void)memset((char *)host_shared_data->realm_out_val, 0,
+ MAX_DATA_SIZE * sizeof(host_shared_data->realm_out_val[0]));
+}
+
+/*
+ * Clear shared Host data
+ */
+void realm_shared_data_clear_host_val(void)
+{
+ (void)memset((char *)host_shared_data->host_param_val, 0,
+ MAX_DATA_SIZE * sizeof(host_shared_data->host_param_val[0]));
+}
+
+/*
+ * Get command sent from Host to realm
+ */
+uint8_t realm_shared_data_get_realm_cmd(void)
+{
+ return guest_shared_data->realm_cmd;
+}
+
+/*
+ * Set command to be send from Host to realm
+ */
+void realm_shared_data_set_realm_cmd(uint8_t cmd)
+{
+ host_shared_data->realm_cmd = cmd;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_test.c b/tftf/tests/runtime_services/host_realm_managment/rmi_delegate_tests.c
similarity index 85%
rename from tftf/tests/runtime_services/realm_payload/realm_payload_test.c
rename to tftf/tests/runtime_services/host_realm_managment/rmi_delegate_tests.c
index 8bdc60a..17ff651 100644
--- a/tftf/tests/runtime_services/realm_payload/realm_payload_test.c
+++ b/tftf/tests/runtime_services/host_realm_managment/rmi_delegate_tests.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,17 +7,23 @@
#include <stdlib.h>
#include <arch_features.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
#include <plat_topology.h>
-#include <power_management.h>
#include <platform.h>
-#include <runtime_services/realm_payload/realm_payload_test.h>
+#include <power_management.h>
+#include "rmi_spm_tests.h"
#include <test_helpers.h>
+
+
static test_result_t realm_multi_cpu_payload_test(void);
static test_result_t realm_multi_cpu_payload_del_undel(void);
/* Buffer to delegate and undelegate */
-static char bufferdelegate[NUM_GRANULES * GRANULE_SIZE * PLATFORM_CORE_COUNT] __aligned(GRANULE_SIZE);
+static char bufferdelegate[NUM_GRANULES * GRANULE_SIZE * PLATFORM_CORE_COUNT]
+ __aligned(GRANULE_SIZE);
static char bufferstate[NUM_GRANULES * PLATFORM_CORE_COUNT];
/*
@@ -41,12 +47,14 @@
{
u_register_t retrmm;
- for (int i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
+ for (uint32_t i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
if ((rand() % 2) == 0) {
- retrmm = realm_granule_delegate((u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
+ retrmm = rmi_granule_delegate(
+ (u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
bufferstate[i] = B_DELEGATED;
if (retrmm != 0UL) {
- tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
+ tftf_testcase_printf("Delegate operation returns fail, %lx\n",
+ retrmm);
return TEST_RESULT_FAIL;
}
} else {
@@ -67,7 +75,7 @@
return TEST_RESULT_SKIPPED;
}
- retrmm = realm_version();
+ retrmm = rmi_version();
tftf_testcase_printf("RMM version is: %lu.%lu\n",
RMI_ABI_VERSION_GET_MAJOR(retrmm),
@@ -138,12 +146,12 @@
return TEST_RESULT_SKIPPED;
}
- retrmm = realm_granule_delegate((u_register_t)bufferdelegate);
+ retrmm = rmi_granule_delegate((u_register_t)bufferdelegate);
if (retrmm != 0UL) {
tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
}
- retrmm = realm_granule_undelegate((u_register_t)bufferdelegate);
+ retrmm = rmi_granule_undelegate((u_register_t)bufferdelegate);
if (retrmm != 0UL) {
tftf_testcase_printf("Undelegate operation returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
@@ -156,7 +164,7 @@
static test_result_t realm_multi_cpu_payload_test(void)
{
- u_register_t retrmm = realm_version();
+ u_register_t retrmm = rmi_version();
tftf_testcase_printf("Multi CPU RMM version on CPU %llx is: %lu.%lu\n",
(long long)read_mpidr_el1() & MPID_MASK, RMI_ABI_VERSION_GET_MAJOR(retrmm),
@@ -221,12 +229,14 @@
* Cleanup to set all granules back to undelegated
*/
- for (int i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
+ for (uint32_t i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
if (bufferstate[i] == B_DELEGATED) {
- retrmm = realm_granule_undelegate((u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
+ retrmm = rmi_granule_undelegate(
+ (u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
bufferstate[i] = B_UNDELEGATED;
if (retrmm != 0UL) {
- tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
+ tftf_testcase_printf("Delegate operation returns fail, %lx\n",
+ retrmm);
return TEST_RESULT_FAIL;
}
}
@@ -250,13 +260,13 @@
cpu_node = platform_get_core_pos(read_mpidr_el1() & MPID_MASK);
- for (int i = 0; i < NUM_GRANULES; i++) {
+ for (uint32_t i = 0; i < NUM_GRANULES; i++) {
if (bufferstate[((cpu_node * NUM_GRANULES) + i)] == B_UNDELEGATED) {
- retrmm = realm_granule_delegate((u_register_t)
+ retrmm = rmi_granule_delegate((u_register_t)
&bufferdelegate[((cpu_node * NUM_GRANULES) + i) * GRANULE_SIZE]);
bufferstate[((cpu_node * NUM_GRANULES) + i)] = B_DELEGATED;
} else {
- retrmm = realm_granule_undelegate((u_register_t)
+ retrmm = rmi_granule_undelegate((u_register_t)
&bufferdelegate[((cpu_node * NUM_GRANULES) + i) * GRANULE_SIZE]);
bufferstate[((cpu_node * NUM_GRANULES) + i)] = B_UNDELEGATED;
}
@@ -281,7 +291,7 @@
u_register_t retrmm;
- retrmm = realm_granule_delegate((u_register_t)&bufferdelegate[0]);
+ retrmm = rmi_granule_delegate((u_register_t)&bufferdelegate[0]);
if (retrmm != 0UL) {
tftf_testcase_printf
@@ -289,7 +299,7 @@
return TEST_RESULT_FAIL;
}
- retrmm = realm_granule_delegate((u_register_t)&bufferdelegate[0]);
+ retrmm = rmi_granule_delegate((u_register_t)&bufferdelegate[0]);
if (retrmm == 0UL) {
tftf_testcase_printf
@@ -297,7 +307,7 @@
return TEST_RESULT_FAIL;
}
- retrmm = realm_granule_undelegate((u_register_t)&bufferdelegate[1]);
+ retrmm = rmi_granule_undelegate((u_register_t)&bufferdelegate[1]);
if (retrmm == 0UL) {
tftf_testcase_printf
@@ -305,7 +315,7 @@
return TEST_RESULT_FAIL;
}
- retrmm = realm_granule_undelegate((u_register_t)&bufferdelegate[0]);
+ retrmm = rmi_granule_undelegate((u_register_t)&bufferdelegate[0]);
if (retrmm != 0UL) {
tftf_testcase_printf
diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c b/tftf/tests/runtime_services/host_realm_managment/rmi_spm_tests.c
similarity index 93%
rename from tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c
rename to tftf/tests/runtime_services/host_realm_managment/rmi_spm_tests.c
index 1aaa12c..2a0e1e1 100644
--- a/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c
+++ b/tftf/tests/runtime_services/host_realm_managment/rmi_spm_tests.c
@@ -6,20 +6,19 @@
#include <stdlib.h>
-#include <debug.h>
-#include <smccc.h>
-
#include <arch_helpers.h>
#include <cactus_test_cmds.h>
+#include <debug.h>
#include <ffa_endpoints.h>
#include <ffa_svc.h>
+#include <host_realm_helper.h>
#include <lib/events.h>
#include <lib/power_management.h>
-#include <platform.h>
-#include <test_helpers.h>
-
#include <plat_topology.h>
-#include <runtime_services/realm_payload/realm_payload_test.h>
+#include <platform.h>
+#include "rmi_spm_tests.h"
+#include <smccc.h>
+#include <test_helpers.h>
static test_result_t realm_multi_cpu_payload_del_undel(void);
@@ -29,7 +28,8 @@
#define MAX_REPEATED_TEST 3
/* Buffer to delegate and undelegate */
-static char bufferdelegate[NUM_GRANULES * GRANULE_SIZE * PLATFORM_CORE_COUNT] __aligned(GRANULE_SIZE);
+static char bufferdelegate[NUM_GRANULES * GRANULE_SIZE * PLATFORM_CORE_COUNT]
+ __aligned(GRANULE_SIZE);
static char bufferstate[NUM_GRANULES * PLATFORM_CORE_COUNT];
static int cpu_test_spm_rmi[PLATFORM_CORE_COUNT];
static event_t cpu_booted[PLATFORM_CORE_COUNT];
@@ -89,10 +89,12 @@
for (int i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
if ((rand() % 2) == 0) {
- retrmm = realm_granule_delegate((u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
+ retrmm = rmi_granule_delegate(
+ (u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
bufferstate[i] = B_DELEGATED;
if (retrmm != 0UL) {
- tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
+ tftf_testcase_printf("Delegate operation\
+ returns fail, %lx\n", retrmm);
return TEST_RESULT_FAIL;
}
} else {
@@ -106,9 +108,9 @@
{
u_register_t retrmm;
- for (uint32_t i = 0; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
+ for (uint32_t i = 0U; i < (NUM_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
if (bufferstate[i] == B_DELEGATED) {
- retrmm = realm_granule_undelegate(
+ retrmm = rmi_granule_undelegate(
(u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
if (retrmm != 0UL) {
ERROR("Undelegate operation returns fail, %lx\n",
@@ -129,7 +131,9 @@
static test_result_t wait_then_call(test_result_t (*callback)(void))
{
unsigned int mpidr, this_mpidr = read_mpidr_el1() & MPID_MASK;
- unsigned int cpu_node, core_pos, this_core_pos = platform_get_core_pos(this_mpidr);
+ unsigned int cpu_node, core_pos;
+ unsigned int this_core_pos = platform_get_core_pos(this_mpidr);
+
tftf_send_event_to_all(&cpu_booted[this_core_pos]);
for_each_cpu(cpu_node) {
mpidr = tftf_get_mpidr_from_node(cpu_node);
@@ -252,7 +256,8 @@
ffa_ret = cactus_echo_send_cmd(HYP_ID, SP_ID(3), ECHO_VAL3);
if ((ffa_func_id(ffa_ret) == FFA_ERROR) &&
(ffa_error_code(ffa_ret) == FFA_ERROR_BUSY)) {
- VERBOSE("%s(%u) trial %u\n", __func__, core_pos, trial_loop);
+ VERBOSE("%s(%u) trial %u\n", __func__,
+ core_pos, trial_loop);
waitms(1);
continue;
}
@@ -277,7 +282,7 @@
/*
* Secondary core will perform sequentially a call to secure and realm worlds.
*/
-test_result_t non_secure_call_secure_and_realm(void)
+static test_result_t non_secure_call_secure_and_realm(void)
{
test_result_t result = run_spm_direct_message();
if (result != TEST_RESULT_SUCCESS)
@@ -310,18 +315,19 @@
for (int i = 0; i < NUM_GRANULES; i++) {
if (bufferstate[((cpu_node * NUM_GRANULES) + i)] == B_UNDELEGATED) {
- retrmm = realm_granule_delegate((u_register_t)
+ retrmm = rmi_granule_delegate((u_register_t)
&bufferdelegate[((cpu_node *
NUM_GRANULES) + i) * GRANULE_SIZE]);
bufferstate[((cpu_node * NUM_GRANULES) + i)] = B_DELEGATED;
} else {
- retrmm = realm_granule_undelegate((u_register_t)
+ retrmm = rmi_granule_undelegate((u_register_t)
&bufferdelegate[((cpu_node *
NUM_GRANULES) + i) * GRANULE_SIZE]);
bufferstate[((cpu_node * NUM_GRANULES) + i)] = B_UNDELEGATED;
}
if (retrmm != 0UL) {
- tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
+ tftf_testcase_printf("Delegate operation returns fail, %lx\n",
+ retrmm);
return TEST_RESULT_FAIL;
}
}
@@ -423,7 +429,8 @@
* Main test to run both SPM and RMM or TRP together in parallel
*/
for (int i = 0; i < MAX_REPEATED_TEST; i++) {
- VERBOSE("Main test(%d) to run both SPM and RMM or TRP together in parallel...\n", i);
+ VERBOSE("Main test(%d) to run both SPM and RMM or\
+ TRP together in parallel...\n", i);
/* Reinitialize all CPUs event */
for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
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
new file mode 100644
index 0000000..562e9b8
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+#include <arch_features.h>
+#include <debug.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+
+#define SLEEP_TIME_MS 200U
+/*
+ * @Test_Aim@ Test realm payload creation and execution
+ */
+test_result_t test_realm_create_enter(void)
+{
+ bool ret1, ret2;
+ u_register_t retrmm;
+
+ if (get_armv9_2_feat_rme_support() == 0U) {
+ INFO("platform doesn't support RME\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ retrmm = rmi_version();
+ VERBOSE("RMM version is: %lu.%lu\n",
+ RMI_ABI_VERSION_GET_MAJOR(retrmm),
+ RMI_ABI_VERSION_GET_MINOR(retrmm));
+ /*
+ * Skip the test if RMM is TRP, TRP version is always null.
+ */
+ if (retrmm == 0UL) {
+ INFO("Test case not supported for TRP as RMM\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ if (!host_create_realm_payload((u_register_t)REALM_IMAGE_BASE,
+ (u_register_t)PAGE_POOL_BASE,
+ (u_register_t)(PAGE_POOL_MAX_SIZE +
+ NS_REALM_SHARED_MEM_SIZE),
+ (u_register_t)PAGE_POOL_MAX_SIZE)) {
+ return TEST_RESULT_FAIL;
+ }
+ if (!host_create_shared_mem(NS_REALM_SHARED_MEM_BASE,
+ NS_REALM_SHARED_MEM_SIZE)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ realm_shared_data_set_host_val(HOST_SLEEP_INDEX, SLEEP_TIME_MS);
+ ret1 = host_enter_realm_execute(REALM_SLEEP_CMD);
+ ret2 = host_destroy_realm();
+
+ if (!ret1 || !ret2) {
+ ERROR("test_realm_create_enter create:%d destroy:%d\n",
+ ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c b/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
deleted file mode 100644
index 49bf674..0000000
--- a/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <runtime_services/realm_payload/realm_payload_test.h>
-
-u_register_t realm_version(void)
-{
- smc_args args = { RMI_RMM_REQ_VERSION };
- smc_ret_values ret;
-
- ret = tftf_smc(&args);
- return ret.ret0;
-}
-
-u_register_t realm_granule_delegate(u_register_t add)
-{
- smc_args args = { 0 };
- smc_ret_values ret;
-
- args.fid = SMC_RMM_GRANULE_DELEGATE;
- args.arg1 = add;
-
- ret = tftf_smc(&args);
- return ret.ret0;
-}
-
-u_register_t realm_granule_undelegate(u_register_t add)
-{
- smc_args args = { 0 };
- smc_ret_values ret;
-
- args.fid = SMC_RMM_GRANULE_UNDELEGATE;
- args.arg1 = add;
-
- ret = tftf_smc(&args);
- return ret.ret0;
-}
-
-u_register_t realm_create(u_register_t rd_addr, u_register_t realm_params_addr)
-{
- smc_args args = { 0 };
- smc_ret_values ret;
-
- args.fid = SMC_RMM_REALM_CREATE;
- args.arg1 = rd_addr;
- args.arg2 = realm_params_addr;
-
- ret = tftf_smc(&args);
- return ret.ret0;
-}
-
-u_register_t realm_destroy(u_register_t rd_addr)
-{
- smc_args args = { 0 };
- smc_ret_values ret;
-
- args.fid = SMC_RMM_REALM_DESTROY;
- args.arg1 = rd_addr;
-
- ret = tftf_smc(&args);
- return ret.ret0;
-}
\ No newline at end of file
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
index 61cf2ad..e809885 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
@@ -9,9 +9,9 @@
#include <debug.h>
#include <ffa_endpoints.h>
#include <ffa_svc.h>
+#include <host_realm_helper.h>
#include <irq.h>
#include <platform.h>
-#include <runtime_services/realm_payload/realm_payload_test.h>
#include <smccc.h>
#include <spm_common.h>
#include <test_helpers.h>
@@ -71,7 +71,7 @@
handle, constituents[0].address);
/* Delegate the shared page to Realm. */
- retmm = realm_granule_delegate((u_register_t)&share_page);
+ retmm = rmi_granule_delegate((u_register_t)&share_page);
if (retmm != 0UL) {
ERROR("Granule delegate failed!\n");
return TEST_RESULT_FAIL;
@@ -82,7 +82,7 @@
handle, 0, true, 1);
/* Undelegate the shared page. */
- retmm = realm_granule_undelegate((u_register_t)&share_page);
+ retmm = rmi_granule_undelegate((u_register_t)&share_page);
if (retmm != 0UL) {
ERROR("Granule undelegate failed!\n");
return TEST_RESULT_FAIL;
diff --git a/tftf/tests/tests-invalid-access.mk b/tftf/tests/tests-invalid-access.mk
index ffca79e..8202c20 100644
--- a/tftf/tests/tests-invalid-access.mk
+++ b/tftf/tests/tests-invalid-access.mk
@@ -4,11 +4,14 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+TFTF_INCLUDES += \
+ -Iinclude/runtime_services/host_realm_managment
+
TESTS_SOURCES += tftf/tests/misc_tests/test_invalid_access.c
TESTS_SOURCES += \
- $(addprefix tftf/tests/runtime_services/realm_payload/, \
- realm_payload_test_helpers.c \
+ $(addprefix tftf/tests/runtime_services/host_realm_managment/, \
+ host_realm_rmi.c \
)
TESTS_SOURCES += \
@@ -17,4 +20,4 @@
ffa_helpers.c \
spm_common.c \
test_ffa_setup_and_discovery.c \
-)
+)
\ No newline at end of file
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index a8642fa..6d23e38 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -1,24 +1,26 @@
#
-# Copyright (c) 2021, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
+TFTF_INCLUDES += \
+ -Iinclude/runtime_services/host_realm_managment
+
TESTS_SOURCES += \
$(addprefix tftf/tests/runtime_services/realm_payload/, \
- realm_payload_test_helpers.c \
- realm_payload_test.c \
- realm_payload_spm_test.c \
+ host_realm_payload_tests.c \
)
TESTS_SOURCES += \
- $(addprefix tftf/tests/runtime_services/secure_service/, \
- ffa_helpers.c \
- spm_common.c \
- test_ffa_direct_messaging.c \
- test_ffa_interrupts.c \
- test_ffa_memory_sharing.c \
- test_ffa_setup_and_discovery.c \
- test_spm_cpu_features.c \
- test_spm_smmu.c \
+ $(addprefix tftf/tests/runtime_services/host_realm_managment/, \
+ host_realm_rmi.c \
+ host_realm_helper.c \
+ host_shared_data.c \
+ rmi_delegate_tests.c \
)
+
+TESTS_SOURCES += \
+ $(addprefix lib/heap/, \
+ page_alloc.c \
+ )
\ No newline at end of file
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index f80ead6..8438ea1 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -7,15 +7,18 @@
-->
<testsuites>
-
- <testsuite name="Realm payload tests" description="Tests for Realm management interface">
- <testcase name="Realm payload boot" function="realm_version_single_cpu" />
- <testcase name="Realm payload multi CPU request" function="realm_version_multi_cpu" />
- <testcase name="Realm payload Delegate and Undelegate" function="realm_delegate_undelegate" />
- <testcase name="Multi CPU Realm payload Delegate and Undelegate" function="realm_delundel_multi_cpu" />
- <testcase name="Testing delegation fails" function="realm_fail_del" />
- <testcase name="Test TFTF can call RMM/TRP and SPM serially on a single core" function="test_spm_rmm_serial_smc" />
- <testcase name="Test TFTF can call RMM/TRP and SPM parallelly on a multi core" function="test_spm_rmm_parallel_smc" />
+ <testsuite name="Realm payload at EL1" description="Test Realm EL1 framework capabilities" >
+ <testcase name="Realm EL1 creation and execution test"
+ function="test_realm_create_enter" />
+ <testcase name="Realm payload boot"
+ function="realm_version_single_cpu" />
+ <testcase name="Realm payload multi CPU request"
+ function="realm_version_multi_cpu" />
+ <testcase name="Realm payload Delegate and Undelegate"
+ function="realm_delegate_undelegate" />
+ <testcase name="Multi CPU Realm payload Delegate and Undelegate"
+ function="realm_delundel_multi_cpu" />
+ <testcase name="Testing delegation fails"
+ function="realm_fail_del" />
</testsuite>
-
</testsuites>
diff --git a/tftf/tests/tests-rmi-spm.mk b/tftf/tests/tests-rmi-spm.mk
new file mode 100644
index 0000000..960aa93
--- /dev/null
+++ b/tftf/tests/tests-rmi-spm.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TFTF_INCLUDES += \
+ -Iinclude/runtime_services/host_realm_managment
+
+TESTS_SOURCES += \
+ $(addprefix tftf/tests/runtime_services/host_realm_managment/, \
+ host_realm_rmi.c \
+ rmi_spm_tests.c \
+ )
+
+TESTS_SOURCES += \
+ $(addprefix tftf/tests/runtime_services/secure_service/, \
+ ${ARCH}/ffa_arch_helpers.S \
+ ffa_helpers.c \
+ spm_common.c \
+ )
+
+TESTS_SOURCES += \
+ $(addprefix lib/heap/, \
+ page_alloc.c \
+ )
\ No newline at end of file
diff --git a/tftf/tests/tests-rmi-spm.xml b/tftf/tests/tests-rmi-spm.xml
new file mode 100644
index 0000000..1d12b4a
--- /dev/null
+++ b/tftf/tests/tests-rmi-spm.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+ <testsuite name="RMI and SPM tests" description="Tests for SPM and RMI delegate/undelegate">
+ <testcase name="Test TFTF can call RMM/TRP and SPM serially on a single core"
+ function="test_spm_rmm_serial_smc" />
+ <testcase name="Test TFTF can call RMM/TRP and SPM parallelly on a multi core"
+ function="test_spm_rmm_parallel_smc" />
+ </testsuite>
+
+</testsuites>
\ No newline at end of file
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 5d71aec..f2ad0e4 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -3,6 +3,10 @@
#
# SPDX-License-Identifier: BSD-3-Clause
#
+
+TFTF_INCLUDES += \
+ -Iinclude/runtime_services/host_realm_managment
+
TESTS_SOURCES += \
$(addprefix tftf/tests/runtime_services/secure_service/, \
${ARCH}/ffa_arch_helpers.S \
@@ -21,6 +25,6 @@
)
TESTS_SOURCES += \
- $(addprefix tftf/tests/runtime_services/realm_payload/, \
- realm_payload_test_helpers.c \
- )
+ $(addprefix tftf/tests/runtime_services/host_realm_managment/, \
+ host_realm_rmi.c \
+ )
\ No newline at end of file
diff --git a/tftf/tests/tests-standard.mk b/tftf/tests/tests-standard.mk
index a722077..d57c381 100644
--- a/tftf/tests/tests-standard.mk
+++ b/tftf/tests/tests-standard.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -22,7 +22,8 @@
tests-trng.mk \
tests-tsp.mk \
tests-uncontainable.mk \
- tests-debugfs.mk \
+ tests-debugfs.mk \
+ tests-rmi-spm.mk \
tests-realm-payload.mk \
)
diff --git a/tftf/tests/tests-standard.xml b/tftf/tests/tests-standard.xml
index 384a5f4..1917bc9 100644
--- a/tftf/tests/tests-standard.xml
+++ b/tftf/tests/tests-standard.xml
@@ -24,6 +24,7 @@
<!ENTITY tests-spm SYSTEM "tests-spm.xml">
<!ENTITY tests-pmu-leakage SYSTEM "tests-pmu-leakage.xml">
<!ENTITY tests-debugfs SYSTEM "tests-debugfs.xml">
+ <!ENTITY tests-rmi-spm SYSTEM "tests-rmi-spm.xml">
<!ENTITY tests-realm-payload SYSTEM "tests-realm-payload.xml">
]>
@@ -44,6 +45,7 @@
&tests-spm;
&tests-pmu-leakage;
&tests-debugfs;
+ &tests-rmi-spm;
&tests-realm-payload;
</testsuites>