Merge "feat: specify the secure partition package for an SP"
diff --git a/.gitignore b/.gitignore
index 708900d..7548ec2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,8 @@
# Ignore build directory and binary files
build/
*.bin
+
+# Ignore the generated fuzzing files
+arg_struct_def.h
+field_specification.h
+fuzz_names.h
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index c640fc7..90d4706 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -1037,13 +1037,22 @@
#define EC_AARCH32_FP U(0x28)
#define EC_AARCH64_FP U(0x2c)
#define EC_SERROR U(0x2f)
+
+/* Common DFSC/IFSC code */
+#define ISS_FSC_MASK U(0x3f)
+#define FSC_L0_ADR_SIZE_FAULT U(0)
+#define FSC_L0_TRANS_FAULT U(4)
+#define FSC_L1_TRANS_FAULT U(5)
+#define FSC_L2_TRANS_FAULT U(6)
+#define FSC_L3_TRANS_FAULT U(7)
+#define FSC_L_MINUS1_TRANS_FAULT U(0x2B)
+#define FSC_L0_PERM_FAULT U(0xC)
+#define FSC_L1_PERM_FAULT U(0xD)
+#define FSC_L2_PERM_FAULT U(0xE)
+#define FSC_L3_PERM_FAULT U(0xF)
+
/* Data Fault Status code, not all error codes listed */
#define ISS_DFSC_MASK U(0x3f)
-#define DFSC_L0_ADR_SIZE_FAULT U(0)
-#define DFSC_L0_TRANS_FAULT U(4)
-#define DFSC_L1_TRANS_FAULT U(5)
-#define DFSC_L2_TRANS_FAULT U(6)
-#define DFSC_L3_TRANS_FAULT U(7)
#define DFSC_NO_WALK_SEA U(0x10)
#define DFSC_L0_SEA U(0x14)
#define DFSC_L1_SEA U(0x15)
@@ -1054,11 +1063,6 @@
/* Instr Fault Status code, not all error codes listed */
#define ISS_IFSC_MASK U(0x3f)
-#define IFSC_L0_ADR_SIZE_FAULT U(0)
-#define IFSC_L0_TRANS_FAULT U(4)
-#define IFSC_L1_TRANS_FAULT U(5)
-#define IFSC_L2_TRANS_FAULT U(6)
-#define IFSC_L3_TRANS_FAULT U(7)
#define IFSC_NO_WALK_SEA U(0x10)
#define IFSC_L0_SEA U(0x24)
#define IFSC_L1_SEA U(0x25)
@@ -1661,6 +1665,24 @@
#define POR_EL1 S3_0_C10_C2_4
#define S2POR_EL1 S3_0_C10_C2_5
+/* Perm value encoding for S2POR_EL1 */
+#define PERM_LABEL_NO_ACCESS U(0)
+#define PERM_LABEL_RESERVED_1 U(1)
+#define PERM_LABEL_MRO U(2)
+#define PERM_LABEL_MRO_TL1 U(3)
+#define PERM_LABEL_WO U(4)
+#define PERM_LABEL_RESERVED_5 U(5)
+#define PERM_LABEL_MRO_TL0 U(6)
+#define PERM_LABEL_MRO_TL01 U(7)
+#define PERM_LABEL_RO U(8)
+#define PERM_LABEL_RO_uX U(9)
+#define PERM_LABEL_RO_pX U(10)
+#define PERM_LABEL_RO_upX U(11)
+#define PERM_LABEL_RW U(12)
+#define PERM_LABEL_RW_uX U(13)
+#define PERM_LABEL_RW_pX U(14)
+#define PERM_LABEL_RW_upX U(15)
+
/*******************************************************************************
* FEAT_GCS - Guarded Control Stack Registers
******************************************************************************/
@@ -1683,4 +1705,72 @@
******************************************************************************/
#define FPMR S3_3_C4_C4_2
+/******************************************************************************
+ * Definitions of system register identifiers
+ *****************************************************************************/
+
+#define ESR_EL2_SYSREG_TRAP_OP0_SHIFT 20
+#define ESR_EL2_SYSREG_TRAP_OP0_WIDTH U(2)
+
+#define ESR_EL2_SYSREG_TRAP_OP2_SHIFT 17
+#define ESR_EL2_SYSREG_TRAP_OP2_WIDTH U(3)
+
+#define ESR_EL2_SYSREG_TRAP_OP1_SHIFT 14
+#define ESR_EL2_SYSREG_TRAP_OP1_WIDTH U(3)
+
+#define ESR_EL2_SYSREG_TRAP_CRN_SHIFT 10
+#define ESR_EL2_SYSREG_TRAP_CRN_WIDTH U(4)
+
+#define ESR_EL2_SYSREG_TRAP_CRM_SHIFT 1
+#define ESR_EL2_SYSREG_TRAP_CRM_WIDTH U(4)
+
+#define SYSREG_ESR(op0, op1, crn, crm, op2) \
+ ((UL(op0) << ESR_EL2_SYSREG_TRAP_OP0_SHIFT) | \
+ (UL(op1) << ESR_EL2_SYSREG_TRAP_OP1_SHIFT) | \
+ (UL(crn) << ESR_EL2_SYSREG_TRAP_CRN_SHIFT) | \
+ (UL(crm) << ESR_EL2_SYSREG_TRAP_CRM_SHIFT) | \
+ (UL(op2) << ESR_EL2_SYSREG_TRAP_OP2_SHIFT))
+
+#define SYSREG_ID_sp_el0 SYSREG_ESR(3, 0, 4, 1, 0)
+#define SYSREG_ID_sp_el1 SYSREG_ESR(3, 4, 4, 1, 0)
+#define SYSREG_ID_elr_el1 SYSREG_ESR(3, 0, 4, 0, 1)
+#define SYSREG_ID_spsr_el1 SYSREG_ESR(3, 0, 4, 0, 0)
+#define SYSREG_ID_pmcr_el0 SYSREG_ESR(3, 3, 9, 12, 0)
+#define SYSREG_ID_tpidrro_el0 SYSREG_ESR(3, 3, 13, 0, 3)
+#define SYSREG_ID_tpidr_el0 SYSREG_ESR(3, 3, 13, 0, 2)
+#define SYSREG_ID_csselr_el1 SYSREG_ESR(3, 2, 0, 0, 0)
+#define SYSREG_ID_sctlr_el1 SYSREG_ESR(3, 0, 1, 0, 0)
+#define SYSREG_ID_actlr_el1 SYSREG_ESR(3, 0, 1, 0, 1)
+#define SYSREG_ID_cpacr_el1 SYSREG_ESR(3, 0, 1, 0, 2)
+#define SYSREG_ID_zcr_el1 SYSREG_ESR(3, 0, 1, 2, 0)
+#define SYSREG_ID_ttbr0_el1 SYSREG_ESR(3, 0, 2, 0, 0)
+#define SYSREG_ID_ttbr1_el1 SYSREG_ESR(3, 0, 2, 0, 1)
+#define SYSREG_ID_tcr_el1 SYSREG_ESR(3, 0, 2, 0, 2)
+#define SYSREG_ID_esr_el1 SYSREG_ESR(3, 0, 5, 2, 0)
+#define SYSREG_ID_afsr0_el1 SYSREG_ESR(3, 0, 5, 1, 0)
+#define SYSREG_ID_afsr1_el1 SYSREG_ESR(3, 0, 5, 1, 1)
+#define SYSREG_ID_far_el1 SYSREG_ESR(3, 0, 6, 0, 0)
+#define SYSREG_ID_mair_el1 SYSREG_ESR(3, 0, 10, 2, 0)
+#define SYSREG_ID_vbar_el1 SYSREG_ESR(3, 0, 12, 0, 0)
+#define SYSREG_ID_contextidr_el1 SYSREG_ESR(3, 0, 13, 0, 1)
+#define SYSREG_ID_tpidr_el1 SYSREG_ESR(3, 0, 13, 0, 4)
+#define SYSREG_ID_amair_el1 SYSREG_ESR(3, 0, 10, 3, 0)
+#define SYSREG_ID_cntkctl_el1 SYSREG_ESR(3, 0, 14, 1, 0)
+#define SYSREG_ID_par_el1 SYSREG_ESR(3, 0, 7, 4, 0)
+#define SYSREG_ID_mdscr_el1 SYSREG_ESR(2, 0, 0, 2, 2)
+#define SYSREG_ID_mdccint_el1 SYSREG_ESR(2, 0, 0, 2, 0)
+#define SYSREG_ID_disr_el1 SYSREG_ESR(3, 0, 12, 1, 1)
+#define SYSREG_ID_mpam0_el1 SYSREG_ESR(3, 0, 10, 5, 1)
+#define SYSREG_ID_apiakeylo_el1 SYSREG_ESR(3, 0, 2, 1, 0)
+#define SYSREG_ID_apiakeyhi_el1 SYSREG_ESR(3, 0, 2, 1, 1)
+#define SYSREG_ID_apibkeylo_el1 SYSREG_ESR(3, 0, 2, 1, 2)
+#define SYSREG_ID_apibkeyhi_el1 SYSREG_ESR(3, 0, 2, 1, 3)
+#define SYSREG_ID_apdakeylo_el1 SYSREG_ESR(3, 0, 2, 2, 0)
+#define SYSREG_ID_apdakeyhi_el1 SYSREG_ESR(3, 0, 2, 2, 1)
+#define SYSREG_ID_apdbkeylo_el1 SYSREG_ESR(3, 0, 2, 2, 2)
+#define SYSREG_ID_apdbkeyhi_el1 SYSREG_ESR(3, 0, 2, 2, 3)
+#define SYSREG_ID_apgakeylo_el1 SYSREG_ESR(3, 0, 2, 3, 0)
+#define SYSREG_ID_apgakeyhi_el1 SYSREG_ESR(3, 0, 2, 3, 1)
+#define SYSREG_ID_mpamidr_el1 SYSREG_ESR(3, 0, 10, 4, 4)
+
#endif /* ARCH_H */
diff --git a/include/lib/timer.h b/include/lib/timer.h
index 0bfff01..ff57cbd 100644
--- a/include/lib/timer.h
+++ b/include/lib/timer.h
@@ -32,6 +32,8 @@
*/
int tftf_initialise_timer(void);
+void tftf_initialise_timer_secondary_core(void);
+
/*
* Requests the timer framework to send an interrupt after milli_secs.
* The interrupt is sent to the calling core of this api. The actual
diff --git a/include/runtime_services/arm_arch_svc.h b/include/runtime_services/arm_arch_svc.h
index 0b4e2ad..4c2358a 100644
--- a/include/runtime_services/arm_arch_svc.h
+++ b/include/runtime_services/arm_arch_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,5 +14,6 @@
#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
#define SMCCC_ARCH_WORKAROUND_3 0x80003FFF
#define SMCCC_ARCH_FEATURE_AVAILABILITY U(0x80000003)
+#define SMCCC_ARCH_WORKAROUND_4 0x80000004
#endif /* __ARM_ARCH_SVC_H__ */
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 4dc3f53..0a63e96 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -357,8 +357,8 @@
*/
struct ffa_partition_rxtx_header {
uint32_t flags;
- /* MBZ */
- uint32_t reserved;
+ /* Reserved (SBZ). */
+ uint32_t reserved_1;
/* Offset from the beginning of the buffer to the message payload. */
uint32_t offset;
/* Sender(Bits[31:16]) and Receiver(Bits[15:0]) endpoint IDs. */
@@ -366,6 +366,10 @@
ffa_id_t sender;
/* Size of message in buffer. */
uint32_t size;
+ /* Reserved (SBZ). Added in v1.2 */
+ uint32_t reserved_2;
+ /* UUID identifying the communication protocol. Added in v1.2. */
+ struct ffa_uuid uuid;
};
#define FFA_RXTX_HEADER_SIZE sizeof(struct ffa_partition_rxtx_header)
@@ -375,11 +379,13 @@
struct ffa_partition_rxtx_header *header)
{
header->flags = 0;
- header->reserved = 0;
+ header->reserved_1 = 0;
header->offset = FFA_RXTX_HEADER_SIZE;
header->sender = sender;
header->receiver = receiver;
header->size = size;
+ header->reserved_2 = 0;
+ header->uuid = (struct ffa_uuid){0};
}
/* The maximum length possible for a single message. */
diff --git a/include/runtime_services/host_realm_managment/host_realm_helper.h b/include/runtime_services/host_realm_managment/host_realm_helper.h
index 168bb0a..6ea9b72 100644
--- a/include/runtime_services/host_realm_managment/host_realm_helper.h
+++ b/include/runtime_services/host_realm_managment/host_realm_helper.h
@@ -18,7 +18,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
/*
* Creates realm, initializes heap, creates RTTs and also
@@ -29,7 +30,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
/*
* Creates realm, initializes heap, creates RTTs,
@@ -40,14 +42,21 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count);
+ unsigned int rec_count,
+ unsigned int num_aux_planes);
bool host_destroy_realm(struct realm *realm_ptr);
void host_rec_send_sgi(struct realm *realm_ptr,
unsigned int sgi, unsigned int rec_num);
bool host_enter_realm_execute(struct realm *realm_ptr, uint8_t cmd,
int test_exit_reason, unsigned int rec_num);
test_result_t host_cmp_result(void);
-void realm_print_handler(struct realm *realm_ptr, unsigned int rec_num);
+void realm_print_handler(struct realm *realm_ptr, unsigned int plane_num, unsigned int rec_num);
bool host_ipa_is_ns(u_register_t addr, u_register_t rmm_feat_reg0);
+/*
+ * This functions sets the shared data args needed for entering aux plane,
+ * using REALM_ENTER_PLANE_N_CMD
+ */
+void host_realm_set_aux_plane_args(struct realm *realm_ptr, unsigned int plane_num);
+
#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
index 7458146..1bef986 100644
--- a/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
+++ b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
@@ -41,8 +41,8 @@
#ifdef ENABLE_REALM_PAYLOAD_TESTS
/* 1MB for shared buffer between Realm and Host */
#define NS_REALM_SHARED_MEM_SIZE U(0x100000)
- /* 8MB of memory used as a pool for realm's objects creation */
- #define PAGE_POOL_MAX_SIZE U(0x800000)
+ /* 10MB of memory used as a pool for realm's objects creation */
+ #define PAGE_POOL_MAX_SIZE U(0xA00000)
#else
#define NS_REALM_SHARED_MEM_SIZE U(0x0)
#define PAGE_POOL_MAX_SIZE U(0x0)
diff --git a/include/runtime_services/host_realm_managment/host_realm_pmu.h b/include/runtime_services/host_realm_managment/host_realm_pmu.h
index 844bb29..66bd385 100644
--- a/include/runtime_services/host_realm_managment/host_realm_pmu.h
+++ b/include/runtime_services/host_realm_managment/host_realm_pmu.h
@@ -23,7 +23,25 @@
#define GET_PMU_CNT \
((read_pmcr_el0() >> PMCR_EL0_N_SHIFT) & PMCR_EL0_N_MASK)
-void host_set_pmu_state(void);
-bool host_check_pmu_state(void);
+#define MAX_COUNTERS 31U
+
+struct pmu_registers {
+ unsigned long pmcr_el0;
+ unsigned long pmcntenset_el0;
+ unsigned long pmovsset_el0;
+ unsigned long pmintenset_el1;
+ unsigned long pmccntr_el0;
+ unsigned long pmccfiltr_el0;
+ unsigned long pmuserenr_el0;
+ unsigned long pmevcntr_el0[MAX_COUNTERS];
+ unsigned long pmevtyper_el0[MAX_COUNTERS];
+ unsigned long pmselr_el0;
+ unsigned long pmxevcntr_el0;
+ unsigned long pmxevtyper_el0;
+} __aligned(64);
+
+void host_set_pmu_state(struct pmu_registers *pmu_ptr);
+
+bool host_check_pmu_state(struct pmu_registers *pmu_ptr);
#endif /* HOST_REALM_PMU_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
index 8f487d0..4de9671 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -146,6 +146,30 @@
/*
* arg0 == RD address
+ * arg1 == RTT address
+ * arg2 == map address
+ * arg3 == level
+ * arg4 == RTT tree index
+ *
+ * ret0 == status/index
+ */
+#define RMI_RTT_AUX_CREATE SMC64_RMI_FID(U(0x2D))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address (PA) of the RTT, if ret0 == RMI_SUCCESS
+ * Otherwise, undefined.
+ * ret2 == Top of the non-live address region. Only valid
+ * if ret0 == RMI_SUCCESS or ret0 == (RMI_ERROR_RTT_WALK, x)
+ */
+#define RMI_RTT_AUX_DESTROY SMC64_RMI_FID(U(0x2E))
+
+/*
+ * arg0 == RD address
* arg1 == map address
* arg2 == level
*
@@ -167,6 +191,31 @@
/*
* arg0 == RD address
* arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ * ret4 == ripas
+ */
+#define RMI_RTT_AUX_MAP_PROTECTED SMC64_RMI_FID(U(0x30))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ */
+#define RMI_RTT_AUX_MAP_UNPROTECTED SMC64_RMI_FID(U(0x31))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
* arg2 == level
*
* ret1 == level
@@ -185,6 +234,40 @@
#define RMI_RTT_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x12))
/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_PROTECTED SMC64_RMI_FID(U(0x33))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_UNPROTECTED SMC64_RMI_FID(U(0x34))
+
+/*
+ * arg0 == RD address
+ * arg1 == target rec
+ * arg2 == base adr
+ * arg3 == top adr
+ *
+ * ret0 == return code
+ * ret1 == Top IPA of range whose S2AP was modified
+ * ret2 == Index of RTT tree in which base alignment check failed
+ */
+#define RMI_RTT_SET_S2AP SMC64_RMI_FID(U(0x3B))
+
+/*
* arg0 == calling rec address
* arg1 == target rec address
*/
@@ -206,6 +289,16 @@
/*
* arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address(PA) of the RTT folded, if ret0 == RMI_SUCCESS
+ */
+#define RMI_RTT_AUX_FOLD SMC64_RMI_FID(U(0x2F))
+
+/*
+ * arg0 == RD address
*/
#define RMI_REC_AUX_COUNT SMC64_RMI_FID(U(0x17))
@@ -398,10 +491,14 @@
#define RMI_FEATURE_FALSE 0U
#define RMI_FEATURE_TRUE 1U
-/* RmiRealmFlags format */
-#define RMI_REALM_FLAGS_LPA2 BIT(0)
-#define RMI_REALM_FLAGS_SVE BIT(1)
-#define RMI_REALM_FLAGS_PMU BIT(2)
+/* RmiRealmFlags0 format */
+#define RMI_REALM_FLAGS0_LPA2 BIT(0)
+#define RMI_REALM_FLAGS0_SVE BIT(1)
+#define RMI_REALM_FLAGS0_PMU BIT(2)
+#define RMI_REALM_FLAGS0_DA BIT(3)
+
+/* RmiRealmFlags1 format */
+#define RMI_REALM_FLAGS1_RTT_TREE_PP BIT(0)
/* RmiInterfaceVersion type */
#define RMI_MAJOR_VERSION 0U
@@ -426,7 +523,11 @@
#define RMI_EXIT_RIPAS_CHANGE 4U
#define RMI_EXIT_HOST_CALL 5U
#define RMI_EXIT_SERROR 6U
-#define RMI_EXIT_INVALID (RMI_EXIT_SERROR + 1U)
+#define RMI_EXIT_IO 7U
+#define RMI_EXIT_RTT_REQUEST 8U
+#define RMI_EXIT_S2AP_CHANGE 9U
+#define RMI_EXIT_VDEV_REQUEST 10U
+#define RMI_EXIT_INVALID (RMI_EXIT_VDEV_REQUEST + 1U)
/* RmiRecRunnable types */
#define RMI_NOT_RUNNABLE 0U
@@ -473,14 +574,27 @@
* Value -1 (0 in case of NUM_BPS and NUM_WPS) indicates not set field,
* and parameter will be set from the corresponding field of feature register 0.
*/
-#define FEATURE_SVE_VL_SHIFT 32UL
-#define FEATURE_SVE_VL_WIDTH 8UL
-#define FEATURE_NUM_BPS_SHIFT 40UL
-#define FEATURE_NUM_BPS_WIDTH 8UL
-#define FEATURE_NUM_WPS_SHIFT 48UL
-#define FEATURE_NUM_WPS_WIDTH 8UL
-#define FEATURE_PMU_NUM_CTRS_SHIFT 56UL
-#define FEATURE_PMU_NUM_CTRS_WIDTH 8UL
+#define RMI_FEATURE_REGISTER_0_DA BIT(42)
+
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_SHIFT 43UL
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_WIDTH 2UL
+
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_SHIFT 45UL
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_WIDTH 4UL
+
+#define FEATURE_SVE_VL_SHIFT 56UL
+#define FEATURE_SVE_VL_WIDTH 4UL
+#define FEATURE_NUM_BPS_SHIFT 14UL
+#define FEATURE_NUM_BPS_WIDTH 6UL
+#define FEATURE_NUM_WPS_SHIFT 20UL
+#define FEATURE_NUM_WPS_WIDTH 6UL
+#define FEATURE_PMU_NUM_CTRS_SHIFT 35UL
+#define FEATURE_PMU_NUM_CTRS_WIDTH 4UL
+
+/* Possible values for RmiPlaneRttFeature */
+#define RMI_PLANE_RTT_AUX 0UL
+#define RMI_PLANE_RTT_AUX_SINGLE 1UL
+#define RMI_PLANE_RTT_SINGLE 2UL
/* RmiStatusCode types */
/*
@@ -520,6 +634,18 @@
* index: RTT level at which the walk terminated
*/
RMI_ERROR_RTT = 4,
+ /*
+ * An attribute of a device does not match the expected value
+ */
+ RMI_ERROR_DEVICE = 5,
+ /*
+ * The command is not supported
+ */
+ RMI_ERROR_NOT_SUPPORTED = 6,
+ /*
+ * RTTE in an auxiliary RTT contained an unexpected value
+ */
+ RMI_ERROR_RTT_AUX = 7,
RMI_ERROR_COUNT
} status_t;
@@ -560,31 +686,41 @@
*/
struct rmi_realm_params {
/* Flags */
- SET_MEMBER(unsigned long flags, 0, 0x8); /* Offset 0 */
+ SET_MEMBER(unsigned long flags0, 0, 0x8); /* Offset 0 */
/* Requested IPA width */
- SET_MEMBER(unsigned int s2sz, 0x8, 0x10); /* 0x8 */
+ SET_MEMBER(unsigned int s2sz, 0x8, 0x10); /* 0x8 */
/* Requested SVE vector length */
- SET_MEMBER(unsigned int sve_vl, 0x10, 0x18); /* 0x10 */
+ SET_MEMBER(unsigned int sve_vl, 0x10, 0x18); /* 0x10 */
/* Requested number of breakpoints */
- SET_MEMBER(unsigned int num_bps, 0x18, 0x20); /* 0x18 */
+ SET_MEMBER(unsigned int num_bps, 0x18, 0x20); /* 0x18 */
/* Requested number of watchpoints */
- SET_MEMBER(unsigned int num_wps, 0x20, 0x28); /* 0x20 */
+ SET_MEMBER(unsigned int num_wps, 0x20, 0x28); /* 0x20 */
/* Requested number of PMU counters */
- SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30); /* 0x28 */
+ SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30); /* 0x28 */
/* Measurement algorithm */
- SET_MEMBER(unsigned char hash_algo, 0x30, 0x400); /* 0x30 */
+ SET_MEMBER(unsigned char algorithm, 0x30, 0x38); /* 0x30 */
+ /* Number of auxiliary Planes */
+ SET_MEMBER(unsigned int num_aux_planes, 0x38, 0x400); /* 0x38 */
/* Realm Personalization Value */
- SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800); /* 0x400 */
+ SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800); /* 0x400 */
SET_MEMBER(struct {
- /* Virtual Machine Identifier */
- unsigned short vmid; /* 0x800 */
- /* Realm Translation Table base */
- u_register_t rtt_base; /* 0x808 */
- /* RTT starting level */
- long rtt_level_start; /* 0x810 */
- /* Number of starting level RTTs */
- unsigned int rtt_num_start; /* 0x818 */
- }, 0x800, 0x1000);
+ /* Virtual Machine Identifier */
+ unsigned short vmid; /* 0x800 */
+ /* Realm Translation Table base */
+ unsigned long rtt_base; /* 0x808 */
+ /* RTT starting level */
+ long rtt_level_start; /* 0x810 */
+ /* Number of starting level RTTs */
+ unsigned int rtt_num_start; /* 0x818 */
+ }, 0x800, 0x820);
+ /* Flags */
+ SET_MEMBER(unsigned long flags1, 0x820, 0x828); /* 0x820 */
+ /* MECID */
+ SET_MEMBER(long mecid, 0x828, 0xF00); /* 0x828 */
+ /* Auxiliary Virtual Machine Identifiers */
+ SET_MEMBER(unsigned short aux_vmid[3], 0xF00, 0xF80); /* 0xF00 */
+ /* Base address of auxiliary RTTs */
+ SET_MEMBER(unsigned long aux_rtt_base[3], 0xF80, 0x1000); /* 0xF80 */
};
/*
@@ -651,7 +787,11 @@
u_register_t far; /* 0x108 */
/* Hypervisor IPA Fault Address register */
u_register_t hpfar; /* 0x110 */
- }, 0x100, 0x200);
+ }, 0x100, 0x118);
+ /* Index of RTT tree active at time of the exit */
+ SET_MEMBER(u_register_t rtt_tree, 0x118, 0x120);/* Offset 0x118 */
+ /* Level of requested RTT */
+ SET_MEMBER(u_register_t rtt_level, 0x120, 0x200);/* Offset 0x120 */
/* General-purpose registers */
SET_MEMBER(u_register_t gprs[REC_EXIT_NR_GPRS], 0x200, 0x300); /* 0x200 */
SET_MEMBER(struct {
@@ -681,7 +821,15 @@
u_register_t ripas_size; /* 0x508 */
/* RIPAS value of pending RIPAS change */
unsigned char ripas_value; /* 0x510 */
- }, 0x500, 0x600);
+ }, 0x500, 0x518);
+ /* Base PA of MMIO region, if RIPAS change
+ * is pending due to exeception of RSI_RDEV_VALIDATE_IO
+ */
+ SET_MEMBER(u_register_t ripas_io_pa, 0x518, 0x520); /* Offset 0x518 */
+ /* Base address of target region for pending S2AP change */
+ SET_MEMBER(u_register_t s2ap_base, 0x520, 0x528); /* Offset 0x520 */
+ /* Top address of target region for pending S2AP change */
+ SET_MEMBER(u_register_t s2ap_top, 0x528, 0x600); /* Offset 0x528 */
/* Host call immediate value */
SET_MEMBER(unsigned int imm, 0x600, 0x700); /* 0x600 */
/* PMU overflow status */
@@ -959,6 +1107,7 @@
struct realm {
u_register_t host_shared_data;
unsigned int rec_count;
+ unsigned int num_aux_planes;
u_register_t par_base;
u_register_t par_size;
u_register_t rd;
@@ -979,9 +1128,12 @@
uint8_t pmu_num_ctrs;
bool payload_created;
bool shared_mem_created;
+ bool rtt_tree_single;
unsigned short vmid;
enum realm_state state;
long start_level;
+ u_register_t aux_rtt_addr[MAX_AUX_PLANE_COUNT];
+ unsigned short aux_vmid[MAX_AUX_PLANE_COUNT];
};
/* RMI/SMC */
@@ -1020,6 +1172,12 @@
u_register_t start,
u_register_t end,
u_register_t *top);
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+ u_register_t rec,
+ u_register_t start,
+ u_register_t end,
+ u_register_t *top,
+ u_register_t *rtt_tree);
u_register_t host_rmi_psci_complete(u_register_t calling_rec, u_register_t target_rec,
unsigned long status);
void host_rmi_init_cmp_result(void);
diff --git a/include/runtime_services/host_realm_managment/host_shared_data.h b/include/runtime_services/host_realm_managment/host_shared_data.h
index 7005c0d..fecb27b 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -36,8 +36,9 @@
/* Buffer to save Realm command results */
uint8_t realm_cmd_output_buffer[REALM_CMD_BUFFER_SIZE];
-} host_shared_data_t;
+}host_shared_data_t;
+typedef host_shared_data_t (*host_shared_data_arr_t)[MAX_PLANE_COUNT][MAX_REC_COUNT];
/*
* Different commands that the Host can requests the Realm to perform
*/
@@ -73,7 +74,9 @@
REALM_SME_UNDEF_ABORT,
REALM_FEAT_DOUBLEFAULT2_TEST,
REALM_ATTESTATION,
- REALM_ATTESTATION_FAULT
+ REALM_ATTESTATION_FAULT,
+ REALM_ENTER_PLANE_N_CMD,
+ REALM_PLANE_N_REG_RW_CMD
};
/*
@@ -82,14 +85,16 @@
enum host_param_index {
HOST_CMD_INDEX = 0U,
HOST_ARG1_INDEX,
- HOST_ARG2_INDEX
+ HOST_ARG2_INDEX,
+ HOST_ARG3_INDEX
};
enum host_call_cmd {
HOST_CALL_GET_SHARED_BUFF_CMD = 1U,
HOST_CALL_EXIT_SUCCESS_CMD,
HOST_CALL_EXIT_FAILED_CMD,
- HOST_CALL_EXIT_PRINT_CMD
+ HOST_CALL_EXIT_PRINT_CMD,
+ HOST_CALL_GET_PLANE_ID_CMD
};
/***************************************
@@ -99,25 +104,34 @@
/*
* Return shared buffer pointer mapped as host_shared_data_t structure
*/
-host_shared_data_t *host_get_shared_structure(struct realm *realm_ptr, unsigned int rec_num);
+host_shared_data_t *host_get_shared_structure(struct realm *realm_ptr,
+ unsigned int plane_num,
+ unsigned int rec_num);
/*
* Set data to be shared from Host to realm
*/
void host_shared_data_set_host_val(struct realm *realm_ptr,
- unsigned int rec_num, uint8_t index, u_register_t val);
+ unsigned int plane_num,
+ unsigned int rec_num,
+ uint8_t index,
+ u_register_t val);
/*
* Get data shared from realm to Host
*/
u_register_t host_shared_data_get_realm_val(struct realm *realm_ptr,
- unsigned int rec_num, uint8_t index);
+ unsigned int plane_num,
+ unsigned int rec_num,
+ uint8_t index);
/*
* Set command to be send from Host to realm
*/
-void host_shared_data_set_realm_cmd(struct realm *realm_ptr, uint8_t cmd,
- unsigned int rec_num);
+void host_shared_data_set_realm_cmd(struct realm *realm_ptr,
+ uint8_t cmd,
+ unsigned int plane_num,
+ unsigned int rec_num);
/****************************************
@@ -127,7 +141,7 @@
/*
* Set guest mapped shared buffer pointer
*/
-void realm_set_shared_structure(host_shared_data_t *ptr);
+void realm_set_shared_structure(u_register_t ptr);
/*
* Get guest mapped shared buffer pointer
@@ -149,4 +163,28 @@
*/
void realm_shared_data_set_my_realm_val(uint8_t index, u_register_t val);
+/*
+ * Set data to be shared from Host/Plane0 to Plane N
+ */
+void realm_shared_data_set_plane_n_val(unsigned int plane_num,
+ unsigned int rec_num, uint8_t index, u_register_t val);
+
+/*
+ * Get data shared from Host/Plane0 to Plane N
+ */
+u_register_t realm_shared_data_get_plane_n_val(unsigned int plane_num,
+ unsigned int rec_num, uint8_t index);
+/*
+ * Get cmd shared from Host/Plane0 to Plane N
+ */
+u_register_t realm_shared_data_get_plane_n_cmd(unsigned int plane_num,
+ unsigned int rec_num, uint8_t index);
+
+/*
+ * Set command to be send from Host/Plane0 to Plane N
+ */
+void realm_shared_data_set_plane_n_cmd(uint8_t cmd,
+ unsigned int plane_num,
+ unsigned int rec_num);
+
#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
index 226034f..5d3a196 100644
--- a/include/runtime_services/host_realm_managment/realm_def.h
+++ b/include/runtime_services/host_realm_managment/realm_def.h
@@ -10,7 +10,7 @@
#include <xlat_tables_defs.h>
-/* 1MB for Realm payload as a default value */
+/* 1 MB for Realm payload as a default value */
#define REALM_MAX_LOAD_IMG_SIZE U(0x100000)
#define REALM_STACK_SIZE 0x1000U
#define DATA_PATTERN_1 0x12345678U
@@ -19,6 +19,10 @@
#define REALM_ERROR 1U
#define MAX_REC_COUNT 17U
#define MAX_REALM_COUNT U(2)
+#define MAX_AUX_PLANE_COUNT U(3)
+#define MAX_PLANE_COUNT MAX_AUX_PLANE_COUNT + U(1)
+#define PRIMARY_RTT_INDEX 0U
+#define PRIMARY_PLANE_ID 0U
/* Only support 4KB at the moment */
diff --git a/include/runtime_services/sdei.h b/include/runtime_services/sdei.h
index 0e0a249..43cb9df 100644
--- a/include/runtime_services/sdei.h
+++ b/include/runtime_services/sdei.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -92,6 +92,8 @@
int64_t sdei_event_context(uint32_t param);
int64_t sdei_event_complete(uint32_t flags);
int64_t sdei_event_complete_and_resume(uint64_t addr);
+int64_t sdei_features(uint32_t feature);
+int64_t sdei_event_get_info(int32_t event, uint32_t info);
#endif /* __ASSEMBLY__ */
#endif /* __SDEI_H__ */
diff --git a/include/runtime_services/spm_test_helpers.h b/include/runtime_services/spm_test_helpers.h
index 93027d6..14b2fb5 100644
--- a/include/runtime_services/spm_test_helpers.h
+++ b/include/runtime_services/spm_test_helpers.h
@@ -104,12 +104,6 @@
event_t *cpu_booted);
/**
- * Call FFA_RUN in the designated SP to make it reach the message loop.
- * Used within CPU_ON handlers, to bring up the SP in the current core.
- */
-bool spm_core_sp_init(ffa_id_t sp_id);
-
-/**
* Initializes the Mailbox for other SPM related tests that need to use
* RXTX buffers.
*/
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 76fa287..3981aa9 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -254,7 +254,7 @@
tftf_prepare_cpu_off();
tftf_set_cpu_offline();
- INFO("Powering off\n");
+ INFO("Powering off CPU:%lx\n", read_mpidr_el1());
/* Flush console before the last CPU is powered off. */
if (tftf_get_ref_cnt() == 0)
@@ -303,10 +303,11 @@
/* Enable the SGI used by the timer management framework */
tftf_irq_enable(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
+ tftf_initialise_timer_secondary_core();
enable_irq();
- INFO("Booting\n");
+ INFO("Booting CPU:%lx\n", read_mpidr_el1());
tftf_set_cpu_online();
diff --git a/lib/sdei/sdei.c b/lib/sdei/sdei.c
index 157ab6c..eb0e961 100644
--- a/lib/sdei/sdei.c
+++ b/lib/sdei/sdei.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -76,6 +76,7 @@
args.arg4 = flags;
args.arg5 = mpidr;
ret = tftf_smc(&args);
+
return ret.ret0;
}
@@ -219,3 +220,26 @@
ret = tftf_smc(&args);
return ret.ret0;
}
+
+int64_t sdei_features(uint32_t feature)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.fid = SDEI_FEATURES;
+ args.arg1 = feature;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+int64_t sdei_event_get_info(int32_t event, uint32_t info)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.fid = SDEI_EVENT_GET_INFO;
+ args.arg1 = event;
+ args.arg2 = info;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
diff --git a/realm/aarch64/realm_entrypoint.S b/realm/aarch64/realm_entrypoint.S
index 7e535bb..1c20dca 100644
--- a/realm/aarch64/realm_entrypoint.S
+++ b/realm/aarch64/realm_entrypoint.S
@@ -81,6 +81,8 @@
*/
adr x0, cold_boot_flag
str xzr, [x0]
+
+ bl realm_plane_init
loop:
/* And jump to the C entrypoint */
bl realm_payload_main
@@ -92,6 +94,7 @@
#if ENABLE_PAUTH
bl pauth_init_enable
#endif
+ bl realm_plane_init
mov x0, x20
b realm_secondary_entrypoint
endfunc realm_entrypoint
diff --git a/realm/include/realm_helpers.h b/realm/include/realm_helpers.h
index 11c4423..7ed8f9b 100644
--- a/realm/include/realm_helpers.h
+++ b/realm/include/realm_helpers.h
@@ -8,8 +8,34 @@
#ifndef REALM_HELPERS_H
#define REALM_HELPERS_H
+#include <realm_rsi.h>
+
/* Generate 64-bit random number */
unsigned long long realm_rand64(void);
+/*
+ * Function to enter Aux Plane from Primary Plane
+ * arg1 == plane index
+ * arg2 == permission index to be used by plane
+ * arg3 == base entrypoint
+ * arg4 == entry flags
+ * aarg5 == run object, needs to be PAGE aligned
+ */
+bool realm_plane_enter(u_register_t plane_index, u_register_t perm_index,
+ u_register_t base, u_register_t flags, rsi_plane_run *run);
+
+/* This function will call the Host to request IPA of the NS shared buffer */
+u_register_t realm_get_ns_buffer(void);
+
+/* This function will return plane index of current plane */
+unsigned int realm_get_my_plane_num(void);
+
+/** This function will return true for primary plane false for aux plane */
+bool realm_is_plane0(void);
+
+/* Function for initializing planes, called at Boot */
+void realm_plane_init(void);
+bool plane_common_init(u_register_t plane_index, u_register_t perm_index,
+ u_register_t base, rsi_plane_run *run);
#endif /* REALM_HELPERS_H */
diff --git a/realm/include/realm_psi.h b/realm/include/realm_psi.h
new file mode 100644
index 0000000..bab2896
--- /dev/null
+++ b/realm/include/realm_psi.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef REALM_PSI_H
+#define REALM_PSI_H
+
+#include <stdint.h>
+#include <realm_rsi.h>
+
+/*
+ * Plane Service Interface
+ * ABIs are designed to be used by auxillary planes to interact with primary plane.
+ * PSI calls uses HVC conduit which causes Plane exit to P0
+ * PSI commands and Planes shared buffer can be used for communication.
+ */
+#define PSI_RETURN_TO_P0 1U
+#define PSI_RETURN_TO_PN 2U
+
+/* PSI Commands to return back to P0 */
+#define PSI_P0_CALL RSI_HOST_CALL
+#define PSI_REALM_CONFIG RSI_REALM_CONFIG
+#define PSI_CALL_EXIT_PRINT_CMD HOST_CALL_EXIT_PRINT_CMD
+#define PSI_CALL_EXIT_SUCCESS_CMD HOST_CALL_EXIT_SUCCESS_CMD
+#define PSI_CALL_EXIT_FAILED_CMD HOST_CALL_EXIT_FAILED_CMD
+#define PSI_CALL_GET_PLANE_ID_CMD HOST_CALL_GET_PLANE_ID_CMD
+#define PSI_CALL_GET_SHARED_BUFF_CMD HOST_CALL_GET_SHARED_BUFF_CMD
+
+/* Exit back to Plane 0 */
+void psi_exit_to_plane0(u_register_t psi_cmd,
+ u_register_t arg1,
+ u_register_t arg2,
+ u_register_t arg3,
+ u_register_t arg4,
+ u_register_t arg5,
+ u_register_t arg6,
+ u_register_t arg7);
+
+/* Request plane_id from P0 */
+u_register_t psi_get_plane_id(void);
+
+#endif /* REALM_PSI_H */
diff --git a/realm/include/realm_rsi.h b/realm/include/realm_rsi.h
index 72ee80e..06f857f 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -8,6 +8,7 @@
#ifndef REALM_RSI_H
#define REALM_RSI_H
+#include <arch.h>
#include <stdint.h>
#include <host_shared_data.h>
#include <tftf_lib.h>
@@ -71,7 +72,9 @@
/* IPA width in bits */
SET_MEMBER(unsigned long ipa_width, 0, 8); /* Offset 0 */
/* Hash algorithm */
- SET_MEMBER(unsigned long algorithm, 8, 0x200); /* Offset 8 */
+ SET_MEMBER(unsigned long algorithm, 8, 0x10); /* Offset 8 */
+ /* Number of auxiliary Planes */
+ SET_MEMBER(unsigned long num_aux_planes, 0x10, 0x200); /* Offset 0x10 */
/* Realm Personalization Value */
SET_MEMBER(unsigned char rpv[RSI_RPV_SIZE], 0x200, 0x1000); /* Offset 0x200 */
};
@@ -157,7 +160,157 @@
#define RSI_NO_CHANGE_DESTROYED 0UL
#define RSI_CHANGE_DESTROYED 1UL
-/* Request RIPAS of a target IPA range to be changed to a specified value */
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ * ret1 == perm value
+ */
+#define RSI_MEM_GET_PERM_VALUE SMC_RSI_FID(0x10U)
+
+/*
+ * arg1 == base adr
+ * arg2 == top adr
+ * arg3 == perm index
+ * arg4 == cookie
+ *
+ * ret0 == status
+ * ret1 == new_base
+ * ret2 == response
+ * ret3 == new_cookie
+ */
+#define RSI_MEM_SET_PERM_INDEX SMC_RSI_FID(0x11U)
+
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ */
+#define RSI_MEM_SET_PERM_VALUE SMC_RSI_FID(0x12U)
+
+#define RSI_PLANE_NR_GPRS 31U
+#define RSI_PLANE_GIC_NUM_LRS 16U
+
+/*
+ * Flags provided by the Primary Plane to the secondary ones upon
+ * plane entry.
+ */
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFI U(1UL << 0)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFE U(1UL << 1)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_HC U(1UL << 2)
+
+/* Data structure used to pass values from P0 to the RMM on Plane entry */
+struct rsi_plane_entry {
+ /* Flags */
+ SET_MEMBER(u_register_t flags, 0, 0x8); /* Offset 0 */
+ /* PC */
+ SET_MEMBER(u_register_t pc, 0x8, 0x100); /* Offset 0x8 */
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x100, 0x200); /* 0x100 */
+ /* EL1 system registers */
+ SET_MEMBER(struct {
+ /* GICv3 Hypervisor Control Register */
+ u_register_t gicv3_hcr; /* 0x200 */
+ /* GICv3 List Registers */
+ u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS]; /* 0x208 */
+ }, 0x200, 0x800);
+};
+
+/* Data structure used to pass values from the RMM to P0 on Plane exit */
+struct rsi_plane_exit {
+ /* Exit reason */
+ SET_MEMBER(u_register_t exit_reason, 0, 0x100);/* Offset 0 */
+ SET_MEMBER(struct {
+ /* Exception Link Register */
+ u_register_t elr; /* 0x100 */
+ /* Exception Syndrome Register */
+ u_register_t esr; /* 0x108 */
+ /* Fault Address Register */
+ u_register_t far; /* 0x108 */
+ /* Hypervisor IPA Fault Address register */
+ u_register_t hpfar; /* 0x110 */
+ }, 0x100, 0x200);
+ /* General-purpose registers */
+ SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x200, 0x300); /* 0x200 */
+ SET_MEMBER(struct {
+ /* GICv3 Hypervisor Control Register */
+ u_register_t gicv3_hcr; /* 0x300 */
+ /* GICv3 List Registers */
+ u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS]; /* 0x308 */
+ /* GICv3 Maintenance Interrupt State Register */
+ u_register_t gicv3_misr; /* 0x388 */
+ /* GICv3 Virtual Machine Control Register */
+ u_register_t gicv3_vmcr; /* 0x390 */
+ }, 0x300, 0x600);
+};
+
+typedef struct {
+ /* Entry information */
+ SET_MEMBER(struct rsi_plane_entry enter, 0, 0x800); /* Offset 0 */
+ /* Exit information */
+ SET_MEMBER(struct rsi_plane_exit exit, 0x800, 0x1000);/* 0x800 */
+} rsi_plane_run;
+
+/*
+ * arg1 == plane index
+ * arg2 == run pointer
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_ENTER SMC_RSI_FID(0x13U)
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ *
+ * ret0 == status
+ * ret1 = register value
+ */
+#define RSI_PLANE_REG_READ SMC_RSI_FID(0x1EU)
+
+u_register_t rsi_plane_reg_read(u_register_t plane_index, u_register_t register_encoding,
+ u_register_t *value);
+
+u_register_t rsi_plane_reg_write(u_register_t plane_index, u_register_t register_encoding,
+ u_register_t value);
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ * arg3 == register value
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_REG_WRITE SMC_RSI_FID(0x1FU)
+
+/*
+ * Function to set overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t perm);
+
+/*
+ * Function to Get overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t *perm);
+
+/* Function to Set overlay permission index for a specified IPA range See RSI_MEM_SET_PERM_INDEX */
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+ u_register_t top,
+ u_register_t perm_index,
+ u_register_t cookie,
+ u_register_t *new_base,
+ u_register_t *response,
+ u_register_t *new_cookie);
+
+/* Request RIPAS of a target IPA range to be changed to a specified value. */
u_register_t rsi_ipa_state_set(u_register_t base,
u_register_t top,
rsi_ripas_type ripas,
@@ -174,9 +327,6 @@
/* This function return RSI_ABI_VERSION */
u_register_t rsi_get_version(u_register_t req_ver);
-/* This function will call the Host to request IPA of the NS shared buffer */
-u_register_t rsi_get_ns_buffer(void);
-
/* This function will initialize the attestation context */
u_register_t rsi_attest_token_init(u_register_t challenge_0,
u_register_t challenge_1,
@@ -195,6 +345,12 @@
u_register_t *bytes_copied);
/* This function call Host and request to exit Realm with proper exit code */
-void rsi_exit_to_host(enum host_call_cmd exit_code);
+u_register_t rsi_exit_to_host(enum host_call_cmd exit_code);
+
+/* Function to get Realm configuration. See RSI_REALM_CONFIG */
+u_register_t rsi_realm_config(struct rsi_realm_config *s);
+
+/* Function to enter aux plane. See RSI_PLANE_ENTER */
+u_register_t rsi_plane_enter(u_register_t plane_index, u_register_t run);
#endif /* REALM_RSI_H */
diff --git a/realm/realm.mk b/realm/realm.mk
index 3e66adc..7d21ed5 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -34,8 +34,10 @@
realm_multiple_rec.c \
realm_pauth.c \
realm_payload_main.c \
+ realm_plane.c \
realm_pmuv3.c \
realm_psci.c \
+ realm_psi.c \
realm_rsi.c \
realm_shared_data.c \
realm_simd.c \
@@ -44,6 +46,7 @@
REALM_SOURCES += lib/${ARCH}/cache_helpers.S \
lib/${ARCH}/misc_helpers.S \
lib/smc/${ARCH}/asm_smc.S \
+ lib/smc/${ARCH}/hvc.c \
lib/smc/${ARCH}/smc.c \
lib/exceptions/${ARCH}/serror.c \
lib/exceptions/${ARCH}/sync.c \
diff --git a/realm/realm_debug.c b/realm/realm_debug.c
index 1c4ee03..6bf8adf 100644
--- a/realm/realm_debug.c
+++ b/realm/realm_debug.c
@@ -11,6 +11,8 @@
#include <arch_helpers.h>
#include <host_shared_data.h>
+#include <realm_helpers.h>
+#include <realm_psi.h>
#include <realm_rsi.h>
/*
@@ -23,6 +25,7 @@
host_shared_data_t *guest_shared_data = realm_get_my_shared_structure();
char *log_buffer = (char *)guest_shared_data->log_buffer;
va_list args;
+ u_register_t ret;
va_start(args, fmt);
if (strnlen((const char *)log_buffer, MAX_BUF_SIZE) == MAX_BUF_SIZE) {
@@ -32,7 +35,15 @@
strnlen((const char *)log_buffer, MAX_BUF_SIZE),
MAX_BUF_SIZE, fmt, args);
va_end(args);
- rsi_exit_to_host(HOST_CALL_EXIT_PRINT_CMD);
+ ret = rsi_exit_to_host(HOST_CALL_EXIT_PRINT_CMD);
+
+ /*
+ * Retry with PSI call for secondary planes
+ * Note - RSI_HOST_CALL will fail if test in P0 sets trap_hc flag in plane_enter
+ */
+ if ((ret != RSI_SUCCESS && !realm_is_plane0())) {
+ psi_exit_to_plane0(PSI_CALL_EXIT_PRINT_CMD, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+ }
}
void __attribute__((__noreturn__)) do_panic(const char *file, int line)
diff --git a/realm/realm_helpers.c b/realm/realm_helpers.c
index 6a3c57d..bf47efc 100644
--- a/realm/realm_helpers.c
+++ b/realm/realm_helpers.c
@@ -5,6 +5,10 @@
*/
#include <stdlib.h>
+#include <realm_helpers.h>
+#include <realm_psi.h>
+#include <realm_rsi.h>
+#include <smccc.h>
/* Generate 64-bit random number */
unsigned long long realm_rand64(void)
@@ -12,3 +16,26 @@
return ((unsigned long long)rand() << 32) | rand();
}
+/* This function will call the Host to request IPA of the NS shared buffer */
+u_register_t realm_get_ns_buffer(void)
+{
+ smc_ret_values res = {};
+ struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
+
+ 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) {
+ /* retry with PSI */
+ hvc_ret_values ret = tftf_hvc(&(hvc_args) {PSI_CALL_GET_SHARED_BUFF_CMD, 0UL, 0UL,
+ 0UL, 0UL, 0UL, 0UL, 0UL});
+
+ if (ret.ret0 != RSI_SUCCESS) {
+ return 0U;
+ }
+ return ret.ret1;
+ }
+
+ return host_cal.gprs[0];
+}
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 3339b9a..aeadb9e 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -14,6 +14,8 @@
#include <host_shared_data.h>
#include <pauth.h>
#include "realm_def.h"
+#include <realm_helpers.h>
+#include <realm_psi.h>
#include <realm_rsi.h>
#include <realm_tests.h>
#include <serror.h>
@@ -22,6 +24,7 @@
static fpu_state_t rl_fpu_state_write;
static fpu_state_t rl_fpu_state_read;
+static rsi_plane_run run __aligned(PAGE_SIZE);
/*
* This function reads sleep time in ms from shared buffer and spins PE
@@ -42,6 +45,105 @@
}
}
+static bool test_realm_enter_plane_n(void)
+{
+ u_register_t base, plane_index, perm_index, flags = 0U;
+ bool ret1;
+
+ plane_index = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+ base = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+ perm_index = plane_index + 1U;
+
+ ret1 = plane_common_init(plane_index, perm_index, base, &run);
+ if (!ret1) {
+ return ret1;
+ }
+
+ realm_printf("Entering plane %ld, ep=0x%lx run=0x%lx\n", plane_index, base, &run);
+ return realm_plane_enter(plane_index, perm_index, base, flags, &run);
+}
+
+static bool test_realm_enter_plane_n_reg_rw(void)
+{
+ u_register_t base, plane_index, perm_index, flags = 0U;
+ u_register_t reg1, reg2, reg3, reg4, ret;
+ bool ret1;
+
+ if (realm_is_plane0()) {
+ plane_index = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+ base = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+ perm_index = plane_index + 1U;
+
+ ret1 = plane_common_init(plane_index, perm_index, base, &run);
+ if (!ret1) {
+ return ret1;
+ }
+
+ realm_printf("Entering plane %ld, ep=0x%lx run=0x%lx\n", plane_index, base, &run);
+ ret = realm_plane_enter(plane_index, perm_index, base, flags, &run);
+ if (ret) {
+ /* get return value from plane1 */
+ reg1 = realm_shared_data_get_plane_n_val(plane_index,
+ REC_IDX(read_mpidr_el1()), HOST_ARG1_INDEX);
+
+ reg2 = realm_shared_data_get_plane_n_val(plane_index,
+ REC_IDX(read_mpidr_el1()), HOST_ARG2_INDEX);
+
+ realm_printf("P0 read 0x%lx 0x%lx\n", reg1, reg2);
+
+ /* read pauth register for plane1 */
+ ret = rsi_plane_reg_read(plane_index, SYSREG_ID_apiakeylo_el1, ®3);
+ if ((ret != RSI_SUCCESS) || (reg1 != reg3)) {
+ realm_printf("pauth register mismatch 0x%lx 0x%lx\n", reg1, reg3);
+ return false;
+ }
+
+ /* read sctlr register for plane1 */
+ ret = rsi_plane_reg_read(plane_index, SYSREG_ID_sctlr_el1, ®4);
+ if ((ret != RSI_SUCCESS) || (reg2 != reg4)) {
+ realm_printf("sctlr register mismatch 0x%lx 0x%lx\n", reg2, reg4);
+ return false;
+ }
+
+ /* write pauth register and verify it is same after exiting plane n */
+ ret = rsi_plane_reg_write(plane_index, SYSREG_ID_apibkeylo_el1, 0xABCD);
+ if (ret != RSI_SUCCESS) {
+ realm_printf("pauth register write failed\n");
+ return false;
+ }
+
+ /* enter plane n */
+ ret = realm_plane_enter(plane_index, perm_index, base, flags, &run);
+ if (ret) {
+ /* read pauth register for plane1 */
+ ret = rsi_plane_reg_read(plane_index, SYSREG_ID_apibkeylo_el1,
+ ®3);
+
+ if ((ret != RSI_SUCCESS) || (reg3 != 0xABCD)) {
+ realm_printf("reg mismatch after write 0x%lx\n", reg3);
+ return false;
+ }
+ }
+
+ /* read sysreg not supported by rmm, expect error */
+ ret = rsi_plane_reg_read(plane_index, SYSREG_ID_mpamidr_el1, ®3);
+ if (ret == RSI_SUCCESS) {
+ realm_printf("reg read should have failed\n");
+ return false;
+ }
+ return true;
+ }
+ return false;
+ } else {
+ realm_printf("PN set 0x%lx 0x%lx\n", read_apiakeylo_el1(), read_sctlr_el1());
+
+ /* return pauth and sctlr back to p0 */
+ realm_shared_data_set_my_realm_val(HOST_ARG1_INDEX, read_apiakeylo_el1());
+ realm_shared_data_set_my_realm_val(HOST_ARG2_INDEX, read_sctlr_el1());
+ return true;
+ }
+}
+
/*
* This function requests RSI/ABI version from RMM.
*/
@@ -184,18 +286,20 @@
static bool realm_exception_handler(void)
{
- u_register_t base, far, esr;
+ u_register_t base, far, esr, elr;
base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
far = read_far_el1();
esr = read_esr_el1();
+ elr = read_elr_el1();
if (far == base) {
/* Return ESR to Host */
realm_shared_data_set_my_realm_val(HOST_ARG2_INDEX, esr);
rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
}
- realm_printf("Realm Abort fail incorrect FAR=0x%lx ESR=0x%lx\n", far, esr);
+ realm_printf("Realm Abort fail incorrect FAR=0x%lx ESR=0x%lx ELR=0x%lx\n",
+ far, esr, elr);
rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
/* Should not return */
@@ -266,7 +370,7 @@
/* No serror handler registered by default */
unregister_custom_serror_handler();
- realm_set_shared_structure((host_shared_data_t *)rsi_get_ns_buffer());
+ realm_set_shared_structure(realm_get_ns_buffer());
if (realm_get_my_shared_structure() != NULL) {
uint8_t cmd = realm_shared_data_get_my_realm_cmd();
@@ -280,6 +384,12 @@
realm_loop_cmd();
test_succeed = true;
break;
+ case REALM_ENTER_PLANE_N_CMD:
+ test_succeed = test_realm_enter_plane_n();
+ break;
+ case REALM_PLANE_N_REG_RW_CMD:
+ test_succeed = test_realm_enter_plane_n_reg_rw();
+ break;
case REALM_MULTIPLE_REC_PSCI_DENIED_CMD:
test_succeed = test_realm_multiple_rec_psci_denied_cmd();
break;
@@ -381,8 +491,18 @@
}
if (test_succeed) {
- rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+ if (realm_is_plane0()) {
+ rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+ } else {
+ psi_exit_to_plane0(PSI_CALL_EXIT_SUCCESS_CMD,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+ }
} else {
- rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+ if (realm_is_plane0()) {
+ rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+ } else {
+ psi_exit_to_plane0(PSI_CALL_EXIT_FAILED_CMD,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+ }
}
}
diff --git a/realm/realm_plane.c b/realm/realm_plane.c
new file mode 100644
index 0000000..c7225ed
--- /dev/null
+++ b/realm/realm_plane.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <stdio.h>
+#include <arch.h>
+#include <arch_features.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <host_realm_helper.h>
+#include <realm_psi.h>
+#include <realm_rsi.h>
+#include <sync.h>
+
+static bool is_plane0;
+static unsigned int plane_num;
+
+bool realm_is_plane0(void)
+{
+ return is_plane0;
+}
+
+unsigned int realm_get_my_plane_num(void)
+{
+ return plane_num;
+}
+
+void realm_plane_init(void)
+{
+ u_register_t ret;
+
+ ret = rsi_get_version(RSI_ABI_VERSION_VAL);
+ if (ret == RSI_ERROR_STATE) {
+ is_plane0 = false;
+ plane_num = (unsigned int)psi_get_plane_id();
+ } else {
+ is_plane0 = true;
+ plane_num = PRIMARY_PLANE_ID;
+ }
+}
+
+static void restore_plane_context(rsi_plane_run *run)
+{
+ for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
+ run->enter.gprs[i] = run->exit.gprs[i];
+ }
+
+ run->enter.pc = run->exit.elr;
+}
+
+static u_register_t realm_exit_to_host_as_plane_n(enum host_call_cmd exit_code,
+ u_register_t plane_num)
+{
+ struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
+ smc_ret_values res = {};
+
+ assert(realm_is_p0());
+ host_cal.imm = exit_code;
+ host_cal.gprs[0] = plane_num;
+ host_cal.gprs[1] = read_mpidr_el1();
+ res = tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+ return res.ret0;
+}
+
+/* return true to re-enter PlaneN, false to exit to P0 */
+u_register_t handle_plane_exit(u_register_t plane_index,
+ u_register_t perm_index,
+ rsi_plane_run *run)
+{
+ u_register_t ec = EC_BITS(run->exit.esr);
+ u_register_t ret;
+
+ if (((run->exit.esr & ISS_FSC_MASK) >= FSC_L0_PERM_FAULT) &&
+ ((run->exit.esr & ISS_FSC_MASK) <= FSC_L3_PERM_FAULT)) {
+
+ /* If Plane N exit is due to permission fault, change s2ap */
+ u_register_t base, new_base, response, ret;
+ u_register_t new_cookie = 0UL;
+
+ new_base = base = (run->exit.far & ~PAGE_SIZE_MASK);
+
+ VERBOSE("P0 set s2ap 0x%lx\n", base);
+ while (new_base != (base + PAGE_SIZE)) {
+
+ ret = rsi_mem_set_perm_index(new_base, base + PAGE_SIZE,
+ perm_index, new_cookie, &new_base,
+ &response, &new_cookie);
+
+ if (ret != RSI_SUCCESS || response == RSI_REJECT) {
+ ERROR("rsi_mem_set_perm_index failed 0x%lx\n", new_base);
+ return PSI_RETURN_TO_P0;
+ }
+ }
+
+ restore_plane_context(run);
+ return PSI_RETURN_TO_PN;
+ }
+
+ /* Disallow SMC from Plane N */
+ if (ec == EC_AARCH64_SMC) {
+ /* TODO Support PSCI in future */
+ restore_plane_context(run);
+ run->enter.gprs[0] = RSI_ERROR_STATE;
+ return PSI_RETURN_TO_PN;
+ }
+
+ /* Handle PSI HVC call from Plane N */
+ if (ec == EC_AARCH64_HVC) {
+ u_register_t hvc_id = run->exit.gprs[0];
+
+ restore_plane_context(run);
+ switch (hvc_id) {
+ case PSI_CALL_GET_SHARED_BUFF_CMD:
+ run->enter.gprs[0] = RSI_SUCCESS;
+ run->enter.gprs[1] = (u_register_t)realm_get_my_shared_structure();
+ return PSI_RETURN_TO_PN;
+ case PSI_CALL_GET_PLANE_ID_CMD:
+ run->enter.gprs[0] = RSI_SUCCESS;
+ run->enter.gprs[1] = plane_index;
+ return PSI_RETURN_TO_PN;
+ case PSI_CALL_EXIT_PRINT_CMD:
+ /* exit to host to flush buffer, then return to PN */
+ ret = realm_exit_to_host_as_plane_n(HOST_CALL_EXIT_PRINT_CMD, plane_index);
+ run->enter.gprs[0] = ret;
+ return PSI_RETURN_TO_PN;
+ case PSI_P0_CALL:
+ default:
+ return PSI_RETURN_TO_P0;
+ }
+ }
+ return PSI_RETURN_TO_P0;
+}
+
+bool plane_common_init(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t base,
+ rsi_plane_run *run)
+{
+ u_register_t ret;
+
+ memset(run, 0, sizeof(rsi_plane_run));
+ run->enter.pc = base;
+
+ /* Perm init */
+ ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
+ if (ret != RSI_SUCCESS) {
+ ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
+ return false;
+ }
+ return true;
+}
+
+bool realm_plane_enter(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t base,
+ u_register_t flags,
+ rsi_plane_run *run)
+{
+ u_register_t ret;
+
+ run->enter.flags = flags;
+
+ while (true) {
+ ret = rsi_plane_enter(plane_index, (u_register_t)run);
+ if (ret != RSI_SUCCESS) {
+ ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
+ return false;
+ }
+
+ VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
+ run->exit.exit_reason,
+ run->exit.esr,
+ run->exit.hpfar,
+ run->exit.far);
+
+ ret = handle_plane_exit(plane_index, perm_index, run);
+
+ if (ret != PSI_RETURN_TO_PN) {
+ return true;
+ }
+ }
+}
+
diff --git a/realm/realm_pmuv3.c b/realm/realm_pmuv3.c
index 0d4782a..214f6df 100644
--- a/realm/realm_pmuv3.c
+++ b/realm/realm_pmuv3.c
@@ -19,7 +19,6 @@
#define PMU_EVT_MEM_ACCESS 0x13
#define NOP_REPETITIONS 50
-#define MAX_COUNTERS 32
#define PRE_OVERFLOW ~(0xF)
diff --git a/realm/realm_psi.c b/realm/realm_psi.c
new file mode 100644
index 0000000..9939d7e
--- /dev/null
+++ b/realm/realm_psi.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <host_realm_rmi.h>
+#include <realm_helpers.h>
+#include <realm_psi.h>
+#include <realm_rsi.h>
+#include <smccc.h>
+
+void psi_exit_to_plane0(u_register_t psi_cmd,
+ u_register_t arg1,
+ u_register_t arg2,
+ u_register_t arg3,
+ u_register_t arg4,
+ u_register_t arg5,
+ u_register_t arg6,
+ u_register_t arg7)
+{
+ if (realm_is_plane0()) {
+ return;
+ }
+ tftf_hvc(&(hvc_args) {psi_cmd, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7});
+}
+
+u_register_t psi_get_plane_id(void)
+{
+ hvc_ret_values res = tftf_hvc(&(hvc_args) {PSI_CALL_GET_PLANE_ID_CMD, 0UL, 0UL,
+ 0UL, 0UL, 0UL, 0UL, 0UL});
+
+ if (res.ret0 != RSI_SUCCESS) {
+ return (u_register_t)-1;
+ }
+ return res.ret1;
+}
+
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index db2394c..4e223ca 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -8,6 +8,7 @@
#include <host_realm_rmi.h>
#include <lib/aarch64/arch_features.h>
+#include <realm_helpers.h>
#include <realm_rsi.h>
#include <smccc.h>
@@ -22,34 +23,27 @@
if (res.ret0 == SMC_UNKNOWN) {
return SMC_UNKNOWN;
}
+
+ if (res.ret0 == RSI_ERROR_STATE) {
+ return RSI_ERROR_STATE;
+ }
+
/* Return lower version */
return res.ret1;
}
-/* 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 = {};
- struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
-
- 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)
+u_register_t rsi_exit_to_host(enum host_call_cmd exit_code)
{
struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
+ smc_ret_values res = {};
host_cal.imm = exit_code;
- host_cal.gprs[0] = read_mpidr_el1();
- tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
+ host_cal.gprs[0] = realm_get_my_plane_num();
+ host_cal.gprs[1] = read_mpidr_el1();
+ res = tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
+ return res.ret0;
}
/* This function will exit to the Host to request RIPAS CHANGE of IPA range */
@@ -141,3 +135,92 @@
}
return res.ret0;
}
+
+u_register_t rsi_realm_config(struct rsi_realm_config *s)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_REALM_CONFIG, (u_register_t)s});
+ return res.ret0;
+}
+
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t *perm)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_GET_PERM_VALUE, plane_index, perm_index});
+ if (res.ret0 == RSI_SUCCESS) {
+ *perm = res.ret1;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+ u_register_t perm_index,
+ u_register_t perm)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_SET_PERM_VALUE, plane_index, perm_index, perm});
+ return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+ u_register_t top,
+ u_register_t perm_index,
+ u_register_t cookie,
+ u_register_t *new_base,
+ u_register_t *response,
+ u_register_t *new_cookie)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_MEM_SET_PERM_INDEX, base, top, perm_index, cookie});
+ if (res.ret0 == RSI_SUCCESS) {
+ *new_base = res.ret1;
+ *response = res.ret2;
+ *new_cookie = res.ret3;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_plane_enter(u_register_t plane_index,
+ u_register_t plane_run)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_PLANE_ENTER, plane_index, plane_run});
+ return res.ret0;
+}
+
+u_register_t rsi_plane_reg_read(u_register_t plane_index,
+ u_register_t register_encoding,
+ u_register_t *value)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_PLANE_REG_READ, plane_index, register_encoding});
+ if (res.ret0 == RSI_SUCCESS) {
+ *value = res.ret1;
+ }
+ return res.ret0;
+}
+
+u_register_t rsi_plane_reg_write(u_register_t plane_index,
+ u_register_t register_encoding,
+ u_register_t value)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_PLANE_REG_WRITE, plane_index, register_encoding, value});
+ return res.ret0;
+}
diff --git a/realm/realm_shared_data.c b/realm/realm_shared_data.c
index 2825796..c52072e 100644
--- a/realm/realm_shared_data.c
+++ b/realm/realm_shared_data.c
@@ -9,6 +9,7 @@
#include <assert.h>
#include <host_shared_data.h>
#include <realm_def.h>
+#include <realm_helpers.h>
/**
* @brief - Returns the base address of the shared region
@@ -16,14 +17,14 @@
* @return - Base address of the shared region
**/
-static host_shared_data_t *guest_shared_data;
+static host_shared_data_arr_t guest_shared_data;
/*
* Set guest mapped shared buffer pointer
*/
-void realm_set_shared_structure(host_shared_data_t *ptr)
+void realm_set_shared_structure(u_register_t ptr)
{
- guest_shared_data = ptr;
+ guest_shared_data = (host_shared_data_arr_t)ptr;
}
/*
@@ -31,7 +32,7 @@
*/
host_shared_data_t *realm_get_my_shared_structure(void)
{
- return &guest_shared_data[REC_IDX(read_mpidr_el1())];
+ return &(*guest_shared_data)[realm_get_my_plane_num()][REC_IDX(read_mpidr_el1())];
}
/*
@@ -40,7 +41,7 @@
u_register_t realm_shared_data_get_my_host_val(uint8_t index)
{
assert(index < MAX_DATA_SIZE);
- return guest_shared_data[REC_IDX(read_mpidr_el1())].host_param_val[index];
+ return (*guest_shared_data)[realm_get_my_plane_num()][REC_IDX(read_mpidr_el1())].host_param_val[index];
}
/*
@@ -48,7 +49,7 @@
*/
uint8_t realm_shared_data_get_my_realm_cmd(void)
{
- return guest_shared_data[REC_IDX(read_mpidr_el1())].realm_cmd;
+ return (*guest_shared_data)[realm_get_my_plane_num()][REC_IDX(read_mpidr_el1())].realm_cmd;
}
/*
@@ -57,6 +58,45 @@
void realm_shared_data_set_my_realm_val(uint8_t index, u_register_t val)
{
assert(index < MAX_DATA_SIZE);
- guest_shared_data[REC_IDX(read_mpidr_el1())].realm_out_val[index] = val;
+ (*guest_shared_data)[realm_get_my_plane_num()][REC_IDX(read_mpidr_el1())].realm_out_val[index] = val;
}
+void realm_shared_data_set_plane_n_val(unsigned int plane_num, unsigned int rec_num,
+ uint8_t index, u_register_t val)
+{
+ assert(index < MAX_DATA_SIZE);
+ assert(plane_num < MAX_PLANE_COUNT);
+ assert(rec_num < MAX_REC_COUNT);
+ assert(is_plane0);
+
+ (*guest_shared_data)[plane_num][rec_num].realm_out_val[index] = val;
+}
+
+u_register_t realm_shared_data_get_plane_n_val(unsigned int plane_num,
+ unsigned int rec_num, uint8_t index)
+{
+ assert(plane_num < MAX_PLANE_COUNT);
+ assert(rec_num < MAX_REC_COUNT);
+ assert(is_plane0);
+
+ return (*guest_shared_data)[plane_num][rec_num].realm_out_val[index];
+}
+
+u_register_t realm_shared_data_get_plane_n_cmd(unsigned int plane_num,
+ unsigned int rec_num, uint8_t index)
+{
+ assert(plane_num < MAX_PLANE_COUNT);
+ assert(rec_num < MAX_REC_COUNT);
+ assert(is_plane0);
+
+ return (*guest_shared_data)[plane_num][rec_num].realm_cmd;
+}
+
+void realm_shared_data_set_plane_n_cmd(uint8_t cmd, unsigned int plane_num, unsigned int rec_num)
+{
+ assert(plane_num < MAX_PLANE_COUNT);
+ assert(rec_num < MAX_REC_COUNT);
+ assert(is_plane0);
+
+ (*guest_shared_data)[plane_num][rec_num].realm_cmd = cmd;
+}
diff --git a/smc_fuzz/dts/auto.dts b/smc_fuzz/dts/auto.dts
new file mode 100644
index 0000000..3c2626c
--- /dev/null
+++ b/smc_fuzz/dts/auto.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ candidates {
+ bias = <1>;
+ sdei_pe_unmask_funcid {
+ bias = <30>;
+ functionname = "sdei_pe_unmask_funcid";
+ };
+ sdei_version_funcid {
+ bias = <30>;
+ functionname = "sdei_version_funcid";
+ };
+ sdei_interrupt_bind_funcid {
+ bias = <30>;
+ functionname = "sdei_interrupt_bind_funcid";
+ };
+ sdei_event_enable_funcid {
+ bias = <30>;
+ functionname = "sdei_event_enable_funcid";
+ };
+ sdei_interrupt_release_funcid {
+ bias = <30>;
+ functionname = "sdei_interrupt_release_funcid";
+ };
+ sdei_features_funcid {
+ bias = <30>;
+ functionname = "sdei_features_funcid";
+ };
+ sdei_private_reset_funcid {
+ bias = <30>;
+ functionname = "sdei_private_reset_funcid";
+ };
+ sdei_event_disable_funcid {
+ bias = <30>;
+ functionname = "sdei_event_disable_funcid";
+ };
+ sdei_event_status_funcid {
+ bias = <30>;
+ functionname = "sdei_event_status_funcid";
+ };
+ sdei_shared_reset_funcid {
+ bias = <30>;
+ functionname = "sdei_shared_reset_funcid";
+ };
+ sdei_event_routing_set_funcid {
+ bias = <30>;
+ functionname = "sdei_event_routing_set_funcid";
+ };
+ sdei_event_unregister_funcid {
+ bias = <30>;
+ functionname = "sdei_event_unregister_funcid";
+ };
+ sdei_pe_mask_funcid {
+ bias = <30>;
+ functionname = "sdei_pe_mask_funcid";
+ };
+ };
+};
diff --git a/smc_fuzz/dts/sdei.dts b/smc_fuzz/dts/sdei.dts
index a8199e1..bf9acf1 100644
--- a/smc_fuzz/dts/sdei.dts
+++ b/smc_fuzz/dts/sdei.dts
@@ -1,12 +1,9 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-
-
-
/dts-v1/;
/ {
@@ -41,6 +38,53 @@
bias = <30>;
functionname = "sdei_shared_reset_funcid";
};
+ sdei_interrupt_bind {
+ bias = <30>;
+ functionname = "sdei_interrupt_bind_funcid";
+ };
+ sdei_event_register {
+ bias = <30>;
+ functionname = "sdei_event_register_funcid";
+ };
+ sdei_event_enable {
+ bias = <30>;
+ functionname = "sdei_event_enable_funcid";
+ };
+ sdei_features {
+ bias = <30>;
+ functionname = "sdei_features_funcid";
+ };
+ sdei_event_disable {
+ bias = <30>;
+ functionname = "sdei_event_disable_funcid";
+ };
+ sdei_event_context {
+ bias = <30>;
+ functionname = "sdei_event_context_funcid";
+ };
+ sdei_event_complete {
+ bias = <30>;
+ functionname = "sdei_event_complete_funcid";
+ };
+ sdei_event_complete_and_resume {
+ bias = <30>;
+ functionname = "sdei_event_complete_and_resume_funcid";
+ };
+ sdei_event_unregister {
+ bias = <30>;
+ functionname = "sdei_event_unregister_funcid";
+ };
+ sdei_event_get_info {
+ bias = <30>;
+ functionname = "sdei_event_get_info_funcid";
+ };
+ sdei_event_routing_set {
+ bias = <30>;
+ functionname = "sdei_event_routing_set_funcid";
+ };
+ sdei_interrupt_release {
+ bias = <30>;
+ functionname = "sdei_interrupt_release_funcid";
+ };
};
-
};
diff --git a/smc_fuzz/dts/sdei_and_vendor.dts b/smc_fuzz/dts/sdei_and_vendor.dts
new file mode 100644
index 0000000..d057cff
--- /dev/null
+++ b/smc_fuzz/dts/sdei_and_vendor.dts
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+ vendor_el3 {
+ bias = <1>;
+ uid {
+ bias = <30>;
+ functionname = "ven_el3_svc_uuid_funcid";
+ };
+ count {
+ bias = <30>;
+ functionname = "ven_el3_svc_count_funcid";
+ };
+ version {
+ bias = <30>;
+ functionname = "ven_el3_svc_version_funcid";
+ };
+ };
+
+ sdei {
+ bias = <0>;
+ sdei_version {
+ bias = <30>;
+ functionname = "sdei_version_funcid";
+ };
+ sdei_pe_unmask {
+ bias = <30>;
+ functionname = "sdei_pe_unmask_funcid";
+ };
+ sdei_pe_mask {
+ bias = <30>;
+ functionname = "sdei_pe_mask_funcid";
+ };
+ sdei_event_status {
+ bias = <30>;
+ functionname = "sdei_event_status_funcid";
+ };
+ sdei_event_signal {
+ bias = <0>;
+ functionname = "sdei_event_signal_funcid";
+ };
+ sdei_private_reset {
+ bias = <30>;
+ functionname = "sdei_private_reset_funcid";
+ };
+ sdei_shared_reset {
+ bias = <30>;
+ functionname = "sdei_shared_reset_funcid";
+ };
+ sdei_interrupt_bind {
+ bias = <150>;
+ functionname = "sdei_interrupt_bind_funcid";
+ };
+ sdei_event_register {
+ bias = <30>;
+ functionname = "sdei_event_register_funcid";
+ };
+ sdei_event_enable {
+ bias = <30>;
+ functionname = "sdei_event_enable_funcid";
+ };
+ sdei_features {
+ bias = <30>;
+ functionname = "sdei_features_funcid";
+ };
+ sdei_event_disable {
+ bias = <30>;
+ functionname = "sdei_event_disable_funcid";
+ };
+ sdei_event_context {
+ bias = <30>;
+ functionname = "sdei_event_context_funcid";
+ };
+ sdei_event_complete {
+ bias = <30>;
+ functionname = "sdei_event_complete_funcid";
+ };
+ sdei_event_complete_and_resume {
+ bias = <30>;
+ functionname = "sdei_event_complete_and_resume_funcid";
+ };
+ sdei_event_unregister {
+ bias = <30>;
+ functionname = "sdei_event_unregister_funcid";
+ };
+ sdei_event_get_info {
+ bias = <30>;
+ functionname = "sdei_event_get_info_funcid";
+ };
+ sdei_event_routing_set {
+ bias = <30>;
+ functionname = "sdei_event_routing_set_funcid";
+ };
+ sdei_interrupt_release {
+ bias = <30>;
+ functionname = "sdei_interrupt_release_funcid";
+ };
+ };
+};
diff --git a/smc_fuzz/dts/sdei_coverage.dts b/smc_fuzz/dts/sdei_coverage.dts
new file mode 100644
index 0000000..2afbc50
--- /dev/null
+++ b/smc_fuzz/dts/sdei_coverage.dts
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+ sdei {
+ bias = <30>;
+ sdei_version {
+ bias = <30>;
+ functionname = "sdei_version_funcid";
+ };
+ sdei_pe_unmask {
+ bias = <30>;
+ functionname = "sdei_pe_unmask_funcid";
+ };
+ sdei_pe_mask {
+ bias = <30>;
+ functionname = "sdei_pe_mask_funcid";
+ };
+ sdei_event_status {
+ bias = <30>;
+ functionname = "sdei_event_status_funcid";
+ };
+ sdei_event_signal {
+ bias = <30>;
+ functionname = "sdei_event_signal_funcid";
+ };
+ sdei_private_reset {
+ bias = <30>;
+ functionname = "sdei_private_reset_funcid";
+ };
+ sdei_shared_reset {
+ bias = <30>;
+ functionname = "sdei_shared_reset_funcid";
+ };
+ sdei_interrupt_bind {
+ bias = <100>;
+ functionname = "sdei_interrupt_bind_funcid";
+ };
+ // added
+ sdei_event_register {
+ bias = <30>;
+ functionname = "sdei_event_register_funcid";
+ };
+ sdei_event_enable {
+ bias = <30>;
+ functionname = "sdei_event_enable_funcid";
+ };
+ sdei_features {
+ bias = <30>;
+ functionname = "sdei_features_funcid";
+ };
+ sdei_event_disable {
+ bias = <30>;
+ functionname = "sdei_event_disable_funcid";
+ };
+ sdei_event_context {
+ bias = <30>;
+ functionname = "sdei_event_context_funcid";
+ };
+ sdei_event_complete {
+ bias = <30>;
+ functionname = "sdei_event_complete_funcid";
+ };
+ sdei_event_complete_and_resume {
+ bias = <30>;
+ functionname = "sdei_event_complete_and_resume_funcid";
+ };
+ sdei_event_unregister {
+ bias = <30>;
+ functionname = "sdei_event_unregister_funcid";
+ };
+ sdei_event_get_info {
+ bias = <30>;
+ functionname = "sdei_event_get_info_funcid";
+ };
+ sdei_event_routing_set {
+ bias = <30>;
+ functionname = "sdei_event_routing_set_funcid";
+ };
+ sdei_interrupt_release {
+ bias = <30>;
+ functionname = "sdei_interrupt_release_funcid";
+ };
+ sdei_routing_set_coverage {
+ bias = <30>;
+ functionname = "sdei_routing_set_coverage_funcid";
+ };
+ sdei_event_get_info_coverage {
+ bias = <30>;
+ functionname = "sdei_event_get_info_coverage_funcid";
+ };
+ };
+
+};
diff --git a/smc_fuzz/dts/test.dts b/smc_fuzz/dts/test.dts
new file mode 100644
index 0000000..2d2b3ec
--- /dev/null
+++ b/smc_fuzz/dts/test.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ experiment {
+ bias = <1>;
+ interrupt {
+ bias = <30>;
+ functionname = "test_funcid";
+ };
+ interrupt_release {
+ bias = <0>;
+ functionname = "sdei_event_signal_funcid";
+ };
+ event {
+ bias = <0>;
+ functionname = "sdei_event_register_funcid";
+ };
+ };
+};
diff --git a/smc_fuzz/dts/vendor.dts b/smc_fuzz/dts/vendor.dts
new file mode 100644
index 0000000..5abf1bd
--- /dev/null
+++ b/smc_fuzz/dts/vendor.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ vendor_el3 {
+ bias = <1>;
+ uid {
+ bias = <30>;
+ functionname = "ven_el3_svc_uuid_funcid";
+ };
+ count {
+ bias = <30>;
+ functionname = "ven_el3_svc_count_funcid";
+ };
+ version {
+ bias = <30>;
+ functionname = "ven_el3_svc_version_funcid";
+ };
+ };
+};
diff --git a/smc_fuzz/include/constraint.h b/smc_fuzz/include/constraint.h
new file mode 100644
index 0000000..3a4af1d
--- /dev/null
+++ b/smc_fuzz/include/constraint.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef CONSTRAINT_H
+#define CONSTRAINT_H
+
+#include <stdint.h>
+#include "smcmalloc.h"
+
+#define SANITY_LEVEL_0 0
+#define SANITY_LEVEL_1 1
+#define SANITY_LEVEL_2 2
+#define SANITY_LEVEL_3 3
+
+#define FUZZER_CONSTRAINT_SVALUE 0
+#define FUZZER_CONSTRAINT_RANGE 1
+#define FUZZER_CONSTRAINT_VECTOR 2
+
+#define FUZZER_CONSTRAINT_ACCMODE 0
+#define FUZZER_CONSTRAINT_EXCMODE 1
+
+#define FUZZ_MAX_SHIFT_AMNT 16
+#define FUZZ_MAX_REG_SIZE 64
+#define FUZZ_MAX_NAME_SIZE 80
+
+struct inputparameters {
+ uint64_t x1;
+ uint64_t x2;
+ uint64_t x3;
+ uint64_t x4;
+ uint64_t x5;
+ uint64_t x6;
+ uint64_t x7;
+ uint64_t x8;
+ uint64_t x9;
+ uint64_t x10;
+ uint64_t x11;
+ uint64_t x12;
+ uint64_t x13;
+ uint64_t x14;
+ uint64_t x15;
+ uint64_t x16;
+ uint64_t x17;
+};
+
+void setconstraint(int contype, uint64_t *vecinput, int veclen, int fieldnameptr, struct memmod *mmod, int mode);
+struct inputparameters generate_args(int smccall, int sanity);
+uint64_t get_generated_value(int fieldnameptr, struct inputparameters inp);
+void print_smccall(int smccall, struct inputparameters inp);
+#endif /* CONSTRAINT_H */
diff --git a/smc_fuzz/include/sdei.h b/smc_fuzz/include/sdei.h
new file mode 100644
index 0000000..63c9698
--- /dev/null
+++ b/smc_fuzz/include/sdei.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SDEI_H__
+#define __SDEI_H__
+
+#define SDEI_VERSION 0xC4000020
+#define SDEI_EVENT_REGISTER 0xC4000021
+#define SDEI_EVENT_ENABLE 0xC4000022
+#define SDEI_EVENT_DISABLE 0xC4000023
+#define SDEI_EVENT_CONTEXT 0xC4000024
+#define SDEI_EVENT_COMPLETE 0xC4000025
+#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026
+
+#define SDEI_EVENT_UNREGISTER 0xC4000027
+#define SDEI_EVENT_STATUS 0xC4000028
+#define SDEI_EVENT_GET_INFO 0xC4000029
+#define SDEI_EVENT_ROUTING_SET 0xC400002A
+#define SDEI_PE_MASK 0xC400002B
+#define SDEI_PE_UNMASK 0xC400002C
+
+#define SDEI_INTERRUPT_BIND 0xC400002D
+#define SDEI_INTERRUPT_RELEASE 0xC400002E
+#define SDEI_EVENT_SIGNAL 0xC400002F
+#define SDEI_FEATURES 0xC4000030
+#define SDEI_PRIVATE_RESET 0xC4000031
+#define SDEI_SHARED_RESET 0xC4000032
+
+/* For debug */
+#define SDEI_SHOW_DEBUG 0xC400003F
+
+/* SDEI_EVENT_REGISTER flags */
+#define SDEI_REGF_RM_ANY 0
+#define SDEI_REGF_RM_PE 1
+
+/* SDEI_EVENT_COMPLETE status flags */
+#define SDEI_EV_HANDLED 0
+#define SDEI_EV_FAILED 1
+
+/* sde event status values in bit position */
+#define SDEI_STATF_REGISTERED 0
+#define SDEI_STATF_ENABLED 1
+#define SDEI_STATF_RUNNING 2
+
+#define SDEI_INFOF_TYPE 0
+#define SDEI_INFOF_SIGNALABLE 1
+#define SDEI_INFOF_ROUTING_MODE 2
+#define SDEI_INFOF_ROUTING_AFF 3
+
+#define SMC_EINVAL 2
+#define SMC_EDENY 3
+#define SMC_EPEND 5
+#define SMC_ENOMEM 10
+
+#define MAKE_SDEI_VERSION(_major, _minor, _vendor) \
+ (((uint64_t)(_major)) << 48 | \
+ ((uint64_t)(_minor)) << 32 | \
+ (_vendor))
+
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+struct sdei_intr_ctx {
+ unsigned int priority;
+ unsigned int num;
+ unsigned int enabled;
+};
+
+typedef int sdei_handler_t(int ev, uint64_t arg);
+
+void sdei_trigger_event(void);
+void sdei_handler_done(void);
+
+int64_t sdei_version(void);
+int64_t sdei_interrupt_bind(int intr, struct sdei_intr_ctx *intr_ctx);
+int64_t sdei_interrupt_release(int intr, const struct sdei_intr_ctx *intr_ctx);
+int64_t sdei_event_register(int ev, sdei_handler_t *ep,
+ uint64_t ep_arg, int flags, uint64_t mpidr);
+int64_t sdei_event_unregister(int ev);
+int64_t sdei_event_enable(int ev);
+int64_t sdei_event_disable(int ev);
+int64_t sdei_pe_mask(void);
+int64_t sdei_pe_unmask(void);
+int64_t sdei_private_reset(void);
+int64_t sdei_shared_reset(void);
+int64_t sdei_event_signal(uint64_t mpidr);
+int64_t sdei_event_status(int32_t ev);
+int64_t sdei_event_routing_set(int32_t ev, uint64_t flags);
+int64_t sdei_event_context(uint32_t param);
+int64_t sdei_event_complete(uint32_t flags);
+int64_t sdei_event_complete_and_resume(uint64_t addr);
+// added
+int64_t sdei_features(uint32_t feature);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __SDEI_H__ */
diff --git a/smc_fuzz/include/sdei_fuzz_helper.h b/smc_fuzz/include/sdei_fuzz_helper.h
index cf4ddd1..b05cb91 100644
--- a/smc_fuzz/include/sdei_fuzz_helper.h
+++ b/smc_fuzz/include/sdei_fuzz_helper.h
@@ -4,7 +4,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <stdlib.h>
+#include <time.h>
+
#include <fuzz_helper.h>
+#include "smcmalloc.h"
+
#include <power_management.h>
#include <sdei.h>
#include <test_helpers.h>
@@ -34,6 +39,64 @@
#endif
-void tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr);
+#ifndef sdei_event_register_funcid
+#define sdei_event_register_funcid 0
+#endif
+#ifndef sdei_event_enable_funcid
+#define sdei_event_enable_funcid 0
+#endif
+#ifndef sdei_event_disable_funcid
+#define sdei_event_disable_funcid 0
+#endif
+#ifndef sdei_event_context_funcid
+#define sdei_event_context_funcid 0
+#endif
+#ifndef sdei_event_complete_funcid
+#define sdei_event_complete_funcid 0
+#endif
+#ifndef sdei_event_complete_and_resume_funcid
+#define sdei_event_complete_and_resume_funcid 0
+#endif
+#ifndef sdei_event_unregister_funcid
+#define sdei_event_unregister_funcid 0
+#endif
+#ifndef sdei_event_get_info_funcid
+#define sdei_event_get_info_funcid 0
+#endif
+#ifndef sdei_event_routing_set_funcid
+#define sdei_event_routing_set_funcid 0
+#endif
+#ifndef sdei_interrupt_bind_funcid
+#define sdei_interrupt_bind_funcid 0
+#endif
+#ifndef sdei_interrupt_release_funcid
+#define sdei_interrupt_release_funcid 0
+#endif
+#ifndef sdei_features_funcid
+#define sdei_features_funcid 0
+#endif
+#ifndef sdei_signal_hang_funcid
+#define sdei_signal_hang_funcid 0
+#endif
+#ifndef experiment_funcid
+#define experiment_funcid 0
+#endif
+#ifndef repeat_interrupt_bind_funcid
+#define repeat_interrupt_bind_funcid 0
+#endif
+#ifndef sdei_event_get_info_coverage_funcid
+#define sdei_event_get_info_coverage_funcid 0
+#endif
+#ifndef sdei_routing_set_coverage_funcid
+#define sdei_routing_set_coverage_funcid 0
+#endif
+#ifndef test_funcid
+#define test_funcid 0
+#endif
+
+
+int64_t tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr);
void tftf_test_sdei_singlearg(int64_t (*sdei_func)(uint64_t), char *funcstr);
-void run_sdei_fuzz(int funcid);
+void run_sdei_fuzz(int funcid, struct memmod *mmod, bool inrange, int cntid);
+char *return_str(int64_t ret);
+void print_ret(char *funcstr, int64_t ret);
diff --git a/smc_fuzz/include/smcmalloc.h b/smc_fuzz/include/smcmalloc.h
index fe134bf..97b33e9 100644
--- a/smc_fuzz/include/smcmalloc.h
+++ b/smc_fuzz/include/smcmalloc.h
@@ -52,12 +52,12 @@
};
void initmem(void);
-struct peret priorityencoder(unsigned int);
-void *smcmalloc(unsigned int, struct memmod*);
-int smcfree(void*, struct memmod *);
+struct peret priorityencoder(unsigned int ennum);
+void *smcmalloc(unsigned int req, struct memmod *mmod);
+int smcfree(void *vin, struct memmod *mmod);
#ifdef DEBUG_SMC_MALLOC
-void displayblocks(struct memmod *);
-void displaymalloctable(struct memmod *);
+void displayblocks(struct memmod *mmod);
+void displaymalloctable(struct memmod *mmod);
#endif
#endif /* SMCMALLOC_H */
diff --git a/smc_fuzz/include/vendor_fuzz_helper.h b/smc_fuzz/include/vendor_fuzz_helper.h
new file mode 100644
index 0000000..106df12
--- /dev/null
+++ b/smc_fuzz/include/vendor_fuzz_helper.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <time.h>
+
+#include <fuzz_helper.h>
+#include "smcmalloc.h"
+
+#include <power_management.h>
+#include <sdei.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <timer.h>
+
+#ifndef ven_el3_svc_uuid_funcid
+#define ven_el3_svc_uuid_funcid 0
+#endif
+#ifndef ven_el3_svc_count_funcid
+#define ven_el3_svc_count_funcid 0
+#endif
+#ifndef ven_el3_svc_version_funcid
+#define ven_el3_svc_version_funcid 0
+#endif
+
+void run_ven_el3_fuzz(int funcid, struct memmod *mmod);
diff --git a/smc_fuzz/script/gen_arg_struct_def.py b/smc_fuzz/script/gen_arg_struct_def.py
new file mode 100755
index 0000000..ce24679
--- /dev/null
+++ b/smc_fuzz/script/gen_arg_struct_def.py
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2025 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+def gen_arg_struct_def(asdname,argfieldname,arglst,argnumfield):
+ asdfile = open(asdname, "w")
+ hline = "/*\n"
+ hline += " * Copyright (c) 2024, Arm Limited. All rights reserved.\n"
+ hline += " *\n"
+ hline += " * SPDX-License-Identifier: BSD-3-Clause\n"
+ hline += " */\n"
+ hline += "\n"
+ hline += "#ifndef ARG_STRUCT_DEF_H\n"
+ hline += "#define ARG_STRUCT_DEF_H\n"
+ hline += "\n"
+ asdfile.write(hline)
+ smccount = 0
+ argcount = 0
+ for sn in argfieldname:
+ hline = "#define "
+ hline += sn
+ hline += " "
+ hline += str(smccount)
+ hline += "\n"
+ asdfile.write(hline)
+ smccount = smccount + 1
+ smccount = smccount - 1
+ hline = "#define MAX_SMC_CALLS "
+ hline += str(smccount)
+ hline += "\n"
+ asdfile.write(hline)
+ asdfile.write("\n")
+ for sn in arglst:
+ for an in arglst[sn]:
+ hline = "#define "
+ hline += sn
+ hline += "_ARG" + str(an) + " " + str(argcount)
+ hline += "\n"
+ asdfile.write(hline)
+ argcount = argcount + 1
+ argcount = argcount - 1
+ hline = "#define MAX_ARG_LENGTH "
+ hline += str(argcount)
+ hline += "\n\n"
+ asdfile.write(hline)
+ for sn in argnumfield:
+ for ag in argnumfield[sn]:
+ fieldcount = 0
+ for fn in argnumfield[sn][ag]:
+ hline = "#define " + sn + "_ARG" + str(argnumfield[sn][ag][fn]) + "_" + fn.upper() + "_CNT " + str(fieldcount)
+ hline += "\n"
+ asdfile.write(hline)
+ fieldcount = fieldcount + 1
+ fieldcount = 0
+ hline = "\n\n"
+ asdfile.write(hline)
+ for sn in argnumfield:
+ for ag in argnumfield[sn]:
+ for fn in argnumfield[sn][ag]:
+ hline = "#define " + sn + "_ARG" + str(argnumfield[sn][ag][fn]) + "_" + fn.upper() + " " + str(fieldcount)
+ hline += "\n"
+ asdfile.write(hline)
+ fieldcount = fieldcount + 1
+ hline = "\n#endif /* ARG_STRUCT_DEF_H */\n"
+ asdfile.write(hline)
+
+ asdfile.close()
diff --git a/smc_fuzz/script/gen_field_specification.py b/smc_fuzz/script/gen_field_specification.py
new file mode 100755
index 0000000..86eff31
--- /dev/null
+++ b/smc_fuzz/script/gen_field_specification.py
@@ -0,0 +1,152 @@
+#
+# Copyright (c) 2025 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+def gen_field_specification(fsname,argfieldname,argendbit,argstartbit,argdefval,argnumfield):
+ faafile = open(fsname, "w")
+ hline = "struct fuzzer_arg_def {\n"
+ hline += " int regnum;\n"
+ hline += " char smcname[FUZZ_MAX_NAME_SIZE];\n"
+ hline += " char smcargname[FUZZ_MAX_NAME_SIZE];\n"
+ hline += " int bitw;\n"
+ hline += " int bitst;\n"
+ hline += " char bnames[FUZZ_MAX_NAME_SIZE];\n"
+ hline += " uint64_t defval;\n"
+ hline += " uint64_t **contval;\n"
+ hline += " int *contvallen;\n"
+ hline += " int contlen;\n"
+ hline += " int *conttype;\n"
+ hline += " int genvalues;\n"
+ hline += "};\n\n"
+ hline += "struct fuzzer_arg_arange {\n"
+ hline += " int arg_span[2];\n"
+ hline += "};\n"
+ faafile.write(hline)
+ hline = "struct fuzzer_arg_def fuzzer_arg_array[] = {\n"
+ faafile.write(hline)
+ ifield = 1
+ for sn in argfieldname:
+ for an in argfieldname[sn]:
+ for fn in argfieldname[sn][an]:
+ if not ifield:
+ hline = ",\n"
+ hline += "{ .bitw = "
+ else:
+ hline = "{ .bitw = "
+ hline += str((int(argendbit[sn][an][fn]) - int(argstartbit[sn][an][fn])) + 1)
+ hline += ", .bitst = " + argstartbit[sn][an][fn] + ", .bnames = \""
+ hline += fn + "\", .defval = " + argdefval[sn][an][fn] + ", .regnum = "
+ hline += argnumfield[sn][an][fn] + ", .smcname = \"" + sn + "\", .smcargname = \""
+ hline += an + "\" }"
+ ifield = 0
+ faafile.write(hline)
+ hline = " };\n\n"
+ faafile.write(hline)
+ lc = 0
+ hline = "struct fuzzer_arg_arange fuzzer_arg_array_lst[] = {" + "\n"
+ faafile.write(hline)
+ ifield = 1
+ for sn in argfieldname:
+ for ag in argfieldname[sn]:
+ if not ifield:
+ hline = ",\n"
+ hline += "{ .arg_span = {" + str(lc) + "," + str(len(argfieldname[sn][ag]) - 1 + lc) + "} }"
+ else :
+ hline = "{ .arg_span = {" + str(lc) + "," + str(len(argfieldname[sn][ag]) - 1 + lc) + "} }"
+ ifield = 0
+ faafile.write(hline)
+ lc = lc + len(argfieldname[sn][ag])
+ hline = " };\n\n"
+ faafile.write(hline)
+ hline = "int fuzzer_arg_array_range[] = {" + "\n"
+ faafile.write(hline)
+ lc = 0
+ ifield = 1
+ hline = ""
+ for sn in argfieldname:
+ if not ifield:
+ hline += ","
+ hline += str(len(argfieldname[sn]))
+ else:
+ hline += str(len(argfieldname[sn]))
+ lc = lc + 1
+ ifield = 0
+ if lc == 20:
+ hline += "\n"
+ lc = 0
+ hline += "};\n\n"
+ faafile.write(hline)
+ hline = "int fuzzer_arg_array_start[] = {" + "\n"
+ faafile.write(hline)
+ lc = 0
+ ifield = 1
+ cargs = 0
+ hline = ""
+ for sn in argfieldname:
+ if not ifield:
+ hline += ","
+ hline += str(cargs)
+ else:
+ hline += str(cargs)
+ cargs = cargs + len(argfieldname[sn])
+ lc = lc + 1
+ ifield = 0
+ if lc == 20:
+ hline += "\n"
+ lc = 0
+ hline += "};\n\n"
+ faafile.write(hline)
+ hline = "int fuzzer_fieldarg[] = {" + "\n"
+ faafile.write(hline)
+ blist = 1
+ hline = "\t"
+ for sn in argnumfield:
+ for ag in argnumfield[sn]:
+ for fn in argnumfield[sn][ag]:
+ if not blist:
+ hline += ",\n\t"
+ blist = 0
+ hline += sn + "_ARG" + str(argnumfield[sn][ag][fn])
+ faafile.write(hline)
+ hline = ""
+ hline = "\n};"
+ faafile.write(hline)
+ hline = "\n\n"
+ faafile.write(hline)
+ hline = "int fuzzer_fieldcall[] = {" + "\n"
+ faafile.write(hline)
+ blist = 1
+ hline = "\t"
+ for sn in argnumfield:
+ for ag in argnumfield[sn]:
+ for fn in argnumfield[sn][ag]:
+ if not blist:
+ hline += ",\n\t"
+ blist = 0
+ hline += sn
+ faafile.write(hline)
+ hline = ""
+ hline = "\n};"
+ faafile.write(hline)
+ hline = "\n\n"
+ faafile.write(hline)
+ hline = "int fuzzer_fieldfld[] = {" + "\n"
+ faafile.write(hline)
+ blist = 1
+ hline = "\t"
+ for sn in argnumfield:
+ for ag in argnumfield[sn]:
+ for fn in argnumfield[sn][ag]:
+ if not blist:
+ hline += ",\n\t"
+ blist = 0
+ hline += sn + "_ARG" + str(argnumfield[sn][ag][fn]) + "_" + fn.upper() + "_CNT"
+ faafile.write(hline)
+ hline = ""
+ hline = "\n};"
+
+ faafile.write(hline)
+
+ faafile.close()
diff --git a/smc_fuzz/script/generate_smc.py b/smc_fuzz/script/generate_smc.py
new file mode 100755
index 0000000..dac5924
--- /dev/null
+++ b/smc_fuzz/script/generate_smc.py
@@ -0,0 +1,45 @@
+# !/usr/bin/env python
+#
+# Copyright (c) 2025 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+#python3 generate_smc.py -s smclist
+#This script generated C files after the read of the SMC description/list file
+import argparse
+import readsmclist
+import gen_arg_struct_def
+import gen_field_specification
+
+parser = argparse.ArgumentParser(
+ prog='generate_smc.py',
+ description='Generates SMC code to add to fuzzer library',
+ epilog='one argument input')
+
+parser.add_argument('-s', '--smclist',help="SMC list file .")
+
+args = parser.parse_args()
+
+print("starting generate SMC")
+
+seq = 0
+
+readsmclist.readsmclist(args.smclist,seq)
+
+arglst = readsmclist.arglst
+argnumfield = readsmclist.argnumfield
+argfieldname = readsmclist.argfieldname
+argstartbit = readsmclist.argstartbit
+argendbit = readsmclist.argendbit
+argdefval = readsmclist.argdefval
+smcname = readsmclist.smcname
+argnum = readsmclist.argnum
+argname = readsmclist.argname
+
+gen_arg_struct_def.gen_arg_struct_def("./include/arg_struct_def.h",argfieldname,arglst,argnumfield)
+
+gen_field_specification.gen_field_specification("./include/field_specification.h",
+argfieldname,argendbit,argstartbit,argdefval,argnumfield)
+
diff --git a/smc_fuzz/script/readsmclist.py b/smc_fuzz/script/readsmclist.py
new file mode 100755
index 0000000..3bfcb6a
--- /dev/null
+++ b/smc_fuzz/script/readsmclist.py
@@ -0,0 +1,193 @@
+#
+# Copyright (c) 2025 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import re
+import copy
+import sys
+
+arglst = {}
+argnumfield = {}
+argfieldname = {}
+argstartbit = {}
+argendbit = {}
+argdefval = {}
+smcname = ""
+argnum = ""
+argname = ""
+
+def readsmclist(smclist,seq):
+ smclistfile = open(smclist, "r")
+ smclist_lines = smclistfile.readlines()
+ smclistfile.close()
+ for sline in smclist_lines:
+ lcon = 0
+ sl = sline.strip()
+ sinstr = re.search(r'^smc:\s*([a-zA-Z0-9_]+)$',sl)
+ if sinstr:
+ smcname = sinstr.group(1)
+ arglst[sinstr.group(1)] = []
+ argnumfield[sinstr.group(1)] = {}
+ argfieldname[sinstr.group(1)] = {}
+ argstartbit[sinstr.group(1)] = {}
+ argendbit[sinstr.group(1)] = {}
+ argdefval[sinstr.group(1)] = {}
+ lcon = 1
+ argoccupy = {}
+ if not seq:
+ seq = seq + 1
+ else:
+ if seq != 2:
+ print("Error: out of sequence for smc call",end=" ")
+ print(smcname)
+ sys.exit()
+ else:
+ seq = 1
+ sinstr = re.search(r'^arg(\d+)\s*:\s*([a-zA-Z0-9_]+)$',sl)
+ if sinstr:
+ if sinstr.group(1) in argoccupy:
+ print("Error: register already specified for SMC call",end=" ")
+ print(smcname,end=" ")
+ print("argument",end=" ")
+ print(sinstr.group(1))
+ sys.exit()
+ argnum = sinstr.group(1)
+ argname = sinstr.group(2)
+ arglst[smcname].append(argnum)
+ argnumfield[smcname][sinstr.group(2)] = {}
+ argfieldname[smcname][sinstr.group(2)] = []
+ argstartbit[smcname][sinstr.group(2)] = {}
+ argendbit[smcname][sinstr.group(2)] = {}
+ argdefval[smcname][sinstr.group(2)] = {}
+ lcon = 1
+ argoccupy[argnum] = 1
+ fieldoccupy = []
+ if seq != 1:
+ if seq != 2:
+ print("Error: out of sequence for arg(value)",end=" ")
+ print("arg",end=" ")
+ print(argnum,end=" ")
+ print("for argname",end=" ")
+ print(argname)
+ sys.exit()
+ else:
+ seq = 2
+ else:
+ seq = seq + 1
+
+ sinstr = re.search(r'^arg(\d+)\s*=\s*(0x[a-fA-F0-9]+|\d+)$',sl)
+ if sinstr:
+ if sinstr.group(1) in argoccupy:
+ print("Error: register already specified for SMC call",end=" ")
+ print(smcname,end=" ")
+ print("argument",end=" ")
+ print(sinstr.group(1))
+ sys.exit()
+ srange = sinstr.group(1)
+ argrangename = smcname + "_args_"+ sinstr.group(1)
+ argnum = srange
+ argname = smcname + "_arg_" + argnum
+ fieldnameargdef = smcname + "_arg_" + argnum + "_field"
+ arglst[smcname].append(argnum)
+ argnumfield[smcname][argname] = {}
+ argfieldname[smcname][argname] = []
+ argstartbit[smcname][argname] = {}
+ argendbit[smcname][argname] = {}
+ argdefval[smcname][argname] = {}
+ argnumfield[smcname][argname][fieldnameargdef] = argnum
+ argfieldname[smcname][argname].append(fieldnameargdef)
+ argstartbit[smcname][argname][fieldnameargdef] = str(0)
+ argendbit[smcname][argname][fieldnameargdef] = str(63)
+ argdefval[smcname][argname][fieldnameargdef] = sinstr.group(2)
+ lcon = 1
+ argoccupy[argnum] = 1
+ if seq != 1:
+ if seq != 2:
+ print("Error: out of sequence for arg(value)",end=" ")
+ print("arg",end=" ")
+ print(argnum,end=" ")
+ print("for argname",end=" ")
+ print(argname)
+ sys.exit()
+ else:
+ seq = seq + 1
+ sinstr = re.search(r'^arg(\d+)-arg(\d+)\s*=\s*(0x[a-fA-F0-9]+|\d+)$',sl)
+ if sinstr:
+ srange = int(sinstr.group(1))
+ erange = int(sinstr.group(2))
+ argrangename = smcname + "_args_"+ sinstr.group(1) + "_" + sinstr.group(2)
+ for i in range((erange - srange) + 1):
+ if str(srange + i) in argoccupy:
+ print("Error: register already specified for SMC call",end=" ")
+ print(smcname,end=" ")
+ print("argument",end=" ")
+ print(str(srange + i))
+ sys.exit()
+ argnum = srange + i
+ argname = smcname + "_arg_" + str(argnum)
+ fieldnameargdef = smcname + "_arg_" + str(argnum) + "_field"
+ arglst[smcname].append(argnum)
+ argnumfield[smcname][argname] = {}
+ argfieldname[smcname][argname] = []
+ argstartbit[smcname][argname] = {}
+ argendbit[smcname][argname] = {}
+ argdefval[smcname][argname] = {}
+ argnumfield[smcname][argname][fieldnameargdef] = str(argnum)
+ argfieldname[smcname][argname].append(fieldnameargdef)
+ argstartbit[smcname][argname][fieldnameargdef] = str(0)
+ argendbit[smcname][argname][fieldnameargdef] = str(63)
+ argdefval[smcname][argname][fieldnameargdef] = sinstr.group(3)
+ argoccupy[str(argnum)] = 1
+ lcon = 1
+ if seq != 1:
+ if seq != 2:
+ print("Error: out of sequence for arg(value)",end=" ")
+ print("arg",end=" ")
+ print(argnum,end=" ")
+ print("for argname",end=" ")
+ print(argname)
+ sys.exit()
+ else:
+ seq = 2
+ else:
+ seq = seq + 1
+ sinstr = re.search(r'^field:([a-zA-Z0-9_]+):\[(\d+),(\d+)\]\s*=\s*(0x[a-fA-F0-9]+|\d+)$',sl)
+ if sinstr:
+ for fs in fieldoccupy:
+ if(((fs[0] <= int(sinstr.group(3))) and (fs[0] >= int(sinstr.group(2)))) or
+ ((fs[1] <= int(sinstr.group(3))) and (fs[1] >= int(sinstr.group(2))))):
+ print("Error: field overlap",end=" ")
+ print(smcname,end=" ")
+ print(argname,end=" ")
+ print(sinstr.group(1),end=" ")
+ print(fs[0],end=" ")
+ print(fs[1],end=" ")
+ print(" with",end=" ")
+ print(sinstr.group(2),end=" ")
+ print(sinstr.group(3))
+ sys.exit()
+ argnumfield[smcname][argname][sinstr.group(1)] = argnum
+ argfieldname[smcname][argname].append(sinstr.group(1))
+ argstartbit[smcname][argname][sinstr.group(1)] = sinstr.group(2)
+ argendbit[smcname][argname][sinstr.group(1)] = sinstr.group(3)
+ argdefval[smcname][argname][sinstr.group(1)] = sinstr.group(4)
+ flist = []
+ flist.append(int(sinstr.group(2)))
+ flist.append(int(sinstr.group(3)))
+ fieldoccupy.append(flist)
+ lcon = 1
+ if seq != 2:
+ print("Error: out of sequence for field")
+ sys.exit()
+ if not lcon:
+ cline = re.search(r'^#',sl)
+ if not cline:
+ if sl:
+ print("Error: malformed line at",end=" ")
+ print(sl)
+ sys.exit()
+ if(seq != 2):
+ print("incorrect ending for smc specification")
+ sys.exit()
diff --git a/smc_fuzz/sdei_and_vendor_smc_calls.txt b/smc_fuzz/sdei_and_vendor_smc_calls.txt
new file mode 100644
index 0000000..63ca64b
--- /dev/null
+++ b/smc_fuzz/sdei_and_vendor_smc_calls.txt
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+smc: SDEI_EVENT_STATUS_CALL
+ arg1:bev
+ field:bev:[0,31] = 0
+smc: SDEI_INTERRUPT_BIND_CALL
+ arg1:interruptnum
+ field:inum:[0,31] = 1
+smc: SDEI_VERSION_CALL
+ arg1-arg17 = 0
+smc: SDEI_EVENT_REGISTER_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+ arg2:entryaddr
+ field:addr:[0,63] = 0
+ arg3:eparg
+ field:arg:[0,63] = 0
+ arg4:flags
+ field:routing:[0,0] = 0
+ field:relative:[1,1] = 0
+ field:reserved:[2,63] = 0
+ arg5:affinity
+ field:aff:[0,63] = 0
+smc: SDEI_EVENT_ENABLE_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+smc: SDEI_FEATURES_CALL
+ arg1:feature
+ field:feat:[0,31] = 0
+smc: SDEI_EVENT_DISABLE_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_CONTEXT_CALL
+ arg1:paramid
+ field:param:[0,31] = 0
+smc: SDEI_EVENT_COMPLETE_CALL
+ arg1:status
+ field:stat:[0,31] = 0
+smc: SDEI_EVENT_COMPLETE_AND_RESUME_CALL
+ arg1:resumeaddr
+ field:addr:[0,63] = 0
+smc: SDEI_EVENT_UNREGISTER_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_GET_INFO_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:info
+ field:info:[0,31] = 0
+smc: SDEI_EVENT_ROUTING_SET_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:routingmode
+ field:routing:[0,0] = 0
+ field:constant:[1,63] = 0
+ arg3:affinity
+ field:aff:[0,63] = 0
+smc: SDEI_PE_MASK_CALL
+ arg1 = 0
+smc: SDEI_PE_UNMASK_CALL
+ arg1 = 0
+smc: SDEI_INTERRUPT_RELEASE_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_SIGNAL_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:targetpe
+ field:pe:[0,31] = 0
+smc: SDEI_PRIVATE_RESET_CALL
+ arg1 = 0
+smc: SDEI_SHARED_RESET_CALL
+ arg1 = 0
+smc: VEN_EL3_SVC_UUID_CALL
+ arg1=0
+smc: VEN_EL3_SVC_COUNT_CALL
+ arg1=0
+smc: VEN_EL3_SVC_VERSION_CALL
+ arg1=0
diff --git a/smc_fuzz/sdei_smc_calls.txt b/smc_fuzz/sdei_smc_calls.txt
new file mode 100644
index 0000000..3017630
--- /dev/null
+++ b/smc_fuzz/sdei_smc_calls.txt
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+smc: SDEI_EVENT_STATUS_CALL
+ arg1:bev
+ field:bev:[0,31] = 0
+smc: SDEI_INTERRUPT_BIND_CALL
+ arg1:interruptnum
+ field:inum:[0,31] = 1
+smc: SDEI_VERSION_CALL
+ arg1-arg17 = 0
+smc: SDEI_EVENT_REGISTER_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+ arg2:entryaddr
+ field:addr:[0,63] = 0
+ arg3:eparg
+ field:arg:[0,63] = 0
+ arg4:flags
+ field:routing:[0,0] = 0
+ field:relative:[1,1] = 0
+ field:reserved:[2,63] = 0
+ arg5:affinity
+ field:aff:[0,63] = 0
+smc: SDEI_EVENT_ENABLE_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+smc: SDEI_FEATURES_CALL
+ arg1:feature
+ field:feat:[0,31] = 0
+smc: SDEI_EVENT_DISABLE_CALL
+ arg1:eventnum
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_CONTEXT_CALL
+ arg1:paramid
+ field:param:[0,31] = 0
+smc: SDEI_EVENT_COMPLETE_CALL
+ arg1:status
+ field:stat:[0,31] = 0
+smc: SDEI_EVENT_COMPLETE_AND_RESUME_CALL
+ arg1:resumeaddr
+ field:addr:[0,63] = 0
+smc: SDEI_EVENT_UNREGISTER_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_GET_INFO_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:info
+ field:info:[0,31] = 0
+smc: SDEI_EVENT_ROUTING_SET_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:routingmode
+ field:routing:[0,0] = 0
+ field:constant:[1,63] = 0
+ arg3:affinity
+ field:aff:[0,63] = 0
+smc: SDEI_PE_MASK_CALL
+ arg1 = 0
+smc: SDEI_PE_UNMASK_CALL
+ arg1 = 0
+smc: SDEI_INTERRUPT_RELEASE_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+smc: SDEI_EVENT_SIGNAL_CALL
+ arg1:event
+ field:enum:[0,31] = 0
+ arg2:targetpe
+ field:pe:[0,31] = 0
+smc: SDEI_PRIVATE_RESET_CALL
+ arg1 = 0
+smc: SDEI_SHARED_RESET_CALL
+ arg1 = 0
diff --git a/smc_fuzz/src/constraint.c b/smc_fuzz/src/constraint.c
new file mode 100644
index 0000000..7e4c4b5
--- /dev/null
+++ b/smc_fuzz/src/constraint.c
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arg_struct_def.h>
+#include <constraint.h>
+#include <field_specification.h>
+
+#include <debug.h>
+
+#ifdef SMC_FUZZ_TMALLOC
+#define GENMALLOC(x) malloc((x))
+#define GENFREE(x) free((x))
+#else
+#define GENMALLOC(x) smcmalloc((x), mmod)
+#define GENFREE(x) smcfree((x), mmod)
+#endif
+
+/*******************************************************
+* Random 64 bit generator for registers
+*******************************************************/
+
+uint64_t rand64bit(void)
+{
+ uint64_t xreg = (rand() % (1 << FUZZ_MAX_SHIFT_AMNT)) << FUZZ_MAX_SHIFT_AMNT;
+
+ xreg = ((rand() % (1 << FUZZ_MAX_SHIFT_AMNT)) | xreg) << FUZZ_MAX_SHIFT_AMNT;
+ xreg = ((rand() % (1 << FUZZ_MAX_SHIFT_AMNT)) | xreg) << FUZZ_MAX_SHIFT_AMNT;
+ xreg = ((rand() % (1 << FUZZ_MAX_SHIFT_AMNT)) | xreg);
+ return xreg;
+}
+
+/*******************************************************
+* Shift left function for registers
+*******************************************************/
+
+uint64_t shiftlft(uint64_t val, int shamnt)
+{
+ uint64_t ressh = val;
+
+ if (shamnt > FUZZ_MAX_REG_SIZE) {
+ printf("Error: cannot shift beyond %d bits\n", FUZZ_MAX_REG_SIZE);
+ panic();
+ }
+ if (shamnt > FUZZ_MAX_SHIFT_AMNT) {
+ for (int i = 0; i < ((shamnt / FUZZ_MAX_SHIFT_AMNT) + 1); i++) {
+ if (i == (shamnt / FUZZ_MAX_SHIFT_AMNT)) {
+ ressh = ressh << (shamnt % FUZZ_MAX_SHIFT_AMNT);
+ } else {
+ ressh = ressh << FUZZ_MAX_SHIFT_AMNT;
+ }
+ }
+ } else {
+ ressh = ressh << shamnt;
+ }
+ return ressh;
+}
+
+/*******************************************************
+* Shift right function for registers
+*******************************************************/
+
+uint64_t shiftrht(uint64_t val, int shamnt)
+{
+ uint64_t ressh = val;
+
+ if (shamnt > FUZZ_MAX_REG_SIZE) {
+ printf("Error: cannot shift beyond %d bits\n", FUZZ_MAX_REG_SIZE);
+ panic();
+ }
+ if (shamnt > FUZZ_MAX_SHIFT_AMNT) {
+ for (int i = 0; i < ((shamnt / FUZZ_MAX_SHIFT_AMNT) + 1); i++) {
+ if (i == (shamnt / FUZZ_MAX_SHIFT_AMNT)) {
+ ressh = ressh >> (shamnt % FUZZ_MAX_SHIFT_AMNT);
+ } else {
+ ressh = ressh >> FUZZ_MAX_SHIFT_AMNT;
+ }
+ }
+ } else {
+ ressh = ressh >> shamnt;
+ }
+ return ressh;
+}
+
+/*******************************************************
+* Set constraints for the fields in the SMC call
+*******************************************************/
+
+
+void setconstraint(int contype, uint64_t *vecinput, int veclen, int fieldnameptr, struct memmod *mmod, int mode)
+{
+ int argdef = fuzzer_fieldarg[fieldnameptr];
+ int fieldname = fuzzer_fieldfld[fieldnameptr];
+
+ if ((argdef > MAX_ARG_LENGTH) || (argdef < 0)) {
+ printf("SMC argument is out of bounds\n");
+ panic();
+ }
+ if ((fieldname > (fuzzer_arg_array_lst[argdef].arg_span[1] -
+ fuzzer_arg_array_lst[argdef].arg_span[0])) || (fieldname < 0)) {
+ printf("SMC fieldname is out of bounds\n");
+ panic();
+ }
+ int fieldptr = fuzzer_arg_array_lst[argdef].arg_span[0] + fieldname;
+
+ if ((contype > FUZZER_CONSTRAINT_VECTOR) || (contype < 0)) {
+ printf("SMC constraint type is out of bounds\n");
+ panic();
+ }
+ if (mode > 2) {
+ printf("SMC constriant mode input is invalid\n");
+ panic();
+ }
+ if (mmod == NULL) {
+ printf("SMC constraint memory pointer is invalid\n");
+ panic();
+ }
+ if (contype == FUZZER_CONSTRAINT_SVALUE) {
+ if (veclen < 1) {
+ printf("vector length to constraint for single value is not large enough");
+ printf(" %d", veclen);
+ panic();
+ }
+ if (vecinput == NULL) {
+ printf("vector input to constraint single value is not defined\n");
+ panic();
+ }
+ if (fuzzer_arg_array[fieldptr].contval == NULL) {
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(1 * sizeof(uint64_t *));
+ fuzzer_arg_array[fieldptr].contval[0][0] = vecinput[0];
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = 1;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+ } else {
+ if (mode == FUZZER_CONSTRAINT_ACCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ if (fuzzer_arg_array[fieldptr].conttype[i] ==
+ FUZZER_CONSTRAINT_SVALUE) {
+ if (fuzzer_arg_array[fieldptr].contval[i][0] == vecinput[0]) {
+ return;
+ }
+ }
+ }
+ uint64_t **tarray;
+
+ tarray = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(uint64_t **));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarray[i] = GENMALLOC(fuzzer_arg_array[fieldptr].contvallen[i]
+ * sizeof(uint64_t *));
+ for (int k = 0; k < fuzzer_arg_array[fieldptr].contvallen[i]; k++) {
+ tarray[i][k] = fuzzer_arg_array[fieldptr].contval[i][k];
+ }
+ }
+ tarray[fuzzer_arg_array[fieldptr].contlen] = GENMALLOC(1 * sizeof(int *));
+ tarray[fuzzer_arg_array[fieldptr].contlen][0] = vecinput[0];
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ fuzzer_arg_array[fieldptr].contval = tarray;
+ int *tarraysingle;
+
+ tarraysingle = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen) * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].contvallen[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = 1;
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ fuzzer_arg_array[fieldptr].contvallen = tarraysingle;
+ tarraysingle = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].conttype[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = contype;
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].conttype = tarraysingle;
+ fuzzer_arg_array[fieldptr].contlen++;
+ }
+ if (mode == FUZZER_CONSTRAINT_EXCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(1 * sizeof(uint64_t *));
+ fuzzer_arg_array[fieldptr].contval[0][0] = vecinput[0];
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = 1;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+ }
+ }
+ }
+ if (contype == FUZZER_CONSTRAINT_RANGE) {
+ if (veclen < 2) {
+ printf("vector length to constraint for range is not large enough");
+ printf(" %d", veclen);
+ panic();
+ }
+ if (vecinput == NULL) {
+ printf("vector inputs to constraint for range is not defined\n");
+ panic();
+ }
+ if (fuzzer_arg_array[fieldptr].contval == NULL) {
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(2 * sizeof(uint64_t *));
+ fuzzer_arg_array[fieldptr].contval[0][0] = vecinput[0];
+ fuzzer_arg_array[fieldptr].contval[0][1] = vecinput[1];
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = 2;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+ } else {
+ if (mode == FUZZER_CONSTRAINT_ACCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ if (fuzzer_arg_array[fieldptr].conttype[i] ==
+ FUZZER_CONSTRAINT_RANGE) {
+ if ((fuzzer_arg_array[fieldptr].contval[i][0] ==
+ vecinput[0]) && (fuzzer_arg_array[fieldptr].contval[i][1]
+ == vecinput[1])) {
+ return;
+ }
+ }
+ }
+ uint64_t **tarray;
+
+ tarray = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(uint64_t **));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarray[i] =
+ GENMALLOC(fuzzer_arg_array[fieldptr].contvallen[i]
+ * sizeof(uint64_t *));
+ for (int k = 0; k < fuzzer_arg_array[fieldptr].contvallen[i]; k++) {
+ tarray[i][k] = fuzzer_arg_array[fieldptr].contval[i][k];
+ }
+ }
+ tarray[fuzzer_arg_array[fieldptr].contlen] = GENMALLOC(2
+ * sizeof(uint64_t *));
+ tarray[fuzzer_arg_array[fieldptr].contlen][0] = vecinput[0];
+ tarray[fuzzer_arg_array[fieldptr].contlen][1] = vecinput[1];
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ fuzzer_arg_array[fieldptr].contval = tarray;
+ int *tarraysingle;
+ tarraysingle =
+ GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen) * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].contvallen[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = 2;
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ fuzzer_arg_array[fieldptr].contvallen = tarraysingle;
+ tarraysingle = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].conttype[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = contype;
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].conttype = tarraysingle;
+ fuzzer_arg_array[fieldptr].contlen++;
+ }
+ if (mode == FUZZER_CONSTRAINT_EXCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(2 * sizeof(uint64_t *));
+ fuzzer_arg_array[fieldptr].contval[0][0] = vecinput[0];
+ fuzzer_arg_array[fieldptr].contval[0][1] = vecinput[1];
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = 2;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+ }
+ }
+ }
+ if (contype == FUZZER_CONSTRAINT_VECTOR) {
+ if (veclen < 2) {
+ printf("vector length to constraint for vector is not large enough");
+ printf(" %d", veclen);
+ panic();
+ }
+ if (vecinput == NULL) {
+ printf("vector input to constraint vector is not defined\n");
+ panic();
+ }
+ if (fuzzer_arg_array[fieldptr].contval == NULL) {
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(veclen * sizeof(uint64_t *));
+ for (int i = 0; i < veclen; i++) {
+ fuzzer_arg_array[fieldptr].contval[0][i] = vecinput[i];
+ }
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = veclen;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+
+ } else {
+ if (mode == FUZZER_CONSTRAINT_ACCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ if (fuzzer_arg_array[fieldptr].conttype[i] ==
+ FUZZER_CONSTRAINT_VECTOR) {
+ if (fuzzer_arg_array[fieldptr].contvallen[i] == veclen) {
+ int fne = 0;
+ for (int j = 0; j <
+ fuzzer_arg_array[fieldptr].contvallen[i]; j++) {
+ if (fuzzer_arg_array[fieldptr].contval
+ [i][j] != vecinput[j]) {
+ fne = 1;
+ }
+ }
+ if (fne == 0) {
+ return;
+ }
+ }
+ }
+ }
+ uint64_t **tarray;
+
+ tarray = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(uint64_t **));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarray[i] = GENMALLOC(fuzzer_arg_array[fieldptr].contvallen
+ [i] * sizeof(uint64_t *));
+ for (int k = 0; k < fuzzer_arg_array[fieldptr].contvallen[i]; k++) {
+ tarray[i][k] = fuzzer_arg_array[fieldptr].contval[i][k];
+ }
+ }
+ tarray[fuzzer_arg_array[fieldptr].contlen] =
+ GENMALLOC(veclen * sizeof(uint64_t *));
+ for (int i = 0; i < veclen; i++) {
+ tarray[fuzzer_arg_array[fieldptr].contlen][i] = vecinput[i];
+ }
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ fuzzer_arg_array[fieldptr].contval = tarray;
+ int *tarraysingle;
+ tarraysingle = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].contvallen[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = veclen;
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ fuzzer_arg_array[fieldptr].contvallen = tarraysingle;
+ tarraysingle = GENMALLOC((1 + fuzzer_arg_array[fieldptr].contlen)
+ * sizeof(int *));
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ tarraysingle[i] = fuzzer_arg_array[fieldptr].conttype[i];
+ }
+ tarraysingle[fuzzer_arg_array[fieldptr].contlen] = contype;
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].conttype = tarraysingle;
+ fuzzer_arg_array[fieldptr].contlen++;
+ }
+ if (mode == FUZZER_CONSTRAINT_EXCMODE) {
+ for (int i = 0; i < fuzzer_arg_array[fieldptr].contlen; i++) {
+ GENFREE(fuzzer_arg_array[fieldptr].contval[i]);
+ }
+ GENFREE(fuzzer_arg_array[fieldptr].contval);
+ GENFREE(fuzzer_arg_array[fieldptr].contvallen);
+ GENFREE(fuzzer_arg_array[fieldptr].conttype);
+ fuzzer_arg_array[fieldptr].contval = GENMALLOC(1 * sizeof(uint64_t **));
+ fuzzer_arg_array[fieldptr].contval[0] = GENMALLOC(veclen
+ * sizeof(uint64_t *));
+ for (int i = 0; i < veclen; i++) {
+ fuzzer_arg_array[fieldptr].contval[0][i] = vecinput[i];
+ }
+ fuzzer_arg_array[fieldptr].contvallen = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].contvallen[0] = veclen;
+ fuzzer_arg_array[fieldptr].contlen = 1;
+ fuzzer_arg_array[fieldptr].conttype = GENMALLOC(1 * sizeof(int *));
+ fuzzer_arg_array[fieldptr].conttype[0] = contype;
+ }
+ }
+ }
+}
+
+/*******************************************************
+* Generate the uncondition(no constraint)
+* fields in the SMC call
+*******************************************************/
+
+uint64_t generate_field_uncon(int smccall, int rsel)
+{
+ uint64_t shiftreg = 0;
+ uint64_t resreg = 0;
+ int fieldptr = 0;
+ int argptr = fuzzer_arg_array_start[smccall] + rsel;
+
+ for (int i = 0; i <= (fuzzer_arg_array_lst[argptr].arg_span[1] -
+ fuzzer_arg_array_lst[argptr].arg_span[0]); i++) {
+ fieldptr = fuzzer_arg_array_lst[argptr].arg_span[0] + i;
+ shiftreg = shiftlft((rand() % shiftlft(1, fuzzer_arg_array[fieldptr].bitw)),
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ return resreg;
+}
+
+uint64_t generate_field_con(int smccall, int rsel)
+{
+ uint64_t shiftreg = 0;
+ uint64_t resreg = 0;
+ int fieldptr = 0;
+ int nullstat = 0;
+ int argptr = fuzzer_arg_array_start[smccall] + rsel;
+
+ for (int i = 0; i <= (fuzzer_arg_array_lst[argptr].arg_span[1] -
+ fuzzer_arg_array_lst[argptr].arg_span[0]); i++) {
+ fieldptr = fuzzer_arg_array_lst[argptr].arg_span[0] + i;
+ nullstat = 0;
+ if (fuzzer_arg_array[fieldptr].contval == NULL) {
+ if (fuzzer_arg_array[fieldptr].defval >
+ (shiftlft(1, fuzzer_arg_array[fieldptr].bitw) - 1)) {
+ printf("Default constraint will not fit inside bitfield %llx %llx\n",
+ fuzzer_arg_array[fieldptr].defval,
+ (shiftlft(1, fuzzer_arg_array[fieldptr].bitw) - 1));
+ panic();
+ } else {
+ shiftreg = shiftlft(fuzzer_arg_array[fieldptr].defval,
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ nullstat = 1;
+ } else if (fuzzer_arg_array[fieldptr].contval[0] == NULL) {
+ if (fuzzer_arg_array[fieldptr].defval >
+ (shiftlft(1, fuzzer_arg_array[fieldptr].bitw) - 1)) {
+ printf("Default constraint will not fit inside bitfield %llx %llx\n",
+ fuzzer_arg_array[fieldptr].defval,
+ (shiftlft(1, fuzzer_arg_array[fieldptr].bitw) - 1));
+ panic();
+ } else {
+ shiftreg = shiftlft(fuzzer_arg_array[fieldptr].defval,
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ nullstat = 1;
+ }
+ if (nullstat == 0) {
+ int selcon = rand() % (fuzzer_arg_array[fieldptr].contlen);
+
+ if (fuzzer_arg_array[fieldptr].conttype[selcon] == FUZZER_CONSTRAINT_SVALUE) {
+ if (fuzzer_arg_array[fieldptr].contval[selcon][0] >
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1)) {
+ printf("Constraint will not fit inside bitfield %llx %llx\n",
+ fuzzer_arg_array[fieldptr].contval[selcon][0],
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1));
+ panic();
+ } else {
+ shiftreg = shiftlft(fuzzer_arg_array[fieldptr].contval[selcon][0],
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ }
+
+ if (fuzzer_arg_array[fieldptr].conttype[selcon] == FUZZER_CONSTRAINT_RANGE) {
+ uint64_t maxn = shiftlft(1, fuzzer_arg_array[fieldptr].bitw);
+
+ if ((fuzzer_arg_array[fieldptr].contval[selcon][0] >
+ ((maxn) - 1)) || ((fuzzer_arg_array[fieldptr].contval[selcon][1] >
+ ((maxn) - 1)))) {
+ if (fuzzer_arg_array[fieldptr].contval[selcon][0] >
+ ((maxn) - 1)) {
+ printf("Constraint will not fit inside bitfield %llx %llx\n",
+ fuzzer_arg_array[fieldptr].contval[selcon][0], ((maxn) - 1));
+ }
+ if (fuzzer_arg_array[fieldptr].contval[selcon][1] >
+ ((maxn) - 1)) {
+ printf("Constraint will not fit inside bitfield %llx %llx\n",
+ fuzzer_arg_array[fieldptr].contval[selcon][1], ((maxn) - 1));
+ }
+ panic();
+ } else {
+ shiftreg = shiftlft(((rand() %
+ (fuzzer_arg_array[fieldptr].contval[selcon][1] -
+ fuzzer_arg_array[fieldptr].contval[selcon][0] + 1)) +
+ fuzzer_arg_array[fieldptr].contval[selcon][0]),
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ }
+
+ if (fuzzer_arg_array[fieldptr].conttype[selcon] == FUZZER_CONSTRAINT_VECTOR) {
+ for (int j = 0; j < fuzzer_arg_array[fieldptr].contvallen[selcon]; j++) {
+ if (fuzzer_arg_array[fieldptr].contval[selcon][j] >
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1)) {
+ printf("Constraint will not fit inside bitfield");
+ printf(" %llx %llx\n",
+ fuzzer_arg_array[fieldptr].contval[selcon][j],
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1));
+ panic();
+ }
+ }
+ shiftreg = shiftlft((fuzzer_arg_array[fieldptr].contval[selcon]
+ [(rand() % (fuzzer_arg_array[fieldptr].contvallen[selcon]))]),
+ fuzzer_arg_array[fieldptr].bitst);
+ resreg = resreg | shiftreg;
+ }
+ }
+ }
+ return resreg;
+}
+
+/*******************************************************
+* Generate the field arguments for constrained fields
+* for all sanity levels
+*******************************************************/
+
+struct inputparameters generate_args(int smccall, int sanity)
+{
+ if ((smccall > MAX_SMC_CALLS) || (smccall < 0)) {
+ printf("generate args SMC call is out of bounds\n");
+ panic();
+ }
+ if ((sanity > SANITY_LEVEL_3) || (sanity < 0)) {
+ printf("generate args sanity level is out of bounds\n");
+ panic();
+ }
+ struct inputparameters nparam;
+
+ nparam.x1 = 1;
+ if (sanity == SANITY_LEVEL_0) {
+ for (int i = 0; i < fuzzer_arg_array_range[smccall]; i++) {
+ switch (i) {
+ case 0: {
+ nparam.x1 = rand64bit();
+ break;
+ }
+ case 1: {
+ nparam.x2 = rand64bit();
+ break;
+ }
+ case 2: {
+ nparam.x3 = rand64bit();
+ break;
+ }
+ case 3: {
+ nparam.x4 = rand64bit();
+ break;
+ }
+ case 4: {
+ nparam.x5 = rand64bit();
+ break;
+ }
+ case 5: {
+ nparam.x6 = rand64bit();
+ break;
+ }
+ case 6: {
+ nparam.x7 = rand64bit();
+ break;
+ }
+ case 7: {
+ nparam.x8 = rand64bit();
+ break;
+ }
+ case 8: {
+ nparam.x9 = rand64bit();
+ break;
+ }
+ case 9: {
+ nparam.x10 = rand64bit();
+ break;
+ }
+ case 10: {
+ nparam.x11 = rand64bit();
+ break;
+ }
+ case 11: {
+ nparam.x12 = rand64bit();
+ break;
+ }
+ case 12: {
+ nparam.x13 = rand64bit();
+ break;
+ }
+ case 13: {
+ nparam.x14 = rand64bit();
+ break;
+ }
+ case 14: {
+ nparam.x15 = rand64bit();
+ break;
+ }
+ case 15: {
+ nparam.x16 = rand64bit();
+ break;
+ }
+ case 16: {
+ nparam.x17 = rand64bit();
+ break;
+ }
+ }
+ }
+ }
+ if (sanity == SANITY_LEVEL_1) {
+ int selreg = rand() % (fuzzer_arg_array_range[smccall] + 1);
+ for (int i = 0; i < fuzzer_arg_array_range[smccall]; i++) {
+ switch (i) {
+ case 0: {
+ if (selreg == 0) {
+ nparam.x1 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x1 = rand64bit();
+ }
+ break;
+ }
+ case 1: {
+ if (selreg == 1) {
+ nparam.x2 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x2 = rand64bit();
+ }
+ break;
+ }
+ case 2: {
+ if (selreg == 2) {
+ nparam.x3 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x3 = rand64bit();
+ }
+ break;
+ }
+ case 3: {
+ if (selreg == 3) {
+ nparam.x4 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x4 = rand64bit();
+ }
+ break;
+ }
+ case 4: {
+ if (selreg == 4) {
+ nparam.x5 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x5 = rand64bit();
+ }
+ break;
+ }
+ case 5: {
+ if (selreg == 5) {
+ nparam.x6 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x6 = rand64bit();
+ }
+ break;
+ }
+ case 6: {
+ if (selreg == 6) {
+ nparam.x7 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x7 = rand64bit();
+ }
+ break;
+ }
+ case 7: {
+ if (selreg == 7) {
+ nparam.x8 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x8 = rand64bit();
+ }
+ break;
+ }
+ case 8: {
+ if (selreg == 8) {
+ nparam.x9 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x9 = rand64bit();
+ }
+ break;
+ }
+ case 9: {
+ if (selreg == 9) {
+ nparam.x10 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x10 = rand64bit();
+ }
+ break;
+ }
+ case 10: {
+ if (selreg == 10) {
+ nparam.x11 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x11 = rand64bit();
+ }
+ break;
+ }
+ case 11: {
+ if (selreg == 11) {
+ nparam.x12 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x12 = rand64bit();
+ }
+ break;
+ }
+ case 12: {
+ if (selreg == 12) {
+ nparam.x13 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x13 = rand64bit();
+ }
+ break;
+ }
+ case 13: {
+ if (selreg == 13) {
+ nparam.x14 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x14 = rand64bit();
+ }
+ break;
+ }
+ case 14: {
+ if (selreg == 14) {
+ nparam.x15 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x15 = rand64bit();
+ }
+ break;
+ }
+ case 15: {
+ if (selreg == 15) {
+ nparam.x16 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x16 = rand64bit();
+ }
+ break;
+ }
+ case 16: {
+ if (selreg == 16) {
+ nparam.x17 = generate_field_uncon(smccall, i);
+ } else {
+ nparam.x17 = rand64bit();
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (sanity == SANITY_LEVEL_2) {
+ for (int i = 0; i < fuzzer_arg_array_range[smccall]; i++) {
+ switch (i) {
+ case 0: {
+ nparam.x1 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 1: {
+ nparam.x2 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 2: {
+ nparam.x3 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 3: {
+ nparam.x4 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 4: {
+ nparam.x5 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 5: {
+ nparam.x6 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 6: {
+ nparam.x7 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 7: {
+ nparam.x8 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 8: {
+ nparam.x9 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 9: {
+ nparam.x10 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 10: {
+ nparam.x11 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 11: {
+ nparam.x12 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 12: {
+ nparam.x13 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 13: {
+ nparam.x14 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 14: {
+ nparam.x15 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 15: {
+ nparam.x16 = generate_field_uncon(smccall, i);
+ break;
+ }
+ case 16: {
+ nparam.x17 = generate_field_uncon(smccall, i);
+ break;
+ }
+ }
+ }
+ }
+ if (sanity == SANITY_LEVEL_3) {
+ for (int i = 0; i < fuzzer_arg_array_range[smccall]; i++) {
+ switch (i) {
+ case 0: {
+ nparam.x1 = generate_field_con(smccall, i);
+ break;
+ }
+ case 1: {
+ nparam.x2 = generate_field_con(smccall, i);
+ break;
+ }
+ case 2: {
+ nparam.x3 = generate_field_con(smccall, i);
+ break;
+ }
+ case 3: {
+ nparam.x4 = generate_field_con(smccall, i);
+ break;
+ }
+ case 4: {
+ nparam.x5 = generate_field_con(smccall, i);
+ break;
+ }
+ case 5: {
+ nparam.x6 = generate_field_con(smccall, i);
+ break;
+ }
+ case 6: {
+ nparam.x7 = generate_field_con(smccall, i);
+ break;
+ }
+ case 7: {
+ nparam.x8 = generate_field_con(smccall, i);
+ break;
+ }
+ case 8: {
+ nparam.x9 = generate_field_con(smccall, i);
+ break;
+ }
+ case 9: {
+ nparam.x10 = generate_field_con(smccall, i);
+ break;
+ }
+ case 10: {
+ nparam.x11 = generate_field_con(smccall, i);
+ break;
+ }
+ case 11: {
+ nparam.x12 = generate_field_con(smccall, i);
+ break;
+ }
+ case 12: {
+ nparam.x13 = generate_field_con(smccall, i);
+ break;
+ }
+ case 13: {
+ nparam.x14 = generate_field_con(smccall, i);
+ break;
+ }
+ case 14: {
+ nparam.x15 = generate_field_con(smccall, i);
+ break;
+ }
+ case 15: {
+ nparam.x16 = generate_field_con(smccall, i);
+ break;
+ }
+ case 16: {
+ nparam.x17 = generate_field_con(smccall, i);
+ break;
+ }
+ }
+ }
+ }
+ #ifdef SMC_FUZZER_DEBUG
+ print_smccall(smccall, nparam);
+ #endif
+ return nparam;
+}
+
+/*******************************************************
+* Get generated value from fuzzer for a given field
+*******************************************************/
+
+uint64_t get_generated_value(int fieldnameptr, struct inputparameters inp)
+{
+ uint64_t xval = 0;
+ int argdef = fuzzer_fieldarg[fieldnameptr];
+ int fieldname = fuzzer_fieldfld[fieldnameptr];
+ int fieldptr = fuzzer_arg_array_lst[argdef].arg_span[0] + fieldname;
+
+ switch(fuzzer_arg_array[fieldptr].regnum) {
+ case 1: {
+ xval = shiftrht(inp.x1, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 2: {
+ xval = shiftrht(inp.x2, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 3: {
+ xval = shiftrht(inp.x3, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 4: {
+ xval = shiftrht(inp.x4, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 5: {
+ xval = shiftrht(inp.x5, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 6: {
+ xval = shiftrht(inp.x6, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 7: {
+ xval = shiftrht(inp.x7, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 8: {
+ xval = shiftrht(inp.x8, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 9: {
+ xval = shiftrht(inp.x9, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 10: {
+ xval = shiftrht(inp.x10, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 11: {
+ xval = shiftrht(inp.x11, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 12: {
+ xval = shiftrht(inp.x12, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 13: {
+ xval = shiftrht(inp.x13, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 14: {
+ xval = shiftrht(inp.x14, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 15: {
+ xval = shiftrht(inp.x15, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 16: {
+ xval = shiftrht(inp.x16, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ case 17: {
+ xval = shiftrht(inp.x17, fuzzer_arg_array[fieldptr].bitst) &
+ ((shiftlft(1, fuzzer_arg_array[fieldptr].bitw)) - 1);
+ return xval;
+ }
+ }
+ return xval;
+}
+
+/*******************************************************
+* Print the values from a generated SMC call from fuzzer
+*******************************************************/
+
+void print_smccall(int smccall, struct inputparameters inp)
+{
+ if ((smccall > MAX_SMC_CALLS) || (smccall < 0)) {
+ printf("generate args SMC call is out of bounds\n");
+ panic();
+ }
+ int argptr = fuzzer_arg_array_start[smccall];
+ int fieldptr = fuzzer_arg_array_lst[fuzzer_arg_array_start[smccall]].arg_span[0];
+
+ printf("%s\n", fuzzer_arg_array[fieldptr].smcname);
+ for (int i = 0; i < (fuzzer_arg_array_range[smccall]); i++) {
+ fieldptr = fuzzer_arg_array_lst[argptr + i].arg_span[0];
+ printf("argument: %s\n", fuzzer_arg_array[fieldptr].smcargname);
+ for (int j = fieldptr; j <= ((fuzzer_arg_array_lst[argptr + i].arg_span[1] -
+ fuzzer_arg_array_lst[argptr + i].arg_span[0]) + fieldptr); j++) {
+ printf("%s = %llx\n", fuzzer_arg_array[j].bnames,
+ get_generated_value(j, inp));
+ }
+ }
+ printf("\n\n");
+}
diff --git a/smc_fuzz/src/randsmcmod.c b/smc_fuzz/src/randsmcmod.c
index a86feb6..e1725f0 100644
--- a/smc_fuzz/src/randsmcmod.c
+++ b/smc_fuzz/src/randsmcmod.c
@@ -4,20 +4,22 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include "fifo3d.h"
+#include "nfifo.h"
+
#include <arch_helpers.h>
#include <debug.h>
#include <drivers/arm/private_timer.h>
#include <events.h>
-#include "fifo3d.h"
-#include "nfifo.h"
#include <libfdt.h>
-
#include <plat_topology.h>
#include <power_management.h>
#include <tftf_lib.h>
+
extern char _binary___dtb_start[];
-extern void runtestfunction(int funcid);
+extern void runtestfunction(int funcid, struct memmod *mmod);
+extern void init_input_arg_struct(void);
struct memmod tmod __aligned(65536) __section("smcfuzz");
static int cntndarray;
@@ -233,9 +235,9 @@
(fdt32_to_cpu(fhd.off_dt_strings) +
fdt32_to_cpu(pv.nameoff)), cset);
if (strcmp(cset, "bias") == 0) {
- rval = *((unsigned int *)dtb);
+ unsigned int bval = *((unsigned int *)dtb);
dtb += sizeof(unsigned int);
- push_3dfifo_bias(&f3d, fdt32_to_cpu(rval));
+ push_3dfifo_bias(&f3d, fdt32_to_cpu(bval));
bias_count++;
if (bintnode == 1U) {
fnode = 0U;
@@ -460,6 +462,7 @@
test_result_t smc_fuzzing_instance(uint32_t seed)
{
struct rand_smc_node *tlnode;
+
/*
* Initialize pseudo random number generator with supplied seed.
*/
@@ -494,7 +497,10 @@
int selent = tlnode->biasarray[nch];
if (tlnode->norcall[selent] == 0) {
- runtestfunction(tlnode->snameid[selent]);
+ #ifdef SMC_FUZZER_DEBUG
+ printf("the name of the SMC call is %s\n", tlnode->snames[selent]);
+ #endif
+ runtestfunction(tlnode->snameid[selent], mmod);
nd = 1;
} else {
tlnode = &tlnode->treenodes[selent];
diff --git a/smc_fuzz/src/runtestfunction_helpers.c b/smc_fuzz/src/runtestfunction_helpers.c
index c3b2cca..411949c 100644
--- a/smc_fuzz/src/runtestfunction_helpers.c
+++ b/smc_fuzz/src/runtestfunction_helpers.c
@@ -5,14 +5,24 @@
*/
#include <sdei_fuzz_helper.h>
+#include "smcmalloc.h"
#include <tsp_fuzz_helper.h>
+int cntid = 0;
+
+#include <vendor_fuzz_helper.h>
/*
* Invoke the SMC call based on the function name specified.
*/
-void runtestfunction(int funcid)
+void runtestfunction(int funcid, struct memmod *mmod)
{
- run_sdei_fuzz(funcid);
+ bool inrange = (cntid >= SMC_FUZZ_CALL_START) && (cntid < SMC_FUZZ_CALL_END);
+ inrange = inrange && (funcid != EXCLUDE_FUNCID);
+
+ run_sdei_fuzz(funcid, mmod, inrange, cntid);
run_tsp_fuzz(funcid);
+ run_ven_el3_fuzz(funcid, mmod);
+
+ cntid++;
}
diff --git a/smc_fuzz/src/sdei_fuzz_helper.c b/smc_fuzz/src/sdei_fuzz_helper.c
index 1d22335..5a1d866 100644
--- a/smc_fuzz/src/sdei_fuzz_helper.c
+++ b/smc_fuzz/src/sdei_fuzz_helper.c
@@ -4,19 +4,94 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <arg_struct_def.h>
+#include "constraint.h"
#include <fuzz_names.h>
#include <sdei_fuzz_helper.h>
+int stbev = 0;
+
+#define MIN_PPI_ID U(16)
+#define MAX_PPI_ID U(31)
+#define MIN_SPI_ID U(32)
+#define MAX_SPI_ID U(255)
+#define EV_COOKIE 0xDEADBEEF
+#define PPI_RANGE ((uint64_t[2]) {MIN_PPI_ID, MAX_PPI_ID})
+#define SPI_RANGE ((uint64_t[2]) {MIN_SPI_ID, MAX_SPI_ID})
+#define BIND_SLOTS_MASK 0xffffU
+#define FEATURES_SHARED_SLOTS_SHIFT 16U
+#define FEATURES_PRIVATE_SLOTS_SHIFT 0U
+
+extern sdei_handler_t sdei_entrypoint;
+extern sdei_handler_t sdei_entrypoint_resume;
+
+#define HANDLER_SVALUE ((uint64_t[1]) { (uint64_t)(uintptr_t)sdei_entrypoint_resume })
+#define PE_SVALUE ((uint64_t[1]) { read_mpidr_el1() })
+#define ZERO_EVENT_SVALUE ((uint64_t[1]) { 0 })
+#define EV_COOKIE_SVALUE ((uint64_t[1]) { 0xDEADBEEF })
+#define VENDOR_EVENTS_RANGE ((uint64_t[2]) { 0x40000000, 0x40FFFFFF })
+#define STD_EVENTS_RANGE ((uint64_t[2]) { 0x00000001, 0x00FFFFFF })
+#define ANY_ROUTING ((uint64_t[1]) { SDEI_REGF_RM_ANY })
+#define PE_ROUTING ((uint64_t[1]) { SDEI_REGF_RM_PE })
+#define ROUTING_MODES ((uint64_t[2]) { SDEI_REGF_RM_ANY, SDEI_REGF_RM_PE })
+#define OUT_OF_RESOURCE_ERR -10
+#define MAX_BIND_SLOTS (1 << 16)
+
+#define register_handler() setconstraint(FUZZER_CONSTRAINT_SVALUE, HANDLER_SVALUE, 1, \
+SDEI_EVENT_REGISTER_CALL_ARG2_ADDR, mmod, FUZZER_CONSTRAINT_ACCMODE)
+
+char *return_str(int64_t return_val)
+{
+ switch (return_val) {
+ case -1:
+ return "NOT_SUPPORTED";
+ case -2:
+ return "INVALID_PARAMETERS";
+ case -3:
+ return "DENIED";
+ case -5:
+ return "PENDING";
+ case -10:
+ return "OUT_OF_RESOURCE";
+ default:
+ return "UNKNOWN ERROR CODE";
+ }
+}
+
+void print_return(char *funcstr, int64_t ret)
+{
+ if (ret < 0) {
+ printf("%s failed: 0x%llx. %s\n", funcstr, ret, return_str(ret));
+ } else {
+ printf("%s successful return: %llx\n", funcstr, ret);
+ }
+}
+
+void set_event_constraints(int sdei_arg_name, struct memmod *mmod)
+{
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, ZERO_EVENT_SVALUE, 1, sdei_arg_name, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, STD_EVENTS_RANGE, 2, sdei_arg_name, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, VENDOR_EVENTS_RANGE, 2, sdei_arg_name, mmod, FUZZER_CONSTRAINT_ACCMODE);
+}
+
/*
* SDEI function that has no arguments
*/
-void tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr)
+int64_t tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr)
{
int64_t ret = (*sdei_func)();
if (ret < 0) {
tftf_testcase_printf("%s failed: 0x%llx\n", funcstr, ret);
}
+
+ printf("%s return: %llx\n", funcstr, ret);
+
+ return ret;
}
/*
@@ -24,37 +99,689 @@
*/
void tftf_test_sdei_singlearg(int64_t (*sdei_func)(uint64_t), char *funcstr)
{
- int64_t ret = (*sdei_func)(0);
+ struct sdei_intr_ctx intr_ctx;
+ int bev;
+
+ bev = sdei_interrupt_bind(tftf_get_timer_irq(), &intr_ctx);
+ int64_t ret = (*sdei_func)(bev);
if (ret < 0) {
tftf_testcase_printf("%s failed: 0x%llx\n", funcstr, ret);
}
}
+uint64_t *bound_shared_inums;
+uint64_t *bound_private_inums;
+uint64_t *bound_shared_evnums;
+uint64_t *bound_private_evnums;
+int64_t private_slots_count;
+int64_t shared_slots_count;
+static int64_t private_slots_len;
+static int64_t shared_slots_len;
+
+
+void bound_event_constraints(int fieldname, struct memmod *mmod)
+{
+ setconstraint(FUZZER_CONSTRAINT_VECTOR, bound_shared_evnums, shared_slots_len, fieldname, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_VECTOR, bound_private_evnums, private_slots_len, fieldname, mmod, FUZZER_CONSTRAINT_ACCMODE);
+}
+
+void release_shared_slots(struct memmod *mmod, int slots, bool release)
+{
+
+ if ((slots < 0) || (slots > shared_slots_len)) {
+ return;
+ }
+
+ struct inputparameters inp;
+ int64_t ret;
+ struct sdei_intr_ctx intr_ctx;
+
+ if (release) {
+ for (int k = 0; k < slots; k++) {
+ uint64_t release_enum[1] = {bound_shared_evnums[shared_slots_len - 1 - k]};
+
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, release_enum, 1, SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_UNREGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_unregister(inp.x1);
+ print_return("unregister", ret);
+
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, release_enum, 1, SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_INTERRUPT_RELEASE_CALL, SANITY_LEVEL_3);
+ ret = sdei_interrupt_release(inp.x1, &intr_ctx);
+ print_return("release", ret);
+ }
+ }
+
+ for (int i = shared_slots_len; i > 0; i--) {
+ bound_shared_inums[i] = bound_shared_inums[i-slots];
+ }
+ for (int i = 0; i < slots; i++) {
+ bound_shared_inums[i] = 0;
+ }
+
+ for (int i = shared_slots_len; i > 0; i--) {
+ bound_shared_evnums[i] = bound_shared_evnums[i-slots];
+ }
+ for (int i = 0; i < slots; i++) {
+ bound_shared_evnums[i] = 0;
+ }
+ shared_slots_count = (shared_slots_count + slots < shared_slots_len ? shared_slots_count + slots : shared_slots_len);
+}
+
+void release_private_slots(struct memmod *mmod, int slots, bool release)
+{
+ if ((slots < 0) || (slots > private_slots_len)) {
+ return;
+ }
+
+ struct inputparameters inp;
+ int64_t ret;
+ struct sdei_intr_ctx intr_ctx;
+
+ if (release) {
+ for (int k = 0; k < slots; k++) {
+ uint64_t release_enum[1] = {bound_private_evnums[private_slots_len-1-k]};
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, release_enum, 1, SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_UNREGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_unregister(inp.x1);
+ print_return("unregister", ret);
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, release_enum, 1, SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_INTERRUPT_RELEASE_CALL, SANITY_LEVEL_3);
+ ret = sdei_interrupt_release(inp.x1, &intr_ctx);
+ print_return("release", ret);
+ }
+ }
+
+ for (int i = private_slots_len; i > 0; i--) {
+ bound_private_inums[i] = bound_private_inums[i-slots];
+ }
+ for (int i = 0; i < slots; i++) {
+ bound_private_inums[i] = 0;
+ }
+
+ for (int i = private_slots_len; i > 0; i--) {
+ bound_private_evnums[i] = bound_private_evnums[i-slots];
+ }
+ for (int i = 0; i < slots; i++) {
+ bound_private_evnums[i] = 0;
+ }
+
+ private_slots_count = (private_slots_count + slots < private_slots_len ? private_slots_count + slots : private_slots_len);
+}
+
+void initalize_interrupt_slots(struct memmod *mmod)
+{
+ uint64_t bind_slots[1] = {0};
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, bind_slots, 1, SDEI_FEATURES_CALL_ARG1_FEAT, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ struct inputparameters inp = generate_args(SDEI_FEATURES_CALL, SMC_FUZZ_SANITY_LEVEL);
+ int64_t slots = sdei_features(inp.x1);
+
+ shared_slots_count = slots & 0xffffU;
+ private_slots_count = (slots >> 16U) & 0xfffU;
+ shared_slots_len = shared_slots_count;
+ private_slots_len = private_slots_count;
+ static uint64_t tmp[MAX_BIND_SLOTS];
+ static uint64_t tmp1[MAX_BIND_SLOTS];
+ static uint64_t tmp2[MAX_BIND_SLOTS];
+ static uint64_t tmp3[MAX_BIND_SLOTS];
+
+ bound_shared_inums = tmp;
+ bound_shared_evnums = tmp1;
+
+ bound_private_inums = tmp2;
+ bound_private_evnums = tmp3;
+ for (int i = 0; i < shared_slots_count; i++) {
+ bound_shared_inums[i] = 0;
+ bound_shared_evnums[i] = 0;
+ }
+ for (int i = 0; i < private_slots_count; i++) {
+ bound_private_inums[i] = 0;
+ bound_private_evnums[i] = 0;
+ }
+}
+
+void release_full_slots(struct inputparameters inp, struct memmod *mmod)
+{
+ if ((!shared_slots_count)) {
+ if (inp.x1 >= MIN_SPI_ID && inp.x1 <= MAX_SPI_ID) {
+ release_shared_slots(mmod, 1, true);
+ }
+ }
+
+ if ((!private_slots_count)) {
+ if (inp.x1 >= MIN_PPI_ID && inp.x1 <= MAX_PPI_ID) {
+ release_private_slots(mmod, 1, true);
+ }
+ }
+}
+
/*
* SDEI function called from fuzzer
*/
-void run_sdei_fuzz(int funcid)
+void run_sdei_fuzz(int funcid, struct memmod *mmod, bool inrange, int cntid)
{
- if (funcid == sdei_version_funcid) {
- long long ret = sdei_version();
+ #ifdef SMC_FUZZER_DEBUG
+ if (inrange) {
+ printf("%d\n", cntid);
+ }
+ #endif
- if (ret != MAKE_SDEI_VERSION(1, 0, 0)) {
- tftf_testcase_printf("Unexpected SDEI version: 0x%llx\n",
- ret);
+ if (cntid == 0 && CONSTRAIN_EVENTS) {
+ initalize_interrupt_slots(mmod);
+ }
+
+ #ifdef SMC_FUZZER_DEBUG
+ if (CONSTRAIN_EVENTS) {
+ printf("Bound priv inums: %llu, %llu, %llu\n", bound_private_inums[0], bound_private_inums[1], bound_private_inums[2]);
+ printf("Bound priv evnums: %llu, %llu, %llu\n", bound_private_evnums[0], bound_private_evnums[1], bound_private_evnums[2]);
+ printf("Bound shared inums: %llu, %llu, %llu\n", bound_shared_inums[0], bound_shared_inums[1], bound_shared_inums[2]);
+ printf("Bound shared evnums: %llu, %llu, %llu\n", bound_shared_evnums[0], bound_shared_evnums[1], bound_shared_evnums[2]);
+ printf("Shared slots left: %lld\n", shared_slots_count);
+ printf("Private slots left: %lld\n\n", private_slots_count);
+ }
+ #endif
+ if (funcid == sdei_version_funcid) {
+ long long ret;
+
+ if (inrange) {
+ ret = sdei_version();
+
+ if (ret != MAKE_SDEI_VERSION(1, 0, 0)) {
+ tftf_testcase_printf("Unexpected SDEI version: 0x%llx\n", ret);
+ }
}
} else if (funcid == sdei_pe_unmask_funcid) {
- tftf_test_sdei_noarg(sdei_pe_unmask, "sdei_pe_unmuask");
+ if (inrange) {
+ tftf_test_sdei_noarg(sdei_pe_unmask, "sdei_pe_unmask");
+ }
} else if (funcid == sdei_pe_mask_funcid) {
- tftf_test_sdei_noarg(sdei_pe_mask, "sdei_pe_mask");
+ if (inrange) {
+ tftf_test_sdei_noarg(sdei_pe_mask, "sdei_pe_mask");
+ }
+ } else if (funcid == sdei_interrupt_bind_funcid) {
+ struct sdei_intr_ctx intr_ctx;
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, SPI_RANGE, 2,
+ SDEI_INTERRUPT_BIND_CALL_ARG1_INUM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+
+ if (INTR_ASSERT) {
+ setconstraint(FUZZER_CONSTRAINT_RANGE, PPI_RANGE, 2,
+ SDEI_INTERRUPT_BIND_CALL_ARG1_INUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ }
+
+ struct inputparameters inp = generate_args(SDEI_INTERRUPT_BIND_CALL, SANITY_LEVEL_3);
+
+ release_full_slots(inp, mmod);
+
+ if (inrange) {
+ stbev = sdei_interrupt_bind(inp.x1, &intr_ctx);
+ if (stbev < 0) {
+ tftf_testcase_printf("sdei_interrupt_bind failed: 0x%llx %d\n", inp.x1, stbev);
+ } else if (CONSTRAIN_EVENTS) {
+ bool duplicate = false;
+
+ if (inp.x1 >= MIN_SPI_ID && inp.x1 <= MAX_SPI_ID) {
+
+ for (int i = 0; i < shared_slots_len; i++) {
+ if (bound_shared_inums[i] == inp.x1) {
+ duplicate = true;
+ }
+ }
+ if (!duplicate) {
+ shared_slots_count--;
+ bound_shared_inums[shared_slots_count] = inp.x1;
+ bound_shared_evnums[shared_slots_count] = stbev;
+ }
+
+ } else if (inp.x1 >= MIN_PPI_ID && inp.x1 <= MAX_PPI_ID) {
+ for (int i = 0; i < private_slots_len; i++) {
+ if (bound_private_inums[i] == inp.x1) {
+ duplicate = true;
+ }
+ }
+ if (!duplicate) {
+ private_slots_count--;
+ bound_private_inums[private_slots_count] = inp.x1;
+ bound_private_evnums[private_slots_count] = stbev;
+ }
+ }
+ }
+
+ #ifdef SMC_FUZZER_DEBUG
+ printf("stbev is %d and interrupt number is %lld\n", stbev, inp.x1);
+ #endif
+ }
} else if (funcid == sdei_event_status_funcid) {
- tftf_test_sdei_singlearg((int64_t (*)(uint64_t))sdei_event_status,
- "sdei_event_status");
+ struct inputparameters inp;
+
+ if (CONSTRAIN_EVENTS) {
+ bound_event_constraints(SDEI_EVENT_STATUS_CALL_ARG1_BEV, mmod);
+ set_event_constraints(SDEI_EVENT_STATUS_CALL_ARG1_BEV, mmod);
+ }
+ inp = generate_args(SDEI_EVENT_STATUS_CALL, SMC_FUZZ_SANITY_LEVEL);
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_status(inp.x1);
+ if (ret < 0) {
+
+ tftf_testcase_printf("sdei_event_status failed: 0x%llx %d\n", ret, stbev);
+ } else {
+
+ }
+ }
+
} else if (funcid == sdei_event_signal_funcid) {
- tftf_test_sdei_singlearg(sdei_event_signal, "sdei_event_signal");
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1,
+ SDEI_EVENT_SIGNAL_CALL_ARG2_PE, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ struct inputparameters inp = generate_args(SDEI_EVENT_SIGNAL_CALL, SMC_FUZZ_SANITY_LEVEL);
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_signal(inp.x2);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_signal failed: %lld\n", ret);
+ }
+ }
} else if (funcid == sdei_private_reset_funcid) {
- tftf_test_sdei_noarg(sdei_private_reset, "sdei_private_reset");
+ if (inrange) {
+ tftf_test_sdei_noarg(sdei_private_reset, "sdei_private_reset");
+ }
} else if (funcid == sdei_shared_reset_funcid) {
- tftf_test_sdei_noarg(sdei_shared_reset, "sdei_shared_reset");
+ int64_t ret = -1;
+
+ if (inrange) {
+ ret = tftf_test_sdei_noarg(sdei_shared_reset, "sdei_shared_reset");
+ }
+ if (ret == 0) {
+ release_shared_slots(mmod, private_slots_len, false);
+ release_private_slots(mmod, shared_slots_len, false);
+ }
+
+ } else if (funcid == sdei_event_register_funcid) {
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_REGISTER_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_REGISTER_CALL_ARG1_ENUM, mmod);
+ }
+
+ register_handler();
+
+ uint64_t routing_modes[2] = {SDEI_REGF_RM_ANY, SDEI_REGF_RM_PE};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, routing_modes, 2, SDEI_EVENT_REGISTER_CALL_ARG4_ROUTING, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, EV_COOKIE_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG3_ARG, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG5_AFF, mmod, FUZZER_CONSTRAINT_ACCMODE);
+
+ struct inputparameters inp = generate_args(SDEI_EVENT_REGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_register(inp.x1, (int (*)(int, uint64_t))(uintptr_t)inp.x2, inp.x3, inp.x4, inp.x5);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_register failed: 0x%llx\n", ret);
+ }
+ }
+
+
+ } else if (funcid == sdei_event_enable_funcid) {
+ struct inputparameters inp;
+
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_ENABLE_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_ENABLE_CALL_ARG1_ENUM, mmod);
+ }
+
+ inp = generate_args(SDEI_EVENT_ENABLE_CALL, SMC_FUZZ_SANITY_LEVEL);
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_enable(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_enable failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_event_disable_funcid) {
+ struct inputparameters inp;
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_DISABLE_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_DISABLE_CALL_ARG1_ENUM, mmod);
+ }
+
+ inp = generate_args(SDEI_EVENT_DISABLE_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_disable(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_disable failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_features_funcid) {
+ uint64_t feature_values[2] = {0, 1};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, feature_values, 2, SDEI_FEATURES_CALL_ARG1_FEAT, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ struct inputparameters inp = generate_args(SDEI_FEATURES_CALL, SANITY_LEVEL_3);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_features(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_features failed: 0x%llx\n", ret);
+ } else if ((ret >> 32) == 0) {
+ #ifdef SMC_FUZZER_DEBUG
+ printf("SUCCESS: sdei_features expected [63:32]\n");
+ printf("private event slots: %llx\n", (ret & 0xffffU));
+ printf("shared event slots: %llx\n", ((ret >> 16U) & 0xfffU));
+ #endif
+ }
+ }
+ } else if (funcid == sdei_event_unregister_funcid) {
+ struct inputparameters inp;
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod);
+ }
+
+ inp = generate_args(SDEI_EVENT_UNREGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_unregister(inp.x1);
+
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_unregister failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_event_context_funcid) {
+
+ uint64_t register_range[2] = {0, 17};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, register_range, 2, SDEI_EVENT_CONTEXT_CALL_ARG1_PARAM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ struct inputparameters inp = generate_args(SDEI_EVENT_CONTEXT_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_context(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_context failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_event_complete_funcid) {
+
+ uint64_t status_codes[2] = {0, 1};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, status_codes, 2, SDEI_EVENT_COMPLETE_CALL_ARG1_STAT, mmod, FUZZER_CONSTRAINT_ACCMODE);
+
+ struct inputparameters inp = generate_args(SDEI_EVENT_COMPLETE_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_complete(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_complete failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_event_complete_and_resume_funcid) {
+ struct inputparameters inp = generate_args(SDEI_EVENT_COMPLETE_AND_RESUME_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_complete_and_resume(inp.x1);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_complete_and_resume failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_event_get_info_funcid) {
+ struct inputparameters inp;
+ uint64_t info_values[2] = {0, 4};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, info_values, 2, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_ACCMODE);
+
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_GET_INFO_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_GET_INFO_CALL_ARG1_ENUM, mmod);
+ }
+
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_get_info failed: 0x%llx\n", ret);
+ }
+ }
+ } else if (funcid == sdei_event_routing_set_funcid) {
+ uint64_t routing_modes[2] = {SDEI_REGF_RM_ANY, SDEI_REGF_RM_PE};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, routing_modes, 2, SDEI_EVENT_ROUTING_SET_CALL_ARG2_ROUTING, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1, SDEI_EVENT_ROUTING_SET_CALL_ARG3_AFF, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ struct inputparameters inp;
+
+ if (CONSTRAIN_EVENTS) {
+ set_event_constraints(SDEI_EVENT_ROUTING_SET_CALL_ARG1_ENUM, mmod);
+ bound_event_constraints(SDEI_EVENT_ROUTING_SET_CALL_ARG1_ENUM, mmod);
+ }
+
+ inp = generate_args(SDEI_EVENT_ROUTING_SET_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_event_routing_set(inp.x1, inp.x2);
+ if (ret < 0) {
+ tftf_testcase_printf("sdei_event_routing_set failed: 0x%llx\n", ret);
+ }
+ }
+
+ } else if (funcid == sdei_interrupt_release_funcid) {
+ struct sdei_intr_ctx intr_ctx;
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, PPI_RANGE, 2,
+ SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_RANGE, SPI_RANGE, 2,
+ SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+
+ struct inputparameters inp = generate_args(SDEI_INTERRUPT_RELEASE_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ int64_t ret;
+
+ if (inrange) {
+ ret = sdei_interrupt_release(inp.x1, &intr_ctx);
+ if (ret < 0) {
+
+ tftf_testcase_printf("sdei_interrupt_release failed: 0x%llx\n", ret);
+ } else {
+ if (inp.x1 >= MIN_SPI_ID && inp.x1 <= MAX_SPI_ID) {
+ release_shared_slots(mmod, 1, false);
+ } else if (inp.x1 >= MIN_PPI_ID && inp.x1 <= MAX_PPI_ID) {
+ release_private_slots(mmod, 1, false);
+ }
+ }
+ }
+
+ } else if (funcid == sdei_routing_set_coverage_funcid) {
+ int64_t ret;
+ struct inputparameters inp;
+
+ uint64_t bind_slots[1] = {0};
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, bind_slots, 1, SDEI_FEATURES_CALL_ARG1_FEAT, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_FEATURES_CALL, SMC_FUZZ_SANITY_LEVEL);
+ int64_t slots = sdei_features(inp.x1);
+
+ print_return("features", slots);
+
+ // bind shared interrupt to create shared event
+ struct sdei_intr_ctx intr_ctx;
+ uint64_t inum_range[2] = { MIN_SPI_ID, U(255) };
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, inum_range, 2, SDEI_INTERRUPT_BIND_CALL_ARG1_INUM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_INTERRUPT_BIND_CALL, SANITY_LEVEL_3);
+
+ release_full_slots(inp, mmod);
+
+
+ ret = sdei_interrupt_bind(inp.x1, &intr_ctx);
+ if (ret < 0) {
+ return;
+ }
+
+ // register shared event
+ uint64_t evnum[1] = {ret};
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_REGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, HANDLER_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG2_ADDR, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG5_AFF, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, ANY_ROUTING, 1, SDEI_EVENT_REGISTER_CALL_ARG4_ROUTING, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_EVENT_REGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_register(inp.x1, (int (*)(int, uint64_t))(uintptr_t)inp.x2, inp.x3, inp.x4, inp.x5);
+ print_return("register", ret);
+
+ uint64_t signal_info[1] = {0};
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_GET_INFO_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, signal_info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get_info", ret);
+
+
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_ROUTING_SET_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, ANY_ROUTING, 1, SDEI_EVENT_ROUTING_SET_CALL_ARG2_ROUTING, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1, SDEI_EVENT_ROUTING_SET_CALL_ARG3_AFF, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_EVENT_ROUTING_SET_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_routing_set(inp.x1, inp.x2);
+ print_return("routing_set", ret);
+
+ // unregister
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_UNREGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_unregister(inp.x1);
+ print_return("unregister", ret);
+
+ // release
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_INTERRUPT_RELEASE_CALL, SMC_FUZZ_SANITY_LEVEL);
+ sdei_interrupt_release(inp.x1, &intr_ctx);
+ print_return("release", ret);
+
+ if (inp.x1 >= MIN_SPI_ID && inp.x1 <= MAX_SPI_ID) {
+ release_shared_slots(mmod, 1, false);
+ } else if (inp.x1 >= MIN_PPI_ID && inp.x1 <= MAX_PPI_ID) {
+ release_private_slots(mmod, 1, false);
+ }
+
+ } else if (funcid == sdei_event_get_info_coverage_funcid) {
+ int64_t ret;
+ struct inputparameters inp;
+ uint64_t info[1];
+
+ // bind shared interrupt to create shared event
+ struct sdei_intr_ctx intr_ctx;
+ uint64_t inum_range[2] = { MIN_SPI_ID, U(255)};
+
+ setconstraint(FUZZER_CONSTRAINT_RANGE, inum_range, 2, SDEI_INTERRUPT_BIND_CALL_ARG1_INUM, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_INTERRUPT_BIND_CALL, SANITY_LEVEL_3);
+
+ release_full_slots(inp, mmod);
+
+ ret = sdei_interrupt_bind(inp.x1, &intr_ctx);
+
+ if (ret < 0) {
+ return;
+ }
+
+ uint64_t evnum[1] = {ret};
+
+ // event type
+ info[0] = 0;
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_GET_INFO_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get info", ret);
+
+ // event signalable
+ info[0] = 1;
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get info", ret);
+
+ // event priority
+ printf("priority\n");
+ info[0] = 2;
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get info", ret);
+
+ // register event
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_REGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, HANDLER_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG2_ADDR, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_SVALUE, 1, SDEI_EVENT_REGISTER_CALL_ARG5_AFF, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, PE_ROUTING, 1, SDEI_EVENT_REGISTER_CALL_ARG4_ROUTING, mmod, FUZZER_CONSTRAINT_ACCMODE);
+ inp = generate_args(SDEI_EVENT_REGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_register(inp.x1, (int (*)(int, uint64_t))(uintptr_t)inp.x2, inp.x3, inp.x4, inp.x5);
+ print_return("register", ret);
+
+ // event routing mode
+ info[0] = 3;
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get info", ret);
+
+ // event affinity
+ info[0] = 4;
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, info, 1, SDEI_EVENT_GET_INFO_CALL_ARG2_INFO, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_GET_INFO_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_get_info(inp.x1, inp.x2);
+ print_return("get info", ret);
+
+ // unregister
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_EVENT_UNREGISTER_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_EVENT_UNREGISTER_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_event_unregister(inp.x1);
+ print_return("unregister", ret);
+
+ // release
+ setconstraint(FUZZER_CONSTRAINT_SVALUE, evnum, 1, SDEI_INTERRUPT_RELEASE_CALL_ARG1_ENUM, mmod, FUZZER_CONSTRAINT_EXCMODE);
+ inp = generate_args(SDEI_INTERRUPT_RELEASE_CALL, SMC_FUZZ_SANITY_LEVEL);
+ ret = sdei_interrupt_release(inp.x1, &intr_ctx);
+ print_return("release", ret);
+
+ if (inp.x1 >= MIN_SPI_ID && inp.x1 <= MAX_SPI_ID) {
+ release_shared_slots(mmod, 1, false);
+ } else if (inp.x1 >= MIN_PPI_ID && inp.x1 <= MAX_PPI_ID) {
+ release_private_slots(mmod, 1, false);
+ }
}
}
diff --git a/smc_fuzz/src/vendor_fuzz_helper.c b/smc_fuzz/src/vendor_fuzz_helper.c
new file mode 100644
index 0000000..2de10b4
--- /dev/null
+++ b/smc_fuzz/src/vendor_fuzz_helper.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arg_struct_def.h>
+#include "constraint.h"
+#include <fuzz_names.h>
+#include <vendor_fuzz_helper.h>
+
+#include <lib/tftf_lib.h>
+#include <runtime_services/ven_el3_svc.h>
+#include <smccc.h>
+#include <uuid_utils.h>
+
+/*
+ * Vendor-Specific EL3 UUID as returned by the implementation in the Trusted
+ * Firmware.
+ */
+static const uuid_t armtf_ven_el3_svc_uuid = {
+ {0xb6, 0x01, 0x1d, 0xca},
+ {0x57, 0xc4},
+ {0x40, 0x7e},
+ 0x83, 0xf0,
+ {0xa7, 0xed, 0xda, 0xf0, 0xdf, 0x6c}
+};
+
+void inputparameters_to_ven_el3_args(struct inputparameters inp, smc_args *args)
+{
+ args->arg1 = inp.x1;
+ args->arg2 = inp.x2;
+ args->arg3 = inp.x3;
+ args->arg4 = inp.x4;
+ args->arg5 = inp.x5;
+ args->arg6 = inp.x6;
+ args->arg7 = inp.x7;
+}
+
+void run_ven_el3_fuzz(int funcid, struct memmod *mmod)
+{
+ if (funcid == ven_el3_svc_uuid_funcid) {
+
+ smc_args ven_el3_svc_args;
+ smc_ret_values ret;
+ uuid_t ven_el3_svc_uuid;
+ char uuid_str[UUID_STR_SIZE];
+
+ /* Standard Service Call UID */
+ ven_el3_svc_args.fid = VEN_EL3_SVC_UID;
+ struct inputparameters inp = generate_args(VEN_EL3_SVC_UUID_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ inputparameters_to_ven_el3_args(inp, &ven_el3_svc_args);
+
+ ret = tftf_smc(&ven_el3_svc_args);
+
+ make_uuid_from_4words(&ven_el3_svc_uuid,
+ ret.ret0, ret.ret1, ret.ret2, ret.ret3);
+
+ if (!uuid_equal(&ven_el3_svc_uuid, &armtf_ven_el3_svc_uuid)) {
+ tftf_testcase_printf("Wrong UUID: expected %s,\n",
+ uuid_to_str(&armtf_ven_el3_svc_uuid, uuid_str));
+ tftf_testcase_printf(" got %s\n",
+ uuid_to_str(&ven_el3_svc_uuid, uuid_str));
+ } else {
+ #ifdef SMC_FUZZER_DEBUG
+ printf("Correct UUID: got %s,\n",
+ uuid_to_str(&ven_el3_svc_uuid, uuid_str));
+ #endif
+ }
+ } else if (funcid == ven_el3_svc_count_funcid) {
+ smc_args ven_el3_svc_args;
+ smc_ret_values ret;
+
+ ven_el3_svc_args.fid = VEN_EL3_SVC_UID + 1;
+ struct inputparameters inp = generate_args(VEN_EL3_SVC_COUNT_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ inputparameters_to_ven_el3_args(inp, &ven_el3_svc_args);
+
+ ret = tftf_smc(&ven_el3_svc_args);
+
+ if (ret.ret0 != SMC_UNKNOWN) {
+ tftf_testcase_printf("Querying Vendor-Specific el3 service call count"
+ " which is reserved failed\n");
+ } else {
+ #ifdef SMC_FUZZER_DEBUG
+ printf("Querying Vendor-Specific el3 service call count"
+ " got %ld\n", ret.ret0);
+ #endif
+ }
+ } else if (funcid == ven_el3_svc_version_funcid) {
+ smc_args ven_el3_svc_args;
+ smc_ret_values ret;
+
+ ven_el3_svc_args.fid = VEN_EL3_SVC_VERSION;
+ struct inputparameters inp = generate_args(VEN_EL3_SVC_UUID_CALL, SMC_FUZZ_SANITY_LEVEL);
+
+ inputparameters_to_ven_el3_args(inp, &ven_el3_svc_args);
+
+ ret = tftf_smc(&ven_el3_svc_args);
+
+ if ((ret.ret0 != VEN_EL3_SVC_VERSION_MAJOR) ||
+ (ret.ret1 != VEN_EL3_SVC_VERSION_MINOR)) {
+ tftf_testcase_printf(
+ "Vendor Specific El3 service reported wrong version: expected {%u.%u}, got {%llu.%llu}\n",
+ VEN_EL3_SVC_VERSION_MAJOR, VEN_EL3_SVC_VERSION_MINOR,
+ (unsigned long long)ret.ret0,
+ (unsigned long long)ret.ret1);
+ }
+ }
+}
diff --git a/smc_fuzz/vendor_smc_calls.txt b/smc_fuzz/vendor_smc_calls.txt
new file mode 100644
index 0000000..a5251ac
--- /dev/null
+++ b/smc_fuzz/vendor_smc_calls.txt
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+smc: VEN_EL3_SVC_UUID_CALL
+ arg1=0
+smc: VEN_EL3_SVC_COUNT_CALL
+ arg1=0
+smc: VEN_EL3_SVC_VERSION_CALL
+ arg1=0
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index b608d7b..c15ee4e 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -61,8 +61,9 @@
ffa_ret = ffa_msg_wait();
for (;;) {
- VERBOSE("Woke up with func id: %s\n",
- ffa_func_name(ffa_func_id(ffa_ret)));
+ VERBOSE("Woke up with func:%s id: %x\n",
+ ffa_func_name(ffa_func_id(ffa_ret)),
+ ffa_func_id(ffa_ret));
if (ffa_func_id(ffa_ret) == FFA_ERROR) {
ERROR("Error: %s\n",
@@ -74,7 +75,7 @@
ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64 &&
ffa_func_id(ffa_ret) != FFA_INTERRUPT &&
ffa_func_id(ffa_ret) != FFA_RUN) {
- ERROR("%s(%u) unknown func id %s\n", __func__, vm_id,
+ ERROR("%s(%x) unknown func id %s\n", __func__, vm_id,
ffa_func_name(ffa_func_id(ffa_ret)));
break;
}
@@ -87,10 +88,15 @@
* informational as we're running with virtual
* interrupts unmasked and the interrupt is processed
* by the interrupt handler.
- *
- * Received FFA_RUN in waiting state, the endpoint
- * simply returns by FFA_MSG_WAIT.
*/
+ if (ffa_func_id(ffa_ret) == FFA_RUN) {
+ /*
+ * Received FFA_RUN in waiting state, the
+ * endpoint simply returns by FFA_MSG_WAIT.
+ */
+ VERBOSE("Nothing to do. Exit to NWd\n");
+ }
+
ffa_ret = ffa_msg_wait();
continue;
}
diff --git a/tftf/framework/timer/timer_framework.c b/tftf/framework/timer/timer_framework.c
index 49fd07f..46fe987 100644
--- a/tftf/framework/timer/timer_framework.c
+++ b/tftf/framework/timer/timer_framework.c
@@ -96,6 +96,14 @@
return 0;
}
+void tftf_initialise_timer_secondary_core(void)
+{
+ if (!IS_SPI(TIMER_IRQ)) {
+ arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
+ arm_gic_intr_enable(TIMER_IRQ);
+ }
+}
+
/*
* It returns the core number of next timer request to be serviced or
* -1 if there is no request from any core. The next service request
@@ -179,7 +187,9 @@
if ((!get_current_prog_time()) || (interrupt_req_time[core_pos] <
(get_current_prog_time() - TIMER_STEP_VALUE))) {
- arm_gic_set_intr_target(TIMER_IRQ, core_pos);
+ if (IS_SPI(TIMER_IRQ)) {
+ arm_gic_set_intr_target(TIMER_IRQ, core_pos);
+ }
rc = PROGRAM_TIMER(time_out_ms);
/* We don't expect timer programming to fail */
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_4.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_4.c
new file mode 100644
index 0000000..98872a1
--- /dev/null
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_4.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <arm_arch_svc.h>
+#include <debug.h>
+#include <plat_topology.h>
+#include <power_management.h>
+#include <psci.h>
+#include <smccc.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+#ifdef __aarch64__
+#define CORTEX_X2_MIDR 0x410FD480
+#define CORTEX_X3_MIDR 0x410FD4E0
+#define CORTEX_X4_MIDR 0x410FD821
+#define CORTEX_X925_MIDR 0x410FD850
+#define NEOVERSE_V2_MIDR 0x410FD4F0
+#define NEOVERSE_V3_MIDR 0x410FD840
+
+static int cortex_x2_test(void);
+static int cortex_x3_test(void);
+static int cortex_x4_test(void);
+static int cortex_x925_test(void);
+static int neoverse_v2_test(void);
+static int neoverse_v3_test(void);
+
+struct ent {
+ unsigned int midr;
+ int (*smc_ret)(void);
+};
+
+struct ent negative_entries[] = {
+ { .midr = CORTEX_X2_MIDR, .smc_ret = cortex_x2_test }
+};
+
+struct ent positive_entries[] = {
+ { .midr = CORTEX_X3_MIDR, .smc_ret = cortex_x3_test },
+ { .midr = CORTEX_X4_MIDR, .smc_ret = cortex_x4_test },
+ { .midr = CORTEX_X925_MIDR, .smc_ret = cortex_x925_test },
+ { .midr = NEOVERSE_V2_MIDR, .smc_ret = neoverse_v2_test},
+ { .midr = NEOVERSE_V3_MIDR, .smc_ret = neoverse_v3_test},
+};
+
+static int cortex_x2_test(void)
+{
+ return -1;
+}
+static int cortex_x3_test(void)
+{
+ return 0;
+}
+
+static int cortex_x4_test(void)
+{
+ return 0;
+}
+
+static int cortex_x925_test(void)
+{
+ return 0;
+}
+
+static int neoverse_v2_test(void)
+{
+ return 0;
+}
+
+static int neoverse_v3_test(void)
+{
+ return 0;
+}
+
+static test_result_t test_smccc_entrypoint(void)
+{
+ smc_args args;
+ smc_ret_values ret;
+ int32_t expected_ver;
+ unsigned int my_midr, midr_mask;
+ size_t i;
+
+ /* Check if SMCCC version is at least v1.1 */
+ expected_ver = MAKE_SMCCC_VERSION(1, 1);
+ memset(&args, 0, sizeof(args));
+ args.fid = SMCCC_VERSION;
+ ret = tftf_smc(&args);
+ if ((int32_t)ret.ret0 < expected_ver) {
+ tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
+ (int)ret.ret0);
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* Check if SMCCC_ARCH_WORKAROUND_4 is required or not */
+ memset(&args, 0, sizeof(args));
+ args.fid = SMCCC_ARCH_FEATURES;
+ args.arg1 = SMCCC_ARCH_WORKAROUND_4;
+ ret = tftf_smc(&args);
+
+ /*
+ * Negetive test. Checks if select non-affected cores
+ * return -1 (Not supported)
+ */
+ my_midr = (unsigned int)read_midr_el1();
+ midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ for (i = 0; i < ARRAY_SIZE(negative_entries); i++) {
+ struct ent *entp = &negative_entries[i];
+ if ((my_midr & midr_mask) == (entp->midr & midr_mask)) {
+ if (entp->smc_ret() != -1) {
+ return TEST_RESULT_FAIL;
+ }
+ break;
+ }
+ }
+
+ if ((int)ret.ret0 == -1) {
+ tftf_testcase_printf("SMCCC_ARCH_WORKAROUND_4 is not implemented\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* Check if the SMC return value matches our expectations */
+ for (i = 0; i < ARRAY_SIZE(positive_entries); i++) {
+ struct ent *entp = &positive_entries[i];
+ if ((my_midr & midr_mask) == (entp->midr & midr_mask)) {
+ if (entp->smc_ret() != 0) {
+ return TEST_RESULT_FAIL;
+ }
+ break;
+ }
+ }
+
+ if ((i == ARRAY_SIZE(positive_entries)) && ((int)ret.ret0) == 0) {
+ tftf_testcase_printf("TFTF workaround table out of sync with TF-A\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Invoke the workaround to make sure nothing nasty happens */
+ memset(&args, 0, sizeof(args));
+ args.fid = SMCCC_ARCH_WORKAROUND_4;
+ tftf_smc(&args);
+ return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_smccc_arch_workaround_4(void)
+{
+ u_register_t lead_mpid, target_mpid;
+ int cpu_node, ret;
+
+ lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+ /* Power on all the non-lead cores. */
+ for_each_cpu(cpu_node) {
+ target_mpid = tftf_get_mpidr_from_node(cpu_node);
+ if (lead_mpid == target_mpid) {
+ continue;
+ }
+ ret = tftf_cpu_on(target_mpid,
+ (uintptr_t)test_smccc_entrypoint, 0);
+ if (ret != PSCI_E_SUCCESS) {
+ ERROR("CPU ON failed for 0x%llx\n",
+ (unsigned long long)target_mpid);
+ return TEST_RESULT_FAIL;
+ }
+ /*
+ * Wait for test_smccc_entrypoint to return
+ * and the CPU to power down
+ */
+ while (tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL0) !=
+ PSCI_STATE_OFF) {
+ continue;
+ }
+ }
+
+ return test_smccc_entrypoint();
+}
+#else
+test_result_t test_smccc_arch_workaround_4(void)
+{
+ INFO("%s skipped on AArch32\n", __func__);
+ return TEST_RESULT_SKIPPED;
+}
+#endif
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c b/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c
index ceca36d..16e87e9 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c
@@ -15,8 +15,6 @@
#include <host_realm_pmu.h>
#include <platform.h>
-#define MAX_COUNTERS 31
-
/* PMCCFILTR_EL0 mask */
#define PMCCFILTR_EL0_MASK ( \
PMCCFILTR_EL0_P_BIT | \
@@ -82,32 +80,10 @@
} \
}
-struct pmu_registers {
- unsigned long pmcr_el0;
- unsigned long pmcntenset_el0;
- unsigned long pmovsset_el0;
- unsigned long pmintenset_el1;
- unsigned long pmccntr_el0;
- unsigned long pmccfiltr_el0;
- unsigned long pmuserenr_el0;
-
- unsigned long pmevcntr_el0[MAX_COUNTERS];
- unsigned long pmevtyper_el0[MAX_COUNTERS];
-
- unsigned long pmselr_el0;
- unsigned long pmxevcntr_el0;
- unsigned long pmxevtyper_el0;
-
-} __aligned(CACHE_WRITEBACK_GRANULE);
-
-static struct pmu_registers pmu_state[PLATFORM_CORE_COUNT];
-
-void host_set_pmu_state(void)
+void host_set_pmu_state(struct pmu_registers *pmu_ptr)
{
- unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
- struct pmu_registers *pmu_ptr = &pmu_state[core_pos];
- unsigned int num_cnts = GET_PMU_CNT;
unsigned long val;
+ unsigned int num_cnts = GET_PMU_CNT;
val = read_pmcr_el0() | PMCR_EL0_DP_BIT;
pmu_ptr->pmcr_el0 = val;
@@ -181,12 +157,13 @@
pmu_ptr->pmxevtyper_el0 = read_pmxevtyper_el0();
}
-bool host_check_pmu_state(void)
+bool host_check_pmu_state(struct pmu_registers *pmu_ptr)
{
- unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
- struct pmu_registers *pmu_ptr = &pmu_state[core_pos];
- unsigned int num_cnts = GET_PMU_CNT;
unsigned long val, read_val;
+ unsigned int num_cnts = GET_PMU_CNT;
+
+ INFO("Check PMU core_pos=%u num_cnts=%u\n",
+ platform_get_core_pos(read_mpidr_el1()), num_cnts);
CHECK_PMREG(pmcr_el0);
CHECK_PMREG(pmcntenset_el0);
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
index 9c7ceba..c1edd79 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
@@ -34,21 +34,25 @@
RMI_EXIT(PSCI),
RMI_EXIT(RIPAS_CHANGE),
RMI_EXIT(HOST_CALL),
- RMI_EXIT(SERROR)
+ RMI_EXIT(SERROR),
+ RMI_EXIT(IO),
+ RMI_EXIT(RTT_REQUEST),
+ RMI_EXIT(S2AP_CHANGE),
+ RMI_EXIT(VDEV_REQUEST)
};
/*
* The function handler to print the Realm logged buffer,
* executed by the secondary core
*/
-void realm_print_handler(struct realm *realm_ptr, unsigned int rec_num)
+void realm_print_handler(struct realm *realm_ptr, unsigned int plane_num, unsigned int rec_num)
{
size_t str_len = 0UL;
host_shared_data_t *host_shared_data;
char *log_buffer;
assert(realm_ptr != NULL);
- host_shared_data = host_get_shared_structure(realm_ptr, rec_num);
+ host_shared_data = host_get_shared_structure(realm_ptr, plane_num, rec_num);
log_buffer = (char *)host_shared_data->log_buffer;
str_len = strlen((const char *)log_buffer);
@@ -59,26 +63,12 @@
if (str_len != 0UL) {
/* Avoid memory overflow */
log_buffer[MAX_BUF_SIZE - 1] = 0U;
- mp_printf("[VMID %u][Rec %u]: %s", realm_ptr->vmid, rec_num, log_buffer);
+ mp_printf("[VMID %u][Rec %u]: %s", plane_num == 0U ? realm_ptr->vmid :
+ realm_ptr->aux_vmid[plane_num - 1U], rec_num, log_buffer);
(void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
}
}
-/*
- * 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.
- */
-static void host_init_realm_print_buffer(struct realm *realm_ptr)
-{
- host_shared_data_t *host_shared_data;
-
- for (unsigned int i = 0U; i < realm_ptr->rec_count; i++) {
- host_shared_data = host_get_shared_structure(realm_ptr, i);
- (void)memset((char *)host_shared_data, 0, sizeof(host_shared_data_t));
- }
-}
-
static bool host_enter_realm(struct realm *realm_ptr,
u_register_t *exit_reason,
unsigned int *host_call_result,
@@ -125,7 +115,6 @@
memset((void *)ns_shared_mem_adr, 0, (size_t)NS_REALM_SHARED_MEM_SIZE);
realm_ptr->host_shared_data = ns_shared_mem_adr;
realm_ptr->shared_mem_created = true;
- host_init_realm_print_buffer(realm_ptr);
return true;
}
@@ -135,7 +124,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
int8_t value;
@@ -169,6 +159,21 @@
EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag));
}
+ realm_ptr->rtt_tree_single = false;
+ if (num_aux_planes > 0U) {
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_PLANE_RTT, feature_flag) >=
+ RMI_PLANE_RTT_SINGLE) {
+ ERROR("S2POE not suported on TFTF\n");
+ return false;
+ }
+
+ /*
+ * @TODO: once S2POE is supported, this should be a parameter
+ * so it can be tested with and without support for auxiliary
+ * tables.
+ */
+ }
+
/* Disable PMU if not required */
if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
@@ -246,6 +251,12 @@
realm_ptr->start_level = sl;
+ if (num_aux_planes > MAX_AUX_PLANE_COUNT) {
+ ERROR("Invalid aux plane count\n");
+ return false;
+ }
+ realm_ptr->num_aux_planes = num_aux_planes;
+
/* Create Realm */
if (host_realm_create(realm_ptr) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_create");
@@ -283,7 +294,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
bool ret;
@@ -292,7 +304,8 @@
feature_flag,
sl,
rec_flag,
- rec_count);
+ rec_count,
+ num_aux_planes);
if (!ret) {
goto destroy_realm;
} else {
@@ -323,7 +336,8 @@
u_register_t feature_flag,
long sl,
const u_register_t *rec_flag,
- unsigned int rec_count)
+ unsigned int rec_count,
+ unsigned int num_aux_planes)
{
bool ret;
@@ -333,7 +347,8 @@
feature_flag,
sl,
rec_flag,
- rec_count);
+ rec_count,
+ num_aux_planes);
if (!ret) {
goto destroy_realm;
} else {
@@ -403,7 +418,7 @@
ERROR("Invalid Rec Count\n");
return false;
}
- host_shared_data_set_realm_cmd(realm_ptr, cmd, rec_num);
+ host_shared_data_set_realm_cmd(realm_ptr, cmd, PRIMARY_PLANE_ID, rec_num);
if (!host_enter_realm(realm_ptr, &realm_exit_reason, &host_call_result, rec_num)) {
return false;
}
@@ -470,3 +485,19 @@
tftf_send_sgi(sgi, core_pos);
}
}
+
+/*
+ * Set Args for Aux Plane Enter
+ * Realm helpers copy the same realm image for each plane
+ * Entrypoint for aux plane = realm.par_base + (plane_num * realm..par_size)
+ */
+void host_realm_set_aux_plane_args(struct realm *realm_ptr,
+ unsigned int plane_num)
+{
+ /* Plane Index */
+ host_shared_data_set_host_val(realm_ptr, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, plane_num);
+
+ /* Plane entrypoint */
+ host_shared_data_set_host_val(realm_ptr, PRIMARY_PLANE_ID, 0U, HOST_ARG2_INDEX,
+ realm_ptr->par_base + (plane_num * realm_ptr->par_size));
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
index ebf4580..27b03e8 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
@@ -76,7 +76,7 @@
* must be preserved unless they contain result,
* as specified in the function definition.
*/
- if (regs[0] != RMI_RTT_READ_ENTRY) {
+ if ((regs[0] != RMI_RTT_READ_ENTRY) && (regs[0] != RMI_RTT_AUX_MAP_PROTECTED)) {
CHECK_RET(4);
}
@@ -184,6 +184,16 @@
rd, rtt, map_addr, (u_register_t)level}, 5U).ret0;
}
+static inline u_register_t host_rmi_rtt_aux_create(u_register_t rd,
+ u_register_t rtt,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index)
+{
+ return host_rmi_handler(&(smc_args) {RMI_RTT_AUX_CREATE,
+ rd, rtt, map_addr, (u_register_t)level, tree_index}, 6U).ret0;
+}
+
u_register_t host_rmi_rtt_destroy(u_register_t rd,
u_register_t map_addr,
long level,
@@ -200,6 +210,24 @@
return rets.ret0;
}
+u_register_t host_rmi_rtt_aux_destroy(u_register_t rd,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index,
+ u_register_t *rtt,
+ u_register_t *top)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_DESTROY,
+ rd, map_addr, (u_register_t)level,
+ tree_index,
+ (u_register_t)&rets}, 6U);
+ *rtt = rets.ret1;
+ *top = rets.ret2;
+ return rets.ret0;
+}
+
u_register_t host_rmi_features(u_register_t index, u_register_t *features)
{
smc_ret_values rets;
@@ -243,6 +271,22 @@
return rets.ret0;
}
+static inline u_register_t host_rmi_rtt_aux_fold(u_register_t rd,
+ u_register_t map_addr,
+ long level,
+ u_register_t tree_index,
+ u_register_t *pa)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_FOLD,
+ rd, map_addr, (u_register_t)level,
+ tree_index,
+ (u_register_t)&rets}, 6U);
+ *pa = rets.ret1;
+ return rets.ret0;
+}
+
static inline u_register_t host_rmi_rec_aux_count(u_register_t rd,
u_register_t *aux_count)
{
@@ -276,6 +320,42 @@
rd, map_addr, (u_register_t)level, ns_pa}, 5U).ret0;
}
+u_register_t host_rmi_rtt_aux_map_unprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_UNPROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *fail_index = rets.ret1;
+ *level_pri = rets.ret2;
+ *state = rets.ret3;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_map_protected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state,
+ u_register_t *ripas)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_PROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *fail_index = rets.ret1;
+ *level_pri = rets.ret2;
+ *state = rets.ret3;
+ *ripas = rets.ret4;
+ return rets.ret0;
+}
+
u_register_t host_rmi_rtt_readentry(u_register_t rd,
u_register_t map_addr,
long level,
@@ -305,6 +385,36 @@
return rets.ret0;
}
+u_register_t host_rmi_rtt_aux_unmap_unprotected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_UNPROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *top = rets.ret1;
+ *level = rets.ret2;
+ return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_unmap_protected(u_register_t rd,
+ u_register_t map_addr,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_PROTECTED,
+ rd, map_addr, tree_index}, 4U);
+ *top = rets.ret1;
+ *level = rets.ret2;
+ return rets.ret0;
+}
+
bool host_ipa_is_ns(u_register_t addr, u_register_t rmm_feat_reg0)
{
return (addr >> (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, rmm_feat_reg0) - 1UL) == 1UL);
@@ -351,6 +461,42 @@
return REALM_SUCCESS;
}
+static u_register_t host_realm_create_rtt_aux_levels(struct realm *realm,
+ u_register_t map_addr,
+ long level, long max_level,
+ u_register_t tree_index)
+{
+ u_register_t rtt, ret, ipa_align;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ while (level++ < max_level) {
+ rtt = (u_register_t)page_alloc(PAGE_SIZE);
+ if (rtt == HEAP_NULL_PTR) {
+ ERROR("Failed to allocate memory for rtt\n");
+ return REALM_ERROR;
+ } else {
+ ret = host_rmi_granule_delegate(rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_delegate", rtt, ret);
+ return REALM_ERROR;
+ }
+ }
+ ipa_align = ALIGN_DOWN(map_addr, RTT_MAP_SIZE(level <= 0 ? level : level - 1));
+ ret = host_rmi_rtt_aux_create(realm->rd, rtt, ipa_align, level,
+ tree_index);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, map_addr =0x%lx ipa_align=0x%lx level=%lx ret=0x%lx\n",
+ "host_realm_rtt_aux_create", map_addr, ipa_align, level, ret);
+ host_rmi_granule_undelegate(rtt);
+ page_free(rtt);
+ return REALM_ERROR;
+ }
+ }
+
+ return REALM_SUCCESS;
+}
+
u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr,
long level)
{
@@ -379,6 +525,93 @@
}
+u_register_t host_realm_aux_map_protected_data(struct realm *realm,
+ u_register_t target_pa,
+ u_register_t map_size,
+ u_register_t tree_index,
+ u_register_t *fail_index,
+ u_register_t *level_pri,
+ u_register_t *state,
+ u_register_t *ripas)
+{
+ u_register_t ret, top;
+ long level;
+ int8_t ulevel;
+ u_register_t size = 0UL;
+ u_register_t map_addr = target_pa;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_map_protected(realm->rd, map_addr, tree_index,
+ fail_index, level_pri, state, ripas);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT_AUX) {
+ /* Create missing RTTs till L3 and retry */
+ ulevel = RMI_RETURN_INDEX(ret);
+ level = (long)ulevel;
+
+ ret = host_realm_create_rtt_aux_levels(realm, map_addr,
+ level,
+ 3U, tree_index);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx line=%u\n",
+ "host_realm_create_rtt_aux_levels",
+ ret, __LINE__);
+ goto err;
+ }
+ ret = host_rmi_rtt_aux_map_protected(realm->rd, target_pa, tree_index,
+ fail_index, level_pri, state, ripas);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx\n",
+ "host_rmi_data_create", ret);
+ goto err;
+ }
+ } else if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_rtt_aux_map_protected failed ret = 0x%lx", ret);
+ goto err;
+ }
+ map_addr += PAGE_SIZE;
+ }
+ return REALM_SUCCESS;
+
+err:
+ while (size >= PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_unmap_protected(realm->rd, target_pa, tree_index,
+ &top, (u_register_t *)&level);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+ "host_rmi_rtt_aux_unmap_protected", map_addr, ret);
+ }
+ size -= PAGE_SIZE;
+ map_addr -= PAGE_SIZE;
+ }
+ return REALM_ERROR;
+}
+
+u_register_t host_realm_aux_unmap_protected_data(struct realm *realm,
+ u_register_t target_ipa,
+ u_register_t map_size,
+ u_register_t tree_index,
+ u_register_t *top,
+ u_register_t *level)
+{
+ u_register_t ret, size = 0UL, map_addr = target_ipa;
+
+ assert(tree_index != PRIMARY_RTT_INDEX);
+ for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+ ret = host_rmi_rtt_aux_unmap_protected(realm->rd, map_addr, tree_index,
+ top, level);
+ if (ret != RMI_SUCCESS) {
+ WARN("%s() failed, ret=0x%lx line=%u\n",
+ "host_rmi_rtt_aux_unmap_protected",
+ ret, __LINE__);
+ return REALM_ERROR;
+ }
+ map_addr += PAGE_SIZE;
+ }
+ return REALM_SUCCESS;
+}
+
u_register_t host_realm_delegate_map_protected_data(bool unknown,
struct realm *realm,
u_register_t target_pa,
@@ -392,7 +625,7 @@
u_register_t phys = target_pa;
u_register_t map_addr = target_pa;
- if (!IS_ALIGNED(map_addr, map_size)) {
+ if (!IS_ALIGNED(map_addr, PAGE_SIZE)) {
return REALM_ERROR;
}
@@ -562,6 +795,50 @@
return REALM_SUCCESS;
}
+static u_register_t host_realm_destroy_free_aux_rtt(struct realm *realm,
+ u_register_t addr,
+ long level)
+{
+ u_register_t rtt2, top, ret;
+
+ /* Destroy and undelegate RTT entry for all trees */
+ for (unsigned int tree_index = 1U;
+ tree_index <= realm->num_aux_planes;
+ tree_index++) {
+
+ ret = host_rmi_rtt_aux_destroy(realm->rd, ALIGN_DOWN(addr,
+ RTT_MAP_SIZE(level)),
+ level + 1L,
+ tree_index, &rtt2, &top);
+
+ if (ret != RMI_SUCCESS) {
+ /*
+ * IPA might not be mapped on all AUX RTTs
+ * ignore error
+ */
+ VERBOSE("%s() failed, map_addr=0x%lx ret=0x%lx \
+ rtt2=0x%lx \
+ top=0x%lx level=0x%lx\n",
+ "host_rmi_rtt_aux_destroy",
+ addr, ret, rtt2,
+ top, level + 1L);
+ }
+
+ if (rtt2 != 0UL) {
+ ret = host_rmi_granule_undelegate(rtt2);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate",
+ rtt2, ret);
+ return REALM_ERROR;
+ }
+
+ page_free(rtt2);
+ }
+ }
+ return REALM_SUCCESS;
+}
+
static u_register_t host_realm_destroy_undelegate_range(struct realm *realm,
u_register_t ipa,
u_register_t addr,
@@ -573,6 +850,29 @@
while (size >= PAGE_SIZE) {
ret = host_rmi_data_destroy(rd, ipa, &data, &top);
+
+ if (ret == RMI_ERROR_RTT_AUX) {
+ /* Unmap from all Aux RTTs */
+ for (unsigned int tree_index = 1U; tree_index <= realm->num_aux_planes;
+ tree_index++) {
+ u_register_t top1, level1;
+
+ /* IPA might not be mapped in all Aux RTTs ignore error */
+ ret = host_rmi_rtt_aux_unmap_protected(
+ rd,
+ ipa,
+ tree_index,
+ &top1, &level1);
+ if (ret != RMI_SUCCESS) {
+ VERBOSE("%s() failed, addr=0x%lx ret=0x%lx tree=0x%x\n",
+ "host_rmi_rtt_aux_unmap_protected",
+ ipa, ret, tree_index);
+ }
+ }
+ /* Retry DATA_DESTROY */
+ continue;
+ }
+
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
"host_rmi_data_destroy", ipa, ret);
@@ -622,6 +922,28 @@
case RMI_ASSIGNED:
if (host_ipa_is_ns(map_addr, realm->rmm_feat_reg0)) {
+ u_register_t level1;
+
+ /* Unmap from all Aux RTT */
+ if (!realm->rtt_tree_single) {
+ for (unsigned int tree_index = 1U;
+ tree_index <= realm->num_aux_planes;
+ tree_index++) {
+
+ ret = host_rmi_rtt_aux_unmap_unprotected(
+ rd,
+ map_addr,
+ tree_index,
+ &top, &level1);
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+ "host_rmi_rtt_unmap_unprotected",
+ map_addr, ret);
+ }
+ }
+ }
+
ret = host_rmi_rtt_unmap_unprotected(
rd,
map_addr,
@@ -669,6 +991,19 @@
map_addr, ret);
return REALM_ERROR;
}
+
+ /* RTT_AUX_DESTROY */
+ if (!realm->rtt_tree_single) {
+ ret = host_realm_destroy_free_aux_rtt(realm, map_addr,
+ level);
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, map_addr=0x%lx ret=0x%lx\n",
+ "host_realm_destroy_free_aux_rtt",
+ map_addr, ret);
+ return REALM_ERROR;
+ }
+ }
break;
default:
return REALM_ERROR;
@@ -700,11 +1035,28 @@
return ret.ret1;
}
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+ u_register_t rec,
+ u_register_t base,
+ u_register_t top,
+ u_register_t *out_top,
+ u_register_t *rtt_tree)
+{
+ smc_ret_values rets;
+
+ rets = host_rmi_handler(&(smc_args) {RMI_RTT_SET_S2AP,
+ rd, rec, base, top,
+ (u_register_t)&rets}, 6U);
+ *out_top = rets.ret1;
+ *rtt_tree = rets.ret2;
+ return rets.ret0;
+}
+
u_register_t host_realm_create(struct realm *realm)
{
struct rmi_realm_params *params;
u_register_t ret;
- unsigned int count;
+ unsigned int count, rtt_page_count = 0U;
realm->par_size = REALM_MAX_LOAD_IMG_SIZE;
@@ -724,11 +1076,19 @@
}
}
+ assert(realm->num_aux_planes <= MAX_AUX_PLANE_COUNT);
+
/*
- * Allocate memory for PAR - Realm image. Granule delegation
+ * Allocate memory for PAR - Realm image for each Plane.
+ * Granule delegation
* of PAR will be performed during rtt creation.
+ * realm->par_size is size if single Plane image.
+ * Same image is copied for each plane.
+ * Offset for Plane N will be realm->par_base + (N*realm->par_size)
*/
- realm->par_base = (u_register_t)page_alloc(realm->par_size);
+ realm->par_base = (u_register_t)page_alloc((realm->par_size) *
+ (realm->num_aux_planes + 1U));
+
if (realm->par_base == HEAP_NULL_PTR) {
ERROR("page_alloc failed, base=0x%lx, size=0x%lx\n",
realm->par_base, realm->par_size);
@@ -737,6 +1097,15 @@
INFO("Realm start adr=0x%lx\n", realm->par_base);
+ /* Allocate memory for params */
+ params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
+ if (params == NULL) {
+ ERROR("Failed to allocate memory for params\n");
+ goto pool_reset;
+ }
+
+ memset(params, 0, PAGE_SIZE);
+
/* Allocate and delegate RD */
realm->rd = (u_register_t)page_alloc(PAGE_SIZE);
if (realm->rd == HEAP_NULL_PTR) {
@@ -752,28 +1121,41 @@
}
/* Allocate and delegate RTT */
- realm->rtt_addr = (u_register_t)page_alloc(PAGE_SIZE);
+ if (realm->rtt_tree_single) {
+ rtt_page_count = 1U;
+ } else {
+ /* Primary + AUX RTT Tree */
+ rtt_page_count = (realm->num_aux_planes + 1U);
+ }
+
+ realm->rtt_addr = (u_register_t)page_alloc(rtt_page_count * PAGE_SIZE);
+
if (realm->rtt_addr == HEAP_NULL_PTR) {
ERROR("Failed to allocate memory for rtt_addr\n");
goto err_undelegate_rd;
} else {
- ret = host_rmi_granule_delegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_delegate(realm->rtt_addr + (i * PAGE_SIZE));
+
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
"host_rmi_granule_delegate", realm->rtt_addr, ret);
- goto err_free_rtt;
+
+ for (unsigned int j = 0U; j < i; j++) {
+ host_rmi_granule_undelegate(realm->rtt_addr
+ + (i * PAGE_SIZE));
+ }
+
+ goto err_free_rtt;
+ }
+
+ if (i > 0U && !realm->rtt_tree_single) {
+ realm->aux_rtt_addr[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+ params->aux_rtt_base[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+ }
}
}
- /* 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;
- }
-
- memset((char *)params, 0U, PAGE_SIZE);
-
/* Populate params */
params->s2sz = EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ,
realm->rmm_feat_reg0);
@@ -782,16 +1164,16 @@
/* SVE enable and vector length */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_SVE_EN) != 0UL) {
- params->flags = RMI_REALM_FLAGS_SVE;
+ params->flags0 = RMI_REALM_FLAGS0_SVE;
params->sve_vl = realm->sve_vl;
} else {
- params->flags = 0UL;
+ params->flags0 = 0UL;
params->sve_vl = 0U;
}
/* PMU enable and number of event counters */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_PMU_EN) != 0UL) {
- params->flags |= RMI_REALM_FLAGS_PMU;
+ params->flags0 |= RMI_REALM_FLAGS0_PMU;
params->pmu_num_ctrs = realm->pmu_num_ctrs;
} else {
params->pmu_num_ctrs = 0U;
@@ -799,21 +1181,32 @@
/* LPA2 enable */
if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_LPA2) != 0UL) {
- params->flags |= RMI_REALM_FLAGS_LPA2;
+ params->flags0 |= RMI_REALM_FLAGS0_LPA2;
}
params->rtt_level_start = realm->start_level;
- params->hash_algo = RMI_HASH_SHA_256;
+ params->algorithm = RMI_HASH_SHA_256;
params->vmid = vmid++;
params->rtt_base = realm->rtt_addr;
params->rtt_num_start = 1U;
+ if (!realm->rtt_tree_single) {
+ params->flags1 = RMI_REALM_FLAGS1_RTT_TREE_PP;
+ }
+ params->num_aux_planes = realm->num_aux_planes;
+
+ /* Allocate VMID for all planes */
+ for (unsigned int i = 0U; i < realm->num_aux_planes; i++) {
+ params->aux_vmid[i] = (unsigned short)(vmid++);
+ realm->aux_vmid[i] = params->aux_vmid[i];
+ }
+
/* Create Realm */
ret = host_rmi_realm_create(realm->rd, (u_register_t)params);
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_realm_create", realm->rd, ret);
- goto err_free_params;
+ goto err_free_vmid;
}
realm->vmid = params->vmid;
@@ -822,7 +1215,7 @@
ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_rec_aux_count", realm->rd, ret);
host_rmi_realm_destroy(realm->rd);
- goto err_free_params;
+ goto err_free_vmid;
}
realm->state = REALM_STATE_NEW;
@@ -831,14 +1224,10 @@
page_free((u_register_t)params);
return REALM_SUCCESS;
-err_free_params:
- page_free((u_register_t)params);
-
-err_undelegate_rtt:
- ret = host_rmi_granule_undelegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
- "host_rmi_granule_undelegate", realm->rtt_addr, ret);
+err_free_vmid:
+ /* Free VMID */
+ for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+ vmid--;
}
err_free_rtt:
@@ -850,9 +1239,20 @@
WARN("%s() failed, rd=0x%lx ret=0x%lx\n",
"host_rmi_granule_undelegate", realm->rd, ret);
}
+
err_free_rd:
page_free(realm->rd);
+ page_free((u_register_t)params);
+
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+ if (ret != RMI_SUCCESS) {
+ WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+ }
+ }
+
err_free_par:
page_free(realm->par_base);
@@ -875,22 +1275,23 @@
u_register_t realm_payload_adr)
{
u_register_t src_pa = realm_payload_adr;
- u_register_t i = 0UL;
u_register_t ret;
/* MAP image regions */
- while (i < (realm->par_size / PAGE_SIZE)) {
+ /* Copy Plane 0-N Images */
+
+ for (unsigned int j = 0U; j <= realm->num_aux_planes; j++) {
ret = host_realm_delegate_map_protected_data(false, realm,
- realm->par_base + i * PAGE_SIZE,
- PAGE_SIZE,
- src_pa + i * PAGE_SIZE);
+ realm->par_base + (j * realm->par_size),
+ realm->par_size,
+ src_pa);
+
if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
- "host_realm_delegate_map_protected_data",
- realm->par_base, ret);
+ ERROR("%s() failed par_base=0x%lx size=0x%lx j=%u ret=0x%lx\n",
+ "host_realm_delegate_map_protected_data",
+ realm->par_base, realm->par_size, j, ret);
return REALM_ERROR;
}
- i++;
}
return REALM_SUCCESS;
@@ -942,25 +1343,74 @@
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(RMI_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 = host_realm_map_unprotected(realm, ns_shared_mem_adr +
- (i * PAGE_SIZE), PAGE_SIZE);
+ for (unsigned int i = 0U; i < ns_shared_mem_size / PAGE_SIZE; i++) {
+ ret = host_realm_map_unprotected(realm,
+ ns_shared_mem_adr + (i * PAGE_SIZE),
+ PAGE_SIZE);
+
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
"host_realm_map_unprotected",
- (ns_shared_mem_adr + i * PAGE_SIZE), ret);
+ (ns_shared_mem_adr + (i * PAGE_SIZE)), ret);
return REALM_ERROR;
}
- i++;
}
+
+ /* AUX MAP NS buffer for all RTTs */
+ if (!realm->rtt_tree_single) {
+ for (unsigned int i = 0U; i < ns_shared_mem_size / PAGE_SIZE; i++) {
+ for (unsigned int j = 0U; j < realm->num_aux_planes; j++) {
+ u_register_t fail_index, level_pri, state;
+
+ ret = host_rmi_rtt_aux_map_unprotected(realm->rd,
+ realm->ipa_ns_buffer + (i * PAGE_SIZE),
+ j + 1, &fail_index, &level_pri, &state);
+
+ if (ret == RMI_SUCCESS) {
+ continue;
+ } else if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT_AUX) {
+
+ /* Create Level and retry */
+ int8_t ulevel = RMI_RETURN_INDEX(ret);
+ long level = (long)ulevel;
+
+ ret = host_realm_create_rtt_aux_levels(realm,
+ realm->ipa_ns_buffer +
+ (i * PAGE_SIZE),
+ level, 3, j + 1);
+
+ if (ret != RMI_SUCCESS) {
+ return REALM_ERROR;
+ }
+
+ ret = host_rmi_rtt_aux_map_unprotected(realm->rd,
+ realm->ipa_ns_buffer +
+ (i * PAGE_SIZE),
+ j + 1, &fail_index,
+ &level_pri, &state);
+
+ if (ret == RMI_SUCCESS) {
+ continue;
+ }
+ }
+
+ ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
+ "host_realm_aux_map_unprotected",
+ (ns_shared_mem_adr), ret);
+ return REALM_ERROR;
+
+ }
+ }
+ }
+
return REALM_SUCCESS;
}
@@ -1131,6 +1581,7 @@
u_register_t host_realm_destroy(struct realm *realm)
{
u_register_t ret;
+ unsigned int rtt_page_count;
long rtt_start_level = realm->start_level;
if (realm->state == REALM_STATE_NULL) {
@@ -1209,11 +1660,24 @@
return REALM_ERROR;
}
- ret = host_rmi_granule_undelegate(realm->rtt_addr);
- if (ret != RMI_SUCCESS) {
- ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
- "host_rmi_granule_undelegate", realm->rtt_addr, ret);
- return REALM_ERROR;
+ if (realm->rtt_tree_single) {
+ rtt_page_count = 1U;
+ } else {
+ rtt_page_count = realm->num_aux_planes + 1U;
+ }
+
+ for (unsigned int i = 0U; i < rtt_page_count; i++) {
+ ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+ "host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+ return REALM_ERROR;
+ }
+ }
+
+ /* Free VMID */
+ for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+ vmid--;
}
page_free(realm->rd);
@@ -1239,6 +1703,126 @@
return MAX_REC_COUNT;
}
+/* Check if adr is in range of any of the Plane Images */
+static bool is_adr_in_par(struct realm *realm, u_register_t addr)
+{
+ if ((addr >= realm->par_base) && (addr <
+ (realm->par_base + (realm->par_size * (realm->num_aux_planes + 1U))))) {
+ return true;
+ }
+ return false;
+}
+
+/* Handle Plane permission falut, return true to return to realm, false to host */
+static bool host_realm_handle_perm_fault(struct realm *realm, struct rmi_rec_run *run)
+{
+ /*
+ * If exception is not in primary rtt
+ * Map Adr in failing Aux RTT and re-enter rec
+ * Validate faulting adr is in Realm payload area
+ * Note - PlaneN uses Primary RTT tree index 0
+ */
+
+ u_register_t fail_index;
+ u_register_t level_pri;
+ u_register_t state;
+ u_register_t ripas;
+ u_register_t ret;
+
+ VERBOSE("host aux_map 0x%lx rtt 0x%lx\n",
+ run->exit.hpfar, run->exit.rtt_tree);
+
+ ret = host_realm_aux_map_protected_data(realm,
+ run->exit.hpfar << 8U,
+ PAGE_SIZE,
+ run->exit.rtt_tree,
+ &fail_index, &level_pri, &state, &ripas);
+
+ if (ret != REALM_SUCCESS) {
+ ERROR("host_realm_aux_map_protected_data failed\n");
+ return false;
+ }
+
+ /* re-enter realm */
+ return true;
+}
+
+/* Handle RSI_MEM_SET_PERM_INDEX by P0, return true to return to realm, false to return to host */
+static bool host_realm_handle_s2ap_change(struct realm *realm, struct rmi_rec_run *run)
+{
+
+
+ u_register_t new_base = run->exit.s2ap_base;
+ u_register_t top = run->exit.s2ap_top;
+ u_register_t rtt_tree, ret;
+ bool ret1 = true;
+
+ while (new_base != top) {
+ ret = host_rmi_rtt_set_s2ap(realm->rd,
+ realm->rec[0U],
+ new_base,
+ top, &new_base,
+ &rtt_tree);
+
+ if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT_AUX) {
+
+ int8_t ulevel = RMI_RETURN_INDEX(ret);
+ long level = (long)ulevel;
+
+ assert(rtt_tree != PRIMARY_RTT_INDEX);
+
+ /* create missing aux rtt level */
+ VERBOSE("set s2ap fail missing aux rtt=%lx 0x%lx 0x%lx\n",
+ rtt_tree, new_base, top);
+
+ ret = host_realm_create_rtt_aux_levels(realm, new_base,
+ level,
+ level + 1, rtt_tree);
+ if (ret != RMI_SUCCESS) {
+ INFO("host_rmi_create_rtt_aux_levels \
+ failed 0x%lx\n", new_base);
+ ret1 = false;
+ break;
+ }
+
+ /* Retry RMI_RTT_SET_S2AP */
+ continue;
+ } else if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
+
+ int8_t ulevel = RMI_RETURN_INDEX(ret);
+ long level = (long)ulevel;
+
+ assert(rtt_tree == PRIMARY_RTT_INDEX);
+ INFO("set s2ap failed missing rtt=0x%lx 0x%lx 0x%lx\n\n",
+ rtt_tree, new_base, top);
+
+ /* create missing rtt level */
+ ret = host_rmi_create_rtt_levels(realm, new_base,
+ level,
+ level + 1);
+
+ if (ret != RMI_SUCCESS) {
+ INFO("host_rmi_create_rtt_levels \
+ failed 0x%lx\n", new_base);
+ ret1 = false;
+ break;
+ }
+
+ /* Retry RMI_RTT_SET_S2AP */
+ continue;
+ } else if (RMI_RETURN_STATUS(ret) != RMI_SUCCESS) {
+ INFO("host set s2ap failed ret=0x%lx\n",
+ RMI_RETURN_STATUS(ret));
+ ret1 = false;
+ break;
+ }
+ }
+
+ /* re-enter realm */
+ return ret1;
+}
+
+
u_register_t host_realm_rec_enter(struct realm *realm,
u_register_t *exit_reason,
unsigned int *host_call_result,
@@ -1273,6 +1857,28 @@
}
}
+ if ((run->exit.exit_reason == RMI_EXIT_SYNC) &&
+ is_adr_in_par(realm, (run->exit.hpfar << 8U)) &&
+ (((((run->exit.esr & ISS_FSC_MASK) >= FSC_L0_TRANS_FAULT) &&
+ ((run->exit.esr & ISS_FSC_MASK) <= FSC_L3_TRANS_FAULT)) ||
+ ((run->exit.esr & ISS_FSC_MASK) == FSC_L_MINUS1_TRANS_FAULT))) &&
+ !realm->rtt_tree_single &&
+ (realm->num_aux_planes > 0U)) {
+
+ re_enter_rec = host_realm_handle_perm_fault(realm, run);
+ }
+
+ /*
+ * P0 issued RSI_MEM_SET_PERM_INDEX call
+ * Validate base is in range of realm payload area
+ */
+ if ((run->exit.exit_reason == RMI_EXIT_S2AP_CHANGE) &&
+ is_adr_in_par(realm, run->exit.s2ap_base) &&
+ (realm->num_aux_planes > 0U)) {
+
+ re_enter_rec = host_realm_handle_s2ap_change(realm, run);
+ }
+
if (ret != RMI_SUCCESS) {
return ret;
}
@@ -1284,7 +1890,8 @@
re_enter_rec = true;
break;
case HOST_CALL_EXIT_PRINT_CMD:
- realm_print_handler(realm, REC_IDX(run->exit.gprs[0]));
+ realm_print_handler(realm, run->exit.gprs[0],
+ REC_IDX(run->exit.gprs[1]));
re_enter_rec = true;
break;
case HOST_CALL_EXIT_SUCCESS_CMD:
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
index b3bfdae..eb75028 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_shared_data.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_shared_data.c
@@ -11,69 +11,65 @@
#include <host_realm_rmi.h>
#include <host_shared_data.h>
-/*
- * Currently we support only creation of a single Realm in TFTF.
- * Hence we can assume that Shared area should be sufficient for all
- * the RECs of this Realm.
- */
-CASSERT(NS_REALM_SHARED_MEM_SIZE > (MAX_REC_COUNT *
+CASSERT(NS_REALM_SHARED_MEM_SIZE > (MAX_REC_COUNT * MAX_PLANE_COUNT *
sizeof(host_shared_data_t)),
too_small_realm_shared_mem_size);
/*
* Return shared buffer pointer mapped as host_shared_data_t structure
*/
-host_shared_data_t *host_get_shared_structure(struct realm *realm_ptr, unsigned int rec_num)
+host_shared_data_t *host_get_shared_structure(struct realm *realm_ptr,
+ unsigned int plane_num, unsigned int rec_num)
{
- host_shared_data_t *host_shared_data;
+ host_shared_data_arr_t host_shared_data;
assert(realm_ptr != NULL);
assert(rec_num < MAX_REC_COUNT);
- host_shared_data = (host_shared_data_t *)realm_ptr->host_shared_data;
- return &host_shared_data[rec_num];
+ host_shared_data = (host_shared_data_arr_t)realm_ptr->host_shared_data;
+ return (host_shared_data_t *)&(*host_shared_data)[plane_num][rec_num];
}
/*
* Set data to be shared from Host to realm
*/
void host_shared_data_set_host_val(struct realm *realm_ptr,
- unsigned int rec_num, uint8_t index, u_register_t val)
+ unsigned int plane_num, unsigned int rec_num, uint8_t index, u_register_t val)
{
- host_shared_data_t *host_shared_data;
+ host_shared_data_arr_t host_shared_data;
assert(realm_ptr != NULL);
assert(rec_num < MAX_REC_COUNT);
assert(index < MAX_DATA_SIZE);
- host_shared_data = (host_shared_data_t *)realm_ptr->host_shared_data;
- host_shared_data[rec_num].host_param_val[index] = val;
+ host_shared_data = (host_shared_data_arr_t)realm_ptr->host_shared_data;
+ (*host_shared_data)[plane_num][rec_num].host_param_val[index] = val;
}
/*
* Return data shared by realm in realm_out_val.
*/
u_register_t host_shared_data_get_realm_val(struct realm *realm_ptr,
- unsigned int rec_num, uint8_t index)
+ unsigned int plane_num, unsigned int rec_num, uint8_t index)
{
- host_shared_data_t *host_shared_data;
+ host_shared_data_arr_t host_shared_data;
assert(realm_ptr != NULL);
assert(rec_num < MAX_REC_COUNT);
assert(index < MAX_DATA_SIZE);
- host_shared_data = (host_shared_data_t *)realm_ptr->host_shared_data;
- return host_shared_data[rec_num].realm_out_val[index];
+ host_shared_data = (host_shared_data_arr_t)realm_ptr->host_shared_data;
+ return (*host_shared_data)[plane_num][rec_num].realm_out_val[index];
}
/*
* Set command to be send from Host to realm
*/
void host_shared_data_set_realm_cmd(struct realm *realm_ptr,
- uint8_t cmd, unsigned int rec_num)
+ uint8_t cmd, unsigned int plane_num, unsigned int rec_num)
{
- host_shared_data_t *host_shared_data;
+ host_shared_data_arr_t host_shared_data;
assert(realm_ptr != NULL);
assert(rec_num < MAX_REC_COUNT);
- host_shared_data = (host_shared_data_t *)realm_ptr->host_shared_data;
- host_shared_data[rec_num].realm_cmd = cmd;
+ host_shared_data = (host_shared_data_arr_t)realm_ptr->host_shared_data;
+ (*host_shared_data)[plane_num][rec_num].realm_cmd = cmd;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
index 9a6341d..43d9f01 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
@@ -22,7 +22,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- 0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U)) {
+ 0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
@@ -41,7 +41,7 @@
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 50UL),
- RTT_MIN_LEVEL, rec_flag, 1U)) {
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
@@ -67,7 +67,7 @@
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
- RTT_MIN_LEVEL, rec_flag, 1U)) {
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -99,7 +99,7 @@
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
- RTT_MIN_LEVEL, rec_flag, 1U)) {
+ RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -155,7 +155,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, RTT_MIN_LEVEL, rec_flag, 1U)) {
+ feature_flag, RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
return TEST_RESULT_SUCCESS;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
index e3ee23b..00d2d57 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
@@ -22,6 +22,7 @@
static uint64_t is_secondary_cpu_on;
static struct realm realm;
static struct realm realm1;
+static struct pmu_registers pmu_state[PLATFORM_CORE_COUNT];
/*
* Test tries to create max Rec
@@ -47,7 +48,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -55,7 +56,9 @@
rec_num = (unsigned int)rand() % MAX_REC_COUNT;
for (unsigned int i = 0; i < MAX_REC_COUNT; i++) {
- host_shared_data_set_host_val(&realm, rec_num, HOST_ARG1_INDEX, 10U);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID,
+ rec_num, HOST_ARG1_INDEX, 10U);
+
ret1 = host_enter_realm_execute(&realm, REALM_SLEEP_CMD,
RMI_EXIT_HOST_CALL, rec_num);
if (!ret1) {
@@ -112,7 +115,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 3U)) {
+ feature_flag, sl, rec_flag, 3U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -257,7 +260,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -361,14 +364,14 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
return TEST_RESULT_FAIL;
}
is_secondary_cpu_on = 0U;
init_spinlock(&secondary_cpu_lock);
my_mpidr = read_mpidr_el1() & MPID_MASK;
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, rec_count);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, rec_count);
ret1 = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
RMI_EXIT_PSCI, 0U);
if (!ret1) {
@@ -499,18 +502,18 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
if (!host_create_activate_realm_payload(&realm2, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ret2 = host_destroy_realm(&realm);
return TEST_RESULT_FAIL;
}
/* Realm to request CPU_ON for rec 2 */
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, 2U);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, 2U);
ret1 = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
RMI_EXIT_PSCI, 0U);
if (!ret1) {
@@ -585,6 +588,9 @@
spin_lock(&secondary_cpu_lock);
i = is_secondary_cpu_on++;
spin_unlock(&secondary_cpu_lock);
+
+ host_set_pmu_state(&pmu_state[i]);
+
ret1 = host_enter_realm_execute(&realm, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, i);
if (!ret1) {
return TEST_RESULT_FAIL;
@@ -597,10 +603,16 @@
if (!ret1) {
return TEST_RESULT_FAIL;
}
+
ret1 = host_enter_realm_execute(&realm1, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, i);
- if (ret1) {
+ if (!ret1) {
+ return TEST_RESULT_FAIL;
+ }
+
+ if (host_check_pmu_state(&pmu_state[i])) {
return TEST_RESULT_SUCCESS;
}
+
return TEST_RESULT_FAIL;
}
@@ -621,7 +633,7 @@
u_register_t rmm_feat_reg0;
u_register_t rec_flag[MAX_REC_COUNT];
bool ret1 = false, ret2;
- unsigned int num_cnts, rec_count, i;
+ unsigned int rec_count, i, num_cnts;
u_register_t other_mpidr, my_mpidr, ret;
int cpu_node;
long sl = RTT_MIN_LEVEL;
@@ -647,7 +659,8 @@
}
num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
- host_set_pmu_state();
+ host_set_pmu_state(&pmu_state[0U]);
+
is_secondary_cpu_on = 0;
my_mpidr = read_mpidr_el1() & MPID_MASK;
@@ -661,7 +674,7 @@
/* Request more PMU counter than total, expect failure */
if (host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm create should have failed\n");
host_destroy_realm(&realm);
return TEST_RESULT_FAIL;
@@ -676,7 +689,7 @@
}
ret1 = host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U);
+ feature_flag, sl, rec_flag, 1U, 0U);
if (!get_feat_hpmn0_supported()) {
if (ret1) {
@@ -702,7 +715,7 @@
/* Prepare realm0, create recs for realm0 later */
if (!host_prepare_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
goto test_exit;
return TEST_RESULT_FAIL;
}
@@ -716,7 +729,7 @@
}
if (!host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count)) {
+ feature_flag, sl, rec_flag, rec_count, 0U)) {
goto test_exit2;
}
@@ -740,8 +753,11 @@
/* Pass num of PMU counters programmed to realm */
for (unsigned int j = 0U; j < rec_count; j++) {
- host_shared_data_set_host_val(&realm, j, HOST_ARG1_INDEX, num_cnts);
- host_shared_data_set_host_val(&realm1, j, HOST_ARG1_INDEX, num_cnts - 1U);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, j,
+ HOST_ARG1_INDEX, num_cnts);
+
+ host_shared_data_set_host_val(&realm1, PRIMARY_PLANE_ID, j,
+ HOST_ARG1_INDEX, num_cnts - 1U);
}
/*
@@ -771,6 +787,10 @@
goto test_exit2;
}
+ if (!host_check_pmu_state(&pmu_state[0U])) {
+ goto test_exit;
+ }
+
i = 0U;
/* Turn on all CPUs */
@@ -820,9 +840,5 @@
return TEST_RESULT_FAIL;
}
- if (!host_check_pmu_state()) {
- return TEST_RESULT_FAIL;
- }
-
return TEST_RESULT_SUCCESS;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
index 5304180..023ec1c 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
@@ -113,7 +113,7 @@
}
/* Check if rdvl matches the SVE VL created */
- sd = host_get_shared_structure(&realm, 0U);
+ sd = host_get_shared_structure(&realm, PRIMARY_PLANE_ID, 0U);
rl_output = (struct sve_cmd_rdvl *)sd->realm_cmd_output_buffer;
rl_max_sve_vq = SVE_VL_TO_VQ(rl_output->rdvl);
if (sve_vq == rl_max_sve_vq) {
@@ -188,7 +188,7 @@
goto rm_realm;
}
- sd = host_get_shared_structure(&realm, 0U);
+ sd = host_get_shared_structure(&realm, PRIMARY_PLANE_ID, 0U);
r_regs = (struct sve_cmd_id_regs *)sd->realm_cmd_output_buffer;
/* Check ID register SVE flags */
@@ -275,7 +275,7 @@
goto rm_realm;
}
- sd = host_get_shared_structure(&realm, 0U);
+ sd = host_get_shared_structure(&realm, PRIMARY_PLANE_ID, 0U);
rl_output = (struct sve_cmd_probe_vl *)sd->realm_cmd_output_buffer;
INFO("Supported SVE vector length in bits (expected):\n");
@@ -649,7 +649,7 @@
goto rm_realm;
}
- sd = host_get_shared_structure(&realm, 0U);
+ sd = host_get_shared_structure(&realm, PRIMARY_PLANE_ID, 0U);
r_regs = (struct sme_cmd_id_regs *)sd->realm_cmd_output_buffer;
/* Check ID register SME flags */
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index ce5409c..760a286 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -21,17 +21,160 @@
#include <host_realm_pmu.h>
#include <host_shared_data.h>
-#define SLEEP_TIME_MS 20U
+#define SLEEP_TIME_MS 2U
extern const char *rmi_exit[];
static struct realm realm[MAX_REALM_COUNT];
+static struct pmu_registers pmu_state;
#if ENABLE_PAUTH
static uint128_t pauth_keys_before[NUM_KEYS];
static uint128_t pauth_keys_after[NUM_KEYS];
#endif
+bool are_planes_supported(void)
+{
+ u_register_t feature_flag;
+
+ /* Read Realm Feature Reg 0 */
+ if (host_rmi_features(0UL, &feature_flag) != REALM_SUCCESS) {
+ ERROR("%s() failed\n", "host_rmi_features");
+ return false;
+ }
+
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES, feature_flag) > 0UL) {
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * @Test_Aim@ Test RSI_PLANE_REG_READ/WRITE
+ */
+test_result_t host_test_realm_create_planes_register_rw(void)
+{
+ bool ret1, ret2;
+ u_register_t rec_flag[MAX_REC_COUNT];
+ struct realm realm;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+ struct rmi_rec_run *run;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (!are_planes_supported()) {
+ return TEST_RESULT_SKIPPED;
+ }
+
+ if (is_feat_52b_on_4k_2_supported() == true) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ for (unsigned int i = 0U; i < MAX_REC_COUNT; i++) {
+ rec_flag[i] = RMI_RUNNABLE;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, 1U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* CMD for Plane N */
+ host_shared_data_set_realm_cmd(&realm, REALM_PLANE_N_REG_RW_CMD, 1U, 0U);
+
+ run = (struct rmi_rec_run *)realm.run[0U];
+
+ host_realm_set_aux_plane_args(&realm, 1U);
+ ret1 = host_enter_realm_execute(&realm, REALM_PLANE_N_REG_RW_CMD,
+ RMI_EXIT_HOST_CALL, 0U);
+
+ if (run->exit.exit_reason != RMI_EXIT_HOST_CALL) {
+ ERROR("Rec0 error exit=0x%lx ret1=%d HPFAR=0x%lx \
+ esr=0x%lx far=0x%lx\n",
+ run->exit.exit_reason, ret1,
+ run->exit.hpfar,
+ run->exit.esr, run->exit.far);
+ }
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret1 || !ret2) {
+ ERROR("%s(): enter=%d destroy=%d\n",
+ __func__, ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+ return host_cmp_result();
+}
+/*
+ * @Test_Aim@ Test realm payload creation with 3 Aux Planes, enter all Planes
+ * Host cannot enter Aux Planes directly,
+ * Host will enter P0, P0 will enter aux plane
+ */
+test_result_t host_test_realm_create_planes_enter(void)
+{
+ bool ret1, ret2;
+ u_register_t rec_flag[MAX_REC_COUNT];
+ struct realm realm;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+ struct rmi_rec_run *run;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (!are_planes_supported()) {
+ return TEST_RESULT_SKIPPED;
+ }
+
+ if (is_feat_52b_on_4k_2_supported() == true) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ for (unsigned int i = 0U; i < MAX_REC_COUNT; i++) {
+ rec_flag[i] = RMI_RUNNABLE;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, MAX_AUX_PLANE_COUNT)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* CMD for Plane N */
+ for (unsigned int j = 1U; j <= MAX_AUX_PLANE_COUNT; j++) {
+ host_shared_data_set_realm_cmd(&realm, REALM_SLEEP_CMD, j, 0U);
+ host_shared_data_set_host_val(&realm, j, 0U,
+ HOST_ARG1_INDEX, SLEEP_TIME_MS);
+ }
+
+ for (unsigned int j = 1U; j <= MAX_AUX_PLANE_COUNT; j++) {
+ run = (struct rmi_rec_run *)realm.run[0U];
+
+ host_realm_set_aux_plane_args(&realm, j);
+ ret1 = host_enter_realm_execute(&realm, REALM_ENTER_PLANE_N_CMD,
+ RMI_EXIT_HOST_CALL, 0U);
+
+
+ if (run->exit.exit_reason != RMI_EXIT_HOST_CALL) {
+ ERROR("Rec0 error exit=0x%lx ret1=%d HPFAR=0x%lx \
+ esr=0x%lx far=0x%lx\n",
+ run->exit.exit_reason, ret1,
+ run->exit.hpfar,
+ run->exit.esr, run->exit.far);
+ }
+ }
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret1 || !ret2) {
+ ERROR("%s(): enter=%d destroy=%d\n",
+ __func__, ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+
+ return host_cmp_result();
+}
+
/*
* @Test_Aim@ Test realm payload creation, execution and destruction iteratively
*/
@@ -59,11 +202,13 @@
unsigned int run_num = (unsigned int)rand() % MAX_REC_COUNT;
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
- host_shared_data_set_host_val(&realm, run_num, HOST_ARG1_INDEX, SLEEP_TIME_MS);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, run_num,
+ HOST_ARG1_INDEX, SLEEP_TIME_MS);
+
ret1 = host_enter_realm_execute(&realm, REALM_SLEEP_CMD, RMI_EXIT_HOST_CALL,
run_num);
ret2 = host_destroy_realm(&realm);
@@ -97,7 +242,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -141,7 +286,7 @@
pauth_test_lib_fill_regs_and_template(pauth_keys_before);
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -203,7 +348,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -281,17 +426,25 @@
static test_result_t host_test_realm_pmuv3(uint8_t cmd)
{
struct realm realm;
- u_register_t feature_flag;
+ u_register_t feature_flag, rmm_feat_reg0;
+ unsigned int num_cnts;
long sl = RTT_MIN_LEVEL;
u_register_t rec_flag[1] = {RMI_RUNNABLE};
bool ret1, ret2;
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- host_set_pmu_state();
+ /* Get Max PMU counter implemented through RMI_FEATURES */
+ if (host_rmi_features(0UL, &rmm_feat_reg0) != REALM_SUCCESS) {
+ ERROR("%s() failed\n", "host_rmi_features");
+ return TEST_RESULT_FAIL;
+ }
+
+ num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
+ host_set_pmu_state(&pmu_state);
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, (unsigned long long)(-1));
+ INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts);
if (is_feat_52b_on_4k_2_supported() == true) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
@@ -299,7 +452,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -319,7 +472,7 @@
return TEST_RESULT_FAIL;
}
- if (!host_check_pmu_state()) {
+ if (!host_check_pmu_state(&pmu_state)) {
return TEST_RESULT_FAIL;
}
@@ -412,7 +565,8 @@
ret = host_create_activate_realm_payload(&realm[num],
(u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT);
+ feature_flag, sl, rec_flag,
+ MAX_REC_COUNT, 0U);
if (!ret) {
goto destroy_realms;
}
@@ -420,8 +574,9 @@
for (unsigned int j = 0U; j < MAX_REC_COUNT; j++) {
for (unsigned int i = 0U; i < MAX_REALM_COUNT; i++) {
- host_shared_data_set_host_val(&realm[i], run_rec[i], HOST_ARG1_INDEX,
- SLEEP_TIME_MS);
+ host_shared_data_set_host_val(&realm[i], PRIMARY_PLANE_ID, run_rec[i],
+ HOST_ARG1_INDEX, SLEEP_TIME_MS);
+
ret = host_enter_realm_execute(&realm[i], REALM_SLEEP_CMD,
RMI_EXIT_HOST_CALL, run_rec[i]);
if (!ret) {
@@ -476,15 +631,15 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, 10U);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, 10U);
ret1 = host_enter_realm_execute(&realm, REALM_SLEEP_CMD, RMI_EXIT_HOST_CALL, 0U);
base = (u_register_t)page_alloc(PAGE_SIZE * test_page_num);
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG2_INDEX,
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG2_INDEX,
base + (PAGE_SIZE * test_page_num));
for (unsigned int i = 0U; i < test_page_num; i++) {
@@ -575,7 +730,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -586,7 +741,7 @@
ERROR("host_realm_delegate_map_protected_data failede\n");
goto destroy_realm;
}
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
ret1 = host_enter_realm_execute(&realm, REALM_REJECT_SET_RIPAS_CMD,
RMI_EXIT_RIPAS_CHANGE, 0U);
@@ -647,7 +802,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -672,8 +827,8 @@
}
INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
base, rtt.state, rtt.ripas);
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base);
ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
if (ret != RMI_SUCCESS || data != base) {
@@ -702,8 +857,8 @@
/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
- || ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
goto undelegate_destroy;
@@ -720,8 +875,8 @@
/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
- || ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault\n");
goto undelegate_destroy;
@@ -773,7 +928,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -802,8 +957,8 @@
}
INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
base, rtt.state, rtt.ripas);
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base);
/* Rec0 expect rec exit due to Instr Abort unassigned ram page */
ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
@@ -812,8 +967,8 @@
/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
- || ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
goto destroy_realm;
@@ -829,8 +984,8 @@
/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
- || ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
goto destroy_realm;
@@ -882,7 +1037,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -904,8 +1059,8 @@
}
INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
base, rtt.state, rtt.ripas);
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base);
if (host_realm_activate(&realm) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_activate");
@@ -945,8 +1100,8 @@
/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
- || ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_IFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
goto destroy_data;
@@ -962,8 +1117,8 @@
/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
- || ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
goto destroy_data;
@@ -1017,7 +1172,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 4U)) {
+ feature_flag, sl, rec_flag, 4U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1029,10 +1184,10 @@
ERROR("wrong initial state\n");
goto destroy_realm;
}
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 2U, HOST_ARG1_INDEX, base);
- host_shared_data_set_host_val(&realm, 3U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 2U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 3U, HOST_ARG1_INDEX, base);
/* Rec0 expect IA due to SEA unassigned empty page */
ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
@@ -1043,7 +1198,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 0U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, 0U, 0U, HOST_ARG2_INDEX);
if (((esr & ISS_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
ERROR("Rec0 incorrect ESR=0x%lx\n", esr);
goto destroy_realm;
@@ -1059,7 +1214,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 1U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, 0U, 1U, HOST_ARG2_INDEX);
if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
ERROR("Rec1 incorrect ESR=0x%lx\n", esr);
goto destroy_realm;
@@ -1091,7 +1246,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 2U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, 0U, 2U, HOST_ARG2_INDEX);
if (((esr & ISS_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
ERROR("Rec2 incorrect ESR=0x%lx\n", esr);
goto destroy_realm;
@@ -1107,7 +1262,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 3U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, 0U, 3U, HOST_ARG2_INDEX);
if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
ERROR("Rec3 incorrect ESR=0x%lx\n", esr);
}
@@ -1159,7 +1314,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1176,8 +1331,8 @@
}
run = (struct rmi_rec_run *)realm.run[0];
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base_ipa);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base_ipa);
/* Rec0 expect SEA in realm due to IA unprotected IPA page */
ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
@@ -1188,7 +1343,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 0U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG2_INDEX);
if (((esr & ISS_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
ERROR("Rec0 incorrect ESR=0x%lx\n", esr);
goto destroy_realm;
@@ -1203,8 +1358,8 @@
if (!ret1 || (run->exit.hpfar >> 4U) != (base_ipa >> PAGE_SIZE_SHIFT)
|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
- || ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
- || ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) < FSC_L0_TRANS_FAULT)
+ || ((run->exit.esr & ISS_DFSC_MASK) > FSC_L3_TRANS_FAULT)
|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U)) {
ERROR("Rec1 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
run->exit.exit_reason, ret1, run->exit.hpfar, run->exit.esr);
@@ -1224,7 +1379,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 1U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG2_INDEX);
if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
ERROR("Rec1 incorrect ESR=0x%lx\n", esr);
goto destroy_realm;
@@ -1267,14 +1422,14 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+ feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
return TEST_RESULT_FAIL;
}
/* Enable FEAT_DIT on Host */
write_dit(DIT_BIT);
for (unsigned int i = 0; i < MAX_REC_COUNT; i++) {
- host_shared_data_set_host_val(&realm, i, HOST_ARG1_INDEX, 10U);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, i, HOST_ARG1_INDEX, 10U);
ret1 = host_enter_realm_execute(&realm, REALM_DIT_CHECK_CMD,
RMI_EXIT_HOST_CALL, i);
if (!ret1) {
@@ -1497,7 +1652,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 2U)) {
+ feature_flag, sl, rec_flag, 2U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1683,7 +1838,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
goto destroy_realm;
}
@@ -1729,7 +1884,7 @@
feature_flag = INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 0x2CU);
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, RTT_MIN_LEVEL, rec_flag, 4U)) {
+ feature_flag, RTT_MIN_LEVEL, rec_flag, 4U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -1738,8 +1893,8 @@
/* IPA outside Realm space */
base_ipa = base | (1UL << (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ,
realm.rmm_feat_reg0) + 1U));
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base_ipa);
- host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG1_INDEX, base_ipa);
INFO("base_ipa=0x%lx\n", base_ipa);
@@ -1755,7 +1910,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 0U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG2_INDEX);
if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA)
|| (EC_BITS(esr) != EC_DABORT_CUR_EL)
|| ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) == 0U)) {
@@ -1775,7 +1930,7 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 1U, HOST_ARG2_INDEX);
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 1U, HOST_ARG2_INDEX);
if (((esr & ISS_DFSC_MASK) != IFSC_NO_WALK_SEA)
|| (EC_BITS(esr) != EC_IABORT_CUR_EL)
|| ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) == 0U)) {
@@ -1790,8 +1945,8 @@
INFO("base_ipa=0x%lx\n", base_ipa);
- host_shared_data_set_host_val(&realm, 2U, HOST_ARG1_INDEX, base_ipa);
- host_shared_data_set_host_val(&realm, 3U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 2U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 3U, HOST_ARG1_INDEX, base_ipa);
run = (struct rmi_rec_run *)realm.run[2];
@@ -1805,8 +1960,8 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 2U, HOST_ARG2_INDEX);
- if (((esr & ISS_DFSC_MASK) != DFSC_L0_ADR_SIZE_FAULT)
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 2U, HOST_ARG2_INDEX);
+ if (((esr & ISS_DFSC_MASK) != FSC_L0_ADR_SIZE_FAULT)
|| (EC_BITS(esr) != EC_DABORT_CUR_EL)
|| ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U)) {
ERROR("Rec2 incorrect ESR=0x%lx\n", esr);
@@ -1825,8 +1980,8 @@
}
/* get ESR set by Realm exception handler */
- esr = host_shared_data_get_realm_val(&realm, 3U, HOST_ARG2_INDEX);
- if (((esr & ISS_IFSC_MASK) != IFSC_L0_ADR_SIZE_FAULT)
+ esr = host_shared_data_get_realm_val(&realm, PRIMARY_PLANE_ID, 3U, HOST_ARG2_INDEX);
+ if (((esr & ISS_IFSC_MASK) != FSC_L0_ADR_SIZE_FAULT)
|| (EC_BITS(esr) != EC_IABORT_CUR_EL)
|| ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U)) {
ERROR("Rec3 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
@@ -1876,7 +2031,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2033,7 +2188,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2208,7 +2363,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2323,7 +2478,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2436,7 +2591,7 @@
}
if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
ERROR("Realm creation failed\n");
goto destroy_realm;
}
@@ -2552,7 +2707,7 @@
if (!host_create_activate_realm_payload(&realm,
(u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, &rec_flag, 1U)) {
+ feature_flag, sl, &rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -2572,10 +2727,10 @@
return TEST_RESULT_FAIL;
}
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+ host_shared_data_set_host_val(&realm, 0U, 0U, HOST_ARG1_INDEX, base);
for (unsigned int i = 0U; i < 2U; i++) {
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG2_INDEX,
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG2_INDEX,
(unsigned long)i);
/* Rec0 expect IA due to SEA unassigned empty page */
@@ -2612,7 +2767,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
@@ -2653,7 +2808,7 @@
}
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
index 02c5d0f..235e093 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
@@ -39,7 +39,7 @@
/* Initialise Realm payload */
if (!host_create_activate_realm_payload(realm,
(u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U)) {
+ feature_flag, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_spm.c b/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
index 8649014..e81d82d 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
@@ -203,7 +203,9 @@
* Spin Realm payload for REALM_TIME_SLEEP ms, This ensures secure wdog
* timer triggers during this time.
*/
- host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, REALM_TIME_SLEEP);
+ host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U,
+ HOST_ARG1_INDEX, REALM_TIME_SLEEP);
+
host_enter_realm_execute(&realm, REALM_SLEEP_CMD, RMI_EXIT_FIQ, 0U);
/*
diff --git a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
index 054e774..09482f2 100644
--- a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
@@ -106,23 +106,3 @@
return TEST_RESULT_SUCCESS;
}
-
-bool spm_core_sp_init(ffa_id_t sp_id)
-{
- /*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (sp_id != SP_ID(1)) {
- uint32_t core_pos = get_current_core_id();
- struct ffa_value ret = ffa_run(sp_id, core_pos);
-
- if (ffa_func_id(ret) != FFA_MSG_WAIT) {
- ERROR("Failed to run SP%x on core %u\n",
- sp_id, core_pos);
- return false;
- }
- }
-
- return true;
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 1f8e81c..4686e4c 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -185,19 +185,6 @@
}
/*
- * Secure Partitions beyond the first SP only have their first
- * EC (or vCPU0) woken up at boot time by the SPMC.
- * Other ECs need one round of ffa_run to reach the message loop.
- */
- ffa_ret = ffa_run(SP_ID(2), core_pos);
- if (ffa_func_id(ffa_ret) != FFA_MSG_WAIT) {
- ERROR("Failed to run SP%x on core %u\n", SP_ID(2),
- core_pos);
- ret = TEST_RESULT_FAIL;
- goto out;
- }
-
- /*
* Send a direct message request to SP2 (MP SP) from current physical
* CPU. The SPMC uses the MP pinned context corresponding to the
* physical CPU emitting the request.
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index 4b61565..fe04751 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -981,14 +981,6 @@
per_vcpu_receiver, core_pos);
/*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (!spm_core_sp_init(per_vcpu_receiver)) {
- goto out;
- }
-
- /*
* Request to get notifications sent to the respective vCPU.
* Check also if NPI was handled by the receiver. It should have been
* pended at notifications set, in the respective vCPU.
@@ -1002,6 +994,8 @@
result = TEST_RESULT_SUCCESS;
out:
+ INFO("Request get per-vCPU notification to %x, core: %u.\n",
+ per_vcpu_receiver, core_pos);
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1016,17 +1010,8 @@
VERBOSE("Request SP %x to enable NPI in core %u\n",
per_vcpu_receiver, core_pos);
- /*
- * Secure Partitions secondary ECs need one round of ffa_run to reach
- * the message loop.
- */
- if (!spm_core_sp_init(per_vcpu_receiver)) {
- goto out;
- }
-
result = TEST_RESULT_SUCCESS;
-out:
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1083,6 +1068,7 @@
per_vcpu_receiver = receiver;
per_vcpu_sender = sender;
+ INFO("Execute npi_enable_per_vcpu_on_handler\n");
/* Boot all cores and enable the NPI in all of them. */
if (spm_run_multi_core_test(
(uintptr_t)npi_enable_per_vcpu_on_handler,
@@ -1134,6 +1120,7 @@
result = TEST_RESULT_FAIL;
}
+ INFO("Execute request_notification_get_per_vcpu_on_handler\n");
/*
* Bring up all the cores, and request the receiver to get notifications
* in each one of them.
@@ -1145,6 +1132,7 @@
}
out:
+ INFO("UNbind message on CPU:%lx\n", read_mpidr_el1());
/* As a clean-up, unbind notifications. */
if (!request_notification_unbind(receiver, receiver,
sender,
@@ -1153,6 +1141,7 @@
result = TEST_RESULT_FAIL;
}
+ INFO("Execute npi_disable_per_vcpu_on_handler\n");
/* Boot all cores and DISABLE the NPI in all of them. */
if (spm_run_multi_core_test(
(uintptr_t)npi_disable_per_vcpu_on_handler,
@@ -1187,10 +1176,6 @@
VERBOSE("Getting per-vCPU notifications from %x, core: %u.\n",
per_vcpu_receiver, core_pos);
- if (!spm_core_sp_init(per_vcpu_sender)) {
- goto out;
- }
-
if (!notification_get_and_validate(per_vcpu_receiver,
FFA_NOTIFICATION(core_pos), 0,
core_pos,
@@ -1199,7 +1184,6 @@
result = TEST_RESULT_FAIL;
}
-out:
/* Tell the lead CPU that the calling CPU has completed the test. */
tftf_send_event(&per_vcpu_finished[core_pos]);
@@ -1498,10 +1482,6 @@
unsigned int core_pos = get_current_core_id();
test_result_t result = TEST_RESULT_FAIL;
- if (!spm_core_sp_init(per_vcpu_sender)) {
- goto out;
- }
-
if (!notification_set(per_vcpu_receiver, per_vcpu_sender,
FFA_NOTIFICATIONS_FLAG_DELAY_SRI |
FFA_NOTIFICATIONS_FLAG_PER_VCPU |
diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
index eae5ccd..3f0c9cb 100644
--- a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
+++ b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
@@ -23,7 +23,7 @@
#define TEST_SPURIOUS_ITERATIONS_COUNT 1000000
#define TEST_SPI_ID (MIN_SPI_ID + 2)
-#define CPU_TARGET_FIELD ((1 << PLATFORM_CORE_COUNT) - 1)
+#define CPU_TARGET_FIELD 0xFF
static event_t cpu_ready[PLATFORM_CORE_COUNT];
static volatile int requested_irq_received[PLATFORM_CORE_COUNT];
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 7375633..9358c49 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -34,4 +34,5 @@
runtime_services/arm_arch_svc/smccc_arch_workaround_2.c \
runtime_services/arm_arch_svc/smccc_arch_workaround_3.c \
runtime_services/arm_arch_svc/smccc_feature_availability.c \
+ runtime_services/arm_arch_svc/smccc_arch_workaround_4.c \
)
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 51aa27c..632e231 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -49,6 +49,7 @@
<testcase name="SMCCC_ARCH_WORKAROUND_1 test" function="test_smccc_arch_workaround_1" />
<testcase name="SMCCC_ARCH_WORKAROUND_2 test" function="test_smccc_arch_workaround_2" />
<testcase name="SMCCC_ARCH_WORKAROUND_3 test" function="test_smccc_arch_workaround_3" />
+ <testcase name="SMCCC_ARCH_WORKAROUND_4 test" function="test_smccc_arch_workaround_4" />
<testcase name="SMCCC_ARCH_SOC_ID test" function="test_smccc_arch_soc_id" />
<testcase name="SMCCC_ARCH_FEATURE_AVAILABILITY test" function="test_smccc_arch_feature_availability" />
</testsuite>
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index da88701..7cc7866 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -8,6 +8,10 @@
<testsuites>
<testsuite name="Realm payload at EL1" description="Test Realm EL1 framework capabilities" >
+ <testcase name="Realm Planes execution test"
+ function="host_test_realm_create_planes_enter" />
+ <testcase name="Realm Planes register read/write test"
+ function="host_test_realm_create_planes_register_rw" />
<testcase name="Realm EL1 creation and execution test"
function="host_test_realm_create_enter" />
<testcase name="Realm RTT fold unfold test Unassigned Empty"
diff --git a/tftf/tests/tests-smcfuzzing.mk b/tftf/tests/tests-smcfuzzing.mk
index 2834e4e..9218da1 100644
--- a/tftf/tests/tests-smcfuzzing.mk
+++ b/tftf/tests/tests-smcfuzzing.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
+# Copyright (c) 2024, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -11,6 +11,13 @@
SMC_FUZZ_INSTANCE_COUNT ?= 1
SMC_FUZZ_SEEDS ?= $(shell python -c "from random import randint; seeds = [randint(0, 4294967295) for i in range($(SMC_FUZZ_INSTANCE_COUNT))];print(\",\".join(str(x) for x in seeds));")
SMC_FUZZ_CALLS_PER_INSTANCE ?= 100
+# ADDED: which fuzz call to start with per instance
+SMC_FUZZ_CALL_START ?= 0
+SMC_FUZZ_CALL_END ?= $(SMC_FUZZ_CALLS_PER_INSTANCE)
+# ADDED: define whether events should specifically be constrained
+EXCLUDE_FUNCID ?= 0
+CONSTRAIN_EVENTS ?= 0
+INTR_ASSERT ?= 0
# Validate SMC fuzzer parameters
@@ -30,13 +37,47 @@
$(error Number of seeds does not match SMC_FUZZ_INSTANCE_COUNT!)
endif
+# Start must be nonnegative and less than calls per instance
+ifeq ($(shell test $(SMC_FUZZ_CALL_START) -lt 0; echo $$?),0)
+$(error SMC_FUZZ_CALL_START must be nonnegative!)
+endif
+
+ifeq ($(shell test $(SMC_FUZZ_CALL_START) -gt $(shell expr $(SMC_FUZZ_CALLS_PER_INSTANCE) - 1); echo $$?),0)
+$(error SMC_FUZZ_CALL_START must be less than SMC_FUZZ_CALLS_PER_INSTANCE!)
+endif
+
+# End must be greater than start and less than or equal to calls per instance
+ifneq ($(shell test $(SMC_FUZZ_CALL_START) -lt $(SMC_FUZZ_CALL_END); echo $$?),0)
+$(error SMC_FUZZ_CALL_END must be greater than SMC_FUZZ_CALL_START!)
+endif
+
+ifeq ($(shell test $(SMC_FUZZ_CALL_END) -gt $(SMC_FUZZ_CALLS_PER_INSTANCE); echo $$?),0)
+$(error SMC_FUZZ_CALL_END must not be greater than SMC_FUZZ_CALLS_PER_INSTANCE!)
+endif
+
+
# Add definitions to TFTF_DEFINES so they can be used in the code
$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_SEEDS))
$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_INSTANCE_COUNT))
$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_CALLS_PER_INSTANCE))
+ifeq ($(SMC_FUZZER_DEBUG),1)
+$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZER_DEBUG))
+endif
ifeq ($(MULTI_CPU_SMC_FUZZER),1)
$(eval $(call add_define,TFTF_DEFINES,MULTI_CPU_SMC_FUZZER))
endif
+$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_SANITY_LEVEL))
+$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_CALL_START))
+$(eval $(call add_define,TFTF_DEFINES,SMC_FUZZ_CALL_END))
+$(eval $(call add_define,TFTF_DEFINES,CONSTRAIN_EVENTS))
+$(eval $(call add_define,TFTF_DEFINES,EXCLUDE_FUNCID))
+$(eval $(call add_define,TFTF_DEFINES,INTR_ASSERT))
+
+TESTS_SOURCES += \
+ $(addprefix tftf/tests/runtime_services/standard_service/sdei/system_tests/, \
+ sdei_entrypoint.S \
+ test_sdei.c \
+ )
TESTS_SOURCES += \
$(addprefix smc_fuzz/src/, \
@@ -47,4 +88,6 @@
sdei_fuzz_helper.c \
tsp_fuzz_helper.c \
nfifo.c \
+ constraint.c \
+ vendor_fuzz_helper.c \
)