Merge "test(psci): add test to validate "psci_is_last_cpu_to_idle_at_pwrlvl""
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/common/test_helpers.h b/include/common/test_helpers.h
index 124cc4e..8ca4cdf 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -431,6 +431,13 @@
} \
} while (false)
+#define SKIP_TEST_IF_FEAT_MPAM_NOT_SUPPORTED() \
+ do { \
+ if (is_feat_mpam_supported() == false) { \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false) \
+
/* Helper macro to verify if system suspend API is supported */
#define is_psci_sys_susp_supported() \
(tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND) \
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index f0d1398..1d5e75a 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -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)
@@ -1167,6 +1171,10 @@
#define PMSELR_EL0_SEL_SHIFT U(0)
#define PMSELR_EL0_SEL_MASK U(0x1f)
+/* PMINTENSET_EL1 definitions */
+#define PMINTENSET_EL1_C_BIT (U(1) << 31)
+#define PMINTENSET_EL1_P_BIT(x) (U(1) << x)
+
/* PMU event counter ID definitions */
#define PMU_EV_PC_WRITE_RETIRED U(0x000C)
@@ -1701,4 +1709,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/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 35d2454..da1794d 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -522,6 +522,9 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(mpamidr_el1, MPAMIDR_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam0_el1, MPAM0_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam1_el1, MPAM1_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(scxtnum_el2, SCXTNUM_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(scxtnum_el1, SCXTNUM_EL1)
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/host_realm_managment/host_realm_helper.h b/include/runtime_services/host_realm_managment/host_realm_helper.h
index 6909a4e..6ea9b72 100644
--- a/include/runtime_services/host_realm_managment/host_realm_helper.h
+++ b/include/runtime_services/host_realm_managment/host_realm_helper.h
@@ -50,7 +50,13 @@
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_pmu.h b/include/runtime_services/host_realm_managment/host_realm_pmu.h
index 844bb29..c7f5fab 100644
--- a/include/runtime_services/host_realm_managment/host_realm_pmu.h
+++ b/include/runtime_services/host_realm_managment/host_realm_pmu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -23,7 +23,23 @@
#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;
+} __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 00435b0..6394fb6 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -582,15 +582,6 @@
#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
@@ -787,7 +778,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 {
@@ -817,7 +812,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 */
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..763306f 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -36,14 +36,17 @@
/* 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
*/
enum realm_cmd {
REALM_SLEEP_CMD = 1U,
REALM_LOOP_CMD,
+ REALM_MPAM_ACCESS,
+ REALM_MPAM_PRESENT,
REALM_MULTIPLE_REC_PSCI_DENIED_CMD,
REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
REALM_GET_RSI_VERSION,
@@ -53,7 +56,8 @@
REALM_PMU_COUNTER,
REALM_PMU_EVENT,
REALM_PMU_PRESERVE,
- REALM_PMU_INTERRUPT,
+ REALM_PMU_CYCLE_INTERRUPT,
+ REALM_PMU_EVENT_INTERRUPT,
REALM_REQ_FPU_FILL_CMD,
REALM_REQ_FPU_CMP_CMD,
REALM_SET_RIPAS_CMD,
@@ -73,7 +77,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 +88,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 +107,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 +144,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 +166,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/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/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 a9b2f7c..c5af1be 100644
--- a/realm/include/realm_helpers.h
+++ b/realm/include/realm_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -8,8 +8,24 @@
#ifndef REALM_HELPERS_H
#define REALM_HELPERS_H
+#include <realm_rsi.h>
+
/* Generate 64-bit random number */
unsigned long long realm_rand64(void);
+
+/* Reset the undefined aborts counter */
+void realm_reset_undef_abort_count(void);
+
+/* Return the undefined aborts counter value */
+unsigned int realm_get_undef_abort_count(void);
+
+/*
+ * Sync exception handler.
+ * If the exception is an undefined abort, it increases the value
+ * of the abort counter and returns 'true'. Otherwise, it returns 'false'
+ */
+bool realm_sync_exception_handler(void);
+
/*
* Function to enter Aux Plane from Primary Plane
* arg1 == plane index
@@ -21,8 +37,19 @@
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 33e8fcf..06f857f 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -270,6 +270,12 @@
*/
#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
@@ -321,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,
@@ -342,7 +345,7 @@
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);
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index 2c1d3a1..6c1e6c3 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -12,7 +12,7 @@
bool test_pmuv3_counter(void);
bool test_pmuv3_event_works_realm(void);
bool test_pmuv3_rmm_preserves(void);
-bool test_pmuv3_overflow_interrupt(void);
+bool test_pmuv3_overflow_interrupt(bool cycle_cnt);
bool test_realm_pauth_set_cmd(void);
bool test_realm_pauth_check_cmd(void);
bool test_realm_pauth_fault(void);
@@ -30,6 +30,7 @@
bool test_realm_sctlr2_ease(void);
bool test_realm_attestation(void);
bool test_realm_attestation_fault(void);
+bool test_realm_mpam_undef_abort(void);
#endif /* REALM_TESTS_H */
diff --git a/realm/realm.mk b/realm/realm.mk
index f59387c..6281779 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -37,14 +37,17 @@
realm_plane.c \
realm_pmuv3.c \
realm_psci.c \
+ realm_psi.c \
realm_rsi.c \
realm_shared_data.c \
realm_simd.c \
+ realm_mpam.c \
)
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..f11e2f3 100644
--- a/realm/realm_helpers.c
+++ b/realm/realm_helpers.c
@@ -1,14 +1,69 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <debug.h>
#include <stdlib.h>
+#include <realm_helpers.h>
+#include <realm_psi.h>
+#include <realm_rsi.h>
+#include <smccc.h>
+
+static unsigned int volatile realm_got_undef_abort;
+
/* Generate 64-bit random number */
unsigned long long realm_rand64(void)
{
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];
+}
+
+bool realm_sync_exception_handler(void)
+{
+ uint64_t esr_el1 = read_esr_el1();
+
+ if (EC_BITS(esr_el1) == EC_UNKNOWN) {
+ realm_printf("received undefined abort. "
+ "ESR_EL1: 0x%llx ELR_EL1: 0x%llx\n",
+ esr_el1, read_elr_el1());
+ realm_got_undef_abort++;
+ }
+
+ return true;
+}
+
+void realm_reset_undef_abort_count(void)
+{
+ realm_got_undef_abort = 0U;
+}
+
+unsigned int realm_get_undef_abort_count(void)
+{
+ return realm_got_undef_abort;
+}
diff --git a/realm/realm_mpam.c b/realm/realm_mpam.c
new file mode 100644
index 0000000..913e451
--- /dev/null
+++ b/realm/realm_mpam.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <sync.h>
+#include <realm_helpers.h>
+
+/* Check if Realm gets undefined abort when it access MPAM registers */
+bool test_realm_mpam_undef_abort(void)
+{
+ realm_reset_undef_abort_count();
+
+ /* Install exception handler to catch undefined abort */
+ register_custom_sync_exception_handler(realm_sync_exception_handler);
+ write_mpam0_el1(0UL);
+ unregister_custom_sync_exception_handler();
+
+ return (realm_get_undef_abort_count() != 0UL);
+}
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 3339b9a..d364aa0 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -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,19 @@
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_MPAM_ACCESS:
+ test_succeed = test_realm_mpam_undef_abort();
+ break;
+ case REALM_MPAM_PRESENT:
+ /* FEAT_MPAM must be hidden to the Realm */
+ test_succeed = !is_feat_mpam_supported();
+ break;
case REALM_MULTIPLE_REC_PSCI_DENIED_CMD:
test_succeed = test_realm_multiple_rec_psci_denied_cmd();
break;
@@ -323,8 +440,11 @@
case REALM_PMU_PRESERVE:
test_succeed = test_pmuv3_rmm_preserves();
break;
- case REALM_PMU_INTERRUPT:
- test_succeed = test_pmuv3_overflow_interrupt();
+ case REALM_PMU_CYCLE_INTERRUPT:
+ test_succeed = test_pmuv3_overflow_interrupt(true);
+ break;
+ case REALM_PMU_EVENT_INTERRUPT:
+ test_succeed = test_pmuv3_overflow_interrupt(false);
break;
case REALM_REQ_FPU_FILL_CMD:
fpu_state_write_rand(&rl_fpu_state_write);
@@ -381,8 +501,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
index ef1e0ab..c7225ed 100644
--- a/realm/realm_plane.c
+++ b/realm/realm_plane.c
@@ -11,10 +11,22 @@
#include <debug.h>
#include <host_realm_helper.h>
+#include <realm_psi.h>
#include <realm_rsi.h>
#include <sync.h>
-bool is_plane0;
+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)
{
@@ -23,8 +35,10 @@
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;
}
}
@@ -37,23 +51,91 @@
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 */
-static bool handle_plane_exit(u_register_t plane_index,
+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 true;
+ return PSI_RETURN_TO_PN;
}
- return false;
+
+ /* 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;
}
-static bool plane_common_init(u_register_t plane_index,
+bool plane_common_init(u_register_t plane_index,
u_register_t perm_index,
u_register_t base,
rsi_plane_run *run)
@@ -79,16 +161,10 @@
rsi_plane_run *run)
{
u_register_t ret;
- bool ret1;
-
- ret1 = plane_common_init(plane_index, perm_index, base, run);
- if (!ret1) {
- return ret1;
- }
run->enter.flags = flags;
- while (ret1) {
+ 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);
@@ -101,8 +177,11 @@
run->exit.hpfar,
run->exit.far);
- ret1 = handle_plane_exit(plane_index, perm_index, run);
+ ret = handle_plane_exit(plane_index, perm_index, run);
+
+ if (ret != PSI_RETURN_TO_PN) {
+ return true;
+ }
}
- return true;
}
diff --git a/realm/realm_pmuv3.c b/realm/realm_pmuv3.c
index 0d4782a..620daf3 100644
--- a/realm/realm_pmuv3.c
+++ b/realm/realm_pmuv3.c
@@ -1,9 +1,11 @@
/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <stdlib.h>
+
#include <arch_helpers.h>
#include <arm_arch_svc.h>
#include <debug.h>
@@ -19,24 +21,23 @@
#define PMU_EVT_MEM_ACCESS 0x13
#define NOP_REPETITIONS 50
-#define MAX_COUNTERS 32
#define PRE_OVERFLOW ~(0xF)
-#define DELAY_MS 3000ULL
+#define DELAY_MS 3000UL
-static inline void read_all_counters(u_register_t *array, int impl_ev_ctrs)
+static inline void read_all_counters(u_register_t *array, unsigned int num_cnts)
{
array[0] = read_pmccntr_el0();
- for (unsigned int i = 0U; i < impl_ev_ctrs; i++) {
+ for (unsigned int i = 0U; i < num_cnts; i++) {
array[i + 1] = read_pmevcntrn_el0(i);
}
}
-static inline void read_all_counter_configs(u_register_t *array, int impl_ev_ctrs)
+static inline void read_all_counter_configs(u_register_t *array, unsigned int num_cnts)
{
array[0] = read_pmccfiltr_el0();
- for (unsigned int i = 0U; i < impl_ev_ctrs; i++) {
+ for (unsigned int i = 0U; i < num_cnts; i++) {
array[i + 1] = read_pmevtypern_el0(i);
}
}
@@ -107,7 +108,7 @@
isb();
}
-static inline void enable_event_counter(int ctr_num)
+static inline void enable_event_counter(unsigned int ctr_num)
{
/*
* Set PMEVTYPER_EL0.U != PMEVTYPER_EL0.RLU
@@ -154,27 +155,21 @@
disable_counting();
clear_counters();
- realm_printf("counted from %lu to %lu\n",
- ccounter_start, ccounter_end);
- if (ccounter_start != ccounter_end) {
- return true;
- }
- return false;
+ realm_printf("cycle counter counted from %lu to %lu\n",
+ ccounter_start, ccounter_end);
+ return (ccounter_start != ccounter_end);
}
/* Test if max counter available is same as that programmed by host */
bool test_pmuv3_counter(void)
{
- uint64_t num_cnts, num_cnts_host;
+ unsigned int num_cnts, num_cnts_host;
num_cnts_host = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
num_cnts = GET_PMU_CNT;
- realm_printf("CPU=%u num_cnts=%lu num_cnts_host=%lu\n", read_mpidr_el1() & MPID_MASK,
+ realm_printf("CPU=%u num_cnts=%u num_cnts_host=%u\n", read_mpidr_el1() & MPID_MASK,
num_cnts, num_cnts_host);
- if (num_cnts == num_cnts_host) {
- return true;
- }
- return false;
+ return (num_cnts == num_cnts_host);
}
/*
@@ -184,28 +179,31 @@
{
u_register_t evcounter_start;
u_register_t evcounter_end;
+ unsigned int num_cnts = GET_PMU_CNT;
+ unsigned int ctr_num;
- if (GET_PMU_CNT == 0) {
- realm_printf("no event counters implemented\n");
- return false;
- }
+ /* Seed the random number generator */
+ srand((unsigned int)read_cntpct_el0());
+
+ /* Select a random number of event counter */
+ ctr_num = (unsigned int)rand() % num_cnts;
pmu_reset();
- enable_event_counter(0);
+ enable_event_counter(ctr_num);
enable_counting();
/*
* If any is enabled it will be in the first range.
*/
- evcounter_start = read_pmevcntrn_el0(0);
+ evcounter_start = read_pmevcntrn_el0(ctr_num);
execute_nops();
disable_counting();
- evcounter_end = read_pmevcntrn_el0(0);
+ evcounter_end = read_pmevcntrn_el0(ctr_num);
clear_counters();
- realm_printf("counted from %lu to %lu\n",
- evcounter_start, evcounter_end);
+ realm_printf("event counter #%u counted from %lu to %lu\n",
+ ctr_num, evcounter_start, evcounter_end);
if (evcounter_start != evcounter_end) {
return true;
}
@@ -223,30 +221,38 @@
u_register_t ctr_end[MAX_COUNTERS] = {0};
u_register_t ctr_cfg_end[MAX_COUNTERS] = {0};
u_register_t pmu_cfg_end[3];
- unsigned int impl_ev_ctrs = GET_PMU_CNT;
+ unsigned int num_cnts = GET_PMU_CNT;
- realm_printf("testing %u event counters\n", impl_ev_ctrs);
+ if (num_cnts == 0U) {
+ realm_printf("testing cycle counter\n");
+ } else {
+ realm_printf("testing %u event counters\n", num_cnts);
+ }
pmu_reset();
- /* Pretend counters have just been used */
+ /* Pretend all counters have just been used */
enable_cycle_counter();
- enable_event_counter(0);
+
+ for (unsigned int i = 0U; i < num_cnts; i++) {
+ enable_event_counter(i);
+ }
+
enable_counting();
execute_nops();
disable_counting();
/* Get before reading */
- read_all_counters(ctr_start, impl_ev_ctrs);
- read_all_counter_configs(ctr_cfg_start, impl_ev_ctrs);
+ read_all_counters(ctr_start, num_cnts);
+ read_all_counter_configs(ctr_cfg_start, num_cnts);
read_all_pmu_configs(pmu_cfg_start);
/* Give RMM a chance to scramble everything */
(void)rsi_get_version(RSI_ABI_VERSION_VAL);
/* Get after reading */
- read_all_counters(ctr_end, impl_ev_ctrs);
- read_all_counter_configs(ctr_cfg_end, impl_ev_ctrs);
+ read_all_counters(ctr_end, num_cnts);
+ read_all_counter_configs(ctr_cfg_end, num_cnts);
read_all_pmu_configs(pmu_cfg_end);
if (memcmp(ctr_start, ctr_end, sizeof(ctr_start)) != 0) {
@@ -270,10 +276,11 @@
return true;
}
-bool test_pmuv3_overflow_interrupt(void)
+bool test_pmuv3_overflow_interrupt(bool cycle_cnt)
{
unsigned long priority_bits, priority;
- uint64_t delay_time = DELAY_MS;
+ unsigned long delay_time = DELAY_MS;
+ unsigned int num_cnts, ctr_num;
pmu_reset();
@@ -293,13 +300,30 @@
/* Enable IRQ */
enable_irq();
- write_pmevcntrn_el0(0, PRE_OVERFLOW);
- enable_event_counter(0);
+ if (cycle_cnt) {
+ write_pmccntr_el0(PRE_OVERFLOW);
+ enable_cycle_counter();
- /* Enable interrupt on event counter #0 */
- write_pmintenset_el1((1UL << 0));
+ /* Enable interrupt on cycle counter */
+ write_pmintenset_el1(PMINTENSET_EL1_C_BIT);
+ realm_printf("waiting for PMU cycle counter vIRQ...\n");
+ } else {
+ num_cnts = GET_PMU_CNT;
- realm_printf("waiting for PMU vIRQ...\n");
+ /* Seed the random number generator */
+ srand((unsigned int)read_cntpct_el0());
+
+ /* Select a random number of event counter */
+ ctr_num = (unsigned int)rand() % num_cnts;
+
+ write_pmevcntrn_el0(ctr_num, PRE_OVERFLOW);
+ enable_event_counter(ctr_num);
+
+ /* Enable interrupt on event counter */
+ write_pmintenset_el1(PMINTENSET_EL1_P_BIT(ctr_num));
+ realm_printf("waiting for PMU event counter #%u vIRQ...\n",
+ ctr_num);
+ }
enable_counting();
execute_nops();
@@ -309,7 +333,7 @@
* Performance Monitors Interrupt Enable Set register
* as part of handling the overflow interrupt.
*/
- while ((read_pmintenset_el1() != 0UL) && (delay_time != 0ULL)) {
+ while ((read_pmintenset_el1() != 0UL) && (delay_time != 0UL)) {
--delay_time;
}
@@ -318,14 +342,13 @@
pmu_reset();
- if (delay_time == 0ULL) {
- realm_printf("PMU vIRQ %sreceived in %llums\n", "not ",
+ if (delay_time == 0UL) {
+ realm_printf("PMU vIRQ %sreceived in %lums\n", "not ",
DELAY_MS);
return false;
}
- realm_printf("PMU vIRQ %sreceived in %llums\n", "",
+ realm_printf("PMU vIRQ %sreceived in %lums\n", "",
DELAY_MS - delay_time);
-
return true;
}
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 1c6fc8e..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>
@@ -31,30 +32,18 @@
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 */
@@ -210,3 +199,28 @@
{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/realm/realm_simd.c b/realm/realm_simd.c
index 2eb3eab..0ff1710 100644
--- a/realm/realm_simd.c
+++ b/realm/realm_simd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,9 +9,11 @@
#include <assert.h>
#include <debug.h>
#include <stdlib.h>
+
#include <sync.h>
#include <lib/extensions/fpu.h>
#include <lib/extensions/sve.h>
+#include <realm_helpers.h>
#include <host_realm_simd.h>
#include <host_shared_data.h>
@@ -34,8 +36,6 @@
static fpu_cs_regs_t rl_fpu_cs_regs_write;
static fpu_cs_regs_t rl_fpu_cs_regs_read;
-static int volatile realm_got_undef_abort;
-
/* Returns the maximum supported VL. This test is called only by sve Realm */
bool test_realm_sve_rdvl(void)
{
@@ -188,35 +188,17 @@
return rc;
}
-static bool realm_sync_exception_handler(void)
-{
- uint64_t esr_el1 = read_esr_el1();
-
- if (EC_BITS(esr_el1) == EC_UNKNOWN) {
- realm_printf("received undefined abort. "
- "esr_el1: 0x%llx elr_el1: 0x%llx\n",
- esr_el1, read_elr_el1());
- realm_got_undef_abort++;
- }
-
- return true;
-}
-
/* Check if Realm gets undefined abort when it accesses SVE functionality */
bool test_realm_sve_undef_abort(void)
{
- realm_got_undef_abort = 0UL;
+ realm_reset_undef_abort_count();
- /* install exception handler to catch undef abort */
+ /* Install exception handler to catch undefined abort */
register_custom_sync_exception_handler(&realm_sync_exception_handler);
(void)sve_rdvl_1();
unregister_custom_sync_exception_handler();
- if (realm_got_undef_abort == 0UL) {
- return false;
- }
-
- return true;
+ return (realm_get_undef_abort_count() != 0U);
}
/* Reads and returns the ID_AA64PFR1_EL1 and ID_AA64SMFR0_EL1 registers */
@@ -240,16 +222,12 @@
/* Check if Realm gets undefined abort when it access SME functionality */
bool test_realm_sme_undef_abort(void)
{
- realm_got_undef_abort = 0UL;
+ realm_reset_undef_abort_count();
- /* install exception handler to catch undef abort */
+ /* Install exception handler to catch undefined abort */
register_custom_sync_exception_handler(&realm_sync_exception_handler);
(void)read_svcr();
unregister_custom_sync_exception_handler();
- if (realm_got_undef_abort == 0UL) {
- return false;
- }
-
- return true;
+ return (realm_get_undef_abort_count() != 0U);
}
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/plat/arm/fvp/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
index 1c01a9f..0f6c23d 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
@@ -24,7 +24,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7100000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <1>;
messaging-method = <3>; /* Direct messaging only */
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
index 946301d..d1ffa2f 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts
@@ -24,7 +24,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7200000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <2>;
notification-support;
diff --git a/spm/cactus/plat/arm/tc/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/tc/fdts/cactus-secondary.dts
index 839fb82..aa48e29 100644
--- a/spm/cactus/plat/arm/tc/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/tc/fdts/cactus-secondary.dts
@@ -22,7 +22,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0xfe100000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <1>;
messaging-method = <3>; /* Direct messaging only */
diff --git a/spm/cactus/plat/arm/tc/fdts/cactus-tertiary.dts b/spm/cactus/plat/arm/tc/fdts/cactus-tertiary.dts
index 1db2c1e..145be36 100644
--- a/spm/cactus/plat/arm/tc/fdts/cactus-tertiary.dts
+++ b/spm/cactus/plat/arm/tc/fdts/cactus-tertiary.dts
@@ -22,7 +22,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0xfe200000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <2>;
messaging-method = <3>; /* Direct messaging only */
diff --git a/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel0.dts b/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel0.dts
index 7bf7d91..f885c5f 100644
--- a/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel0.dts
+++ b/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel0.dts
@@ -21,7 +21,7 @@
exception-level = <1>; /* S-EL0 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7600000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
boot-order = <3>;
messaging-method = <3>; /* Direct messaging only */
diff --git a/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel1.dts b/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel1.dts
index a4d26ef..1dfca01 100644
--- a/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel1.dts
+++ b/spm/ivy/app/plat/arm/fvp/fdts/ivy-sel1.dts
@@ -22,7 +22,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7600000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
boot-order = <3>;
messaging-method = <3>; /* Direct messaging only */
/* Non-secure interrupts are signaled by default. */
diff --git a/spm/ivy/app/plat/arm/tc/fdts/ivy-sel0.dts b/spm/ivy/app/plat/arm/tc/fdts/ivy-sel0.dts
index 7d333a6..1dd3b61 100644
--- a/spm/ivy/app/plat/arm/tc/fdts/ivy-sel0.dts
+++ b/spm/ivy/app/plat/arm/tc/fdts/ivy-sel0.dts
@@ -20,7 +20,7 @@
exception-level = <1>; /* S-EL0 */
execution-state = <0>; /* AARCH64 */
load-address = <0xfe280000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
boot-order = <3>;
messaging-method = <3>; /* Direct messaging only */
diff --git a/spm/ivy/app/plat/arm/tc/fdts/ivy-sel1.dts b/spm/ivy/app/plat/arm/tc/fdts/ivy-sel1.dts
index 6503e15..bcb3162 100644
--- a/spm/ivy/app/plat/arm/tc/fdts/ivy-sel1.dts
+++ b/spm/ivy/app/plat/arm/tc/fdts/ivy-sel1.dts
@@ -21,7 +21,7 @@
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0xfe280000>;
- entrypoint-offset = <0x00004000>;
+ entrypoint-offset = <0x00002000>;
boot-order = <3>;
messaging-method = <3>; /* Direct messaging only */
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..31965be 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_pmuv3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -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 | \
@@ -67,9 +65,9 @@
CHECK_PMEV_REG(n, pmevtyper); \
}
-#define WRITE_PMREG(reg, mask) { \
+#define WRITE_PMREG(reg, mask) { \
pmu_ptr->reg = rand64() & mask; \
- write_##reg(pmu_ptr->reg); \
+ write_##reg(pmu_ptr->reg); \
}
#define CHECK_PMREG(reg) { \
@@ -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;
@@ -127,11 +103,15 @@
pmu_ptr->pmintenset_el1 = 0UL;
write_pmintenclr_el1(PMU_CLEAR_ALL);
+ /* Seed the random number generator */
+ srand((unsigned int)read_cntpct_el0());
+
WRITE_PMREG(pmccntr_el0, UINT64_MAX);
WRITE_PMREG(pmccfiltr_el0, PMCCFILTR_EL0_MASK);
pmu_ptr->pmuserenr_el0 = read_pmuserenr_el0();
+ /* Check number of event counters implemented */
if (num_cnts != 0U) {
switch (--num_cnts) {
WRITE_PMEV_REGS(30);
@@ -168,25 +148,30 @@
WRITE_PMEV_REGS(0);
}
- /* Generate a random number between 0 and num_cnts */
+ /* Seed the random number generator */
+ srand((unsigned int)read_cntpct_el0());
+
+ /*
+ * Select a random number of event counter
+ * between 0 and num_cnts - 1
+ */
val = rand() % ++num_cnts;
} else {
- val = 0UL;
+ /* Select the cycle counter, PMCCNTR_EL0 */
+ val = 31UL;
}
pmu_ptr->pmselr_el0 = val;
write_pmselr_el0(val);
-
- pmu_ptr->pmxevcntr_el0 = read_pmxevcntr_el0();
- 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);
@@ -196,9 +181,8 @@
CHECK_PMREG(pmccfiltr_el0);
CHECK_PMREG(pmuserenr_el0);
CHECK_PMREG(pmselr_el0);
- CHECK_PMREG(pmxevcntr_el0);
- CHECK_PMREG(pmxevtyper_el0);
+ /* Check number of event counters implemented */
if (num_cnts != 0UL) {
switch (--num_cnts) {
CHECK_PMEV_REGS(30);
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 3a4121b..e73fe0d 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -45,14 +45,14 @@
* 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);
@@ -63,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,
@@ -129,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;
}
@@ -194,14 +179,9 @@
realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
realm_ptr->pmu_num_ctrs = 0U;
} else {
- value = EXTRACT(FEATURE_PMU_NUM_CTRS, feature_flag);
- if (value != -1) {
- realm_ptr->pmu_num_ctrs = (unsigned int)value;
- } else {
- realm_ptr->pmu_num_ctrs =
- EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
- realm_ptr->rmm_feat_reg0);
- }
+ /* Requested number of event counters */
+ realm_ptr->pmu_num_ctrs = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
+ feature_flag);
}
/* Disable SVE if not required */
@@ -209,11 +189,12 @@
realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_SVE_EN;
realm_ptr->sve_vl = 0U;
} else {
- realm_ptr->sve_vl = EXTRACT(FEATURE_SVE_VL, feature_flag);
+ realm_ptr->sve_vl = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL,
+ feature_flag);
}
/* Requested number of breakpoints */
- value = EXTRACT(FEATURE_NUM_BPS, feature_flag);
+ value = EXTRACT(RMI_FEATURE_REGISTER_0_NUM_BPS, feature_flag);
if (value != 0) {
realm_ptr->num_bps = (unsigned int)value;
} else {
@@ -222,7 +203,7 @@
}
/* Requested number of watchpoints */
- value = EXTRACT(FEATURE_NUM_WPS, feature_flag);
+ value = EXTRACT(RMI_FEATURE_REGISTER_0_NUM_WPS, feature_flag);
if (value != 0) {
realm_ptr->num_wps = (unsigned int)value;
} else {
@@ -433,12 +414,11 @@
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;
}
-
if (test_exit_reason == realm_exit_reason) {
if (realm_exit_reason != RMI_EXIT_HOST_CALL) {
return true;
@@ -500,3 +480,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 5c851a7..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
@@ -482,12 +482,12 @@
return REALM_ERROR;
}
}
- ipa_align = ALIGN_DOWN(map_addr, RTT_MAP_SIZE(level - 1));
- ret = host_rmi_rtt_aux_create(realm->rd, rtt, ipa_align, (u_register_t)level,
+ 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, rtt=0x%lx ret=0x%lx\n",
- "host_realm_rtt_aux_create", rtt, ret);
+ 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;
@@ -551,7 +551,7 @@
level = (long)ulevel;
ret = host_realm_create_rtt_aux_levels(realm, map_addr,
- (u_register_t)level,
+ level,
3U, tree_index);
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, ret=0x%lx line=%u\n",
@@ -1082,6 +1082,9 @@
* 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->num_aux_planes + 1U));
@@ -1340,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;
}
@@ -1651,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,
@@ -1685,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;
}
@@ -1696,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_mpam_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_mpam_tests.c
new file mode 100644
index 0000000..7967828
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_mpam_tests.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+#include <test_helpers.h>
+
+static test_result_t realm_test_feat_mpam(enum realm_cmd cmd)
+{
+ bool ret1, ret2;
+ u_register_t rec_flag[] = {RMI_RUNNABLE};
+ struct realm realm;
+ u_register_t feature_flag = 0UL;
+ long sl = RTT_MIN_LEVEL;
+
+ assert((cmd >= REALM_MPAM_ACCESS) && (cmd <= REALM_MPAM_PRESENT));
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+ SKIP_TEST_IF_FEAT_MPAM_NOT_SUPPORTED();
+
+ if (is_feat_52b_on_4k_2_supported()) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, 0U)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ret1 = host_enter_realm_execute(&realm, cmd, RMI_EXIT_HOST_CALL, 0U);
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret1 || !ret2) {
+ ERROR("%s(): enter=%u destroy=%u\n",
+ __func__, ret1, ret2);
+ return TEST_RESULT_FAIL;
+ }
+
+ return true;
+}
+
+/*
+ * @Test_Aim@ Test that FEAT_MPAM is hidden to the realm
+ */
+test_result_t host_realm_hide_feat_mpam(void)
+{
+ return realm_test_feat_mpam(REALM_MPAM_PRESENT);
+}
+
+/*
+ * @Test_Aim@ Test that access to MPAM registers triggers an undefined abort
+ * taken into the realm.
+ */
+test_result_t host_realm_mpam_undef_abort(void)
+{
+ return realm_test_feat_mpam(REALM_MPAM_ACCESS);
+}
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 151e871..5c3299a 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -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
@@ -37,7 +38,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -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) {
@@ -106,7 +109,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -247,7 +250,7 @@
rec_count = tftf_get_total_cpus_count();
assert(rec_count <= MAX_REC_COUNT);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -351,7 +354,7 @@
rec_count = tftf_get_total_cpus_count();
assert(rec_count <= MAX_REC_COUNT);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -368,7 +371,7 @@
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) {
@@ -489,7 +492,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -510,7 +513,7 @@
}
/* 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,17 +633,19 @@
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;
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+ host_rmi_init_cmp_result();
+
rec_count = tftf_get_total_cpus_count();
assert(rec_count <= MAX_REC_COUNT);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -640,135 +654,157 @@
rec_flag[i] = RMI_RUNNABLE;
}
- /* Get Max PMU counter implemented through RMI_FEATURES */
+ /* Get number of PMU event counters 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();
+ host_set_pmu_state(&pmu_state[0U]);
+
is_secondary_cpu_on = 0;
my_mpidr = read_mpidr_el1() & MPID_MASK;
- if (num_cnts == 0U) {
- ERROR("No PMU counters implemented\n");
- return TEST_RESULT_SKIPPED;
+ if (num_cnts == 0) {
+ INFO("No event counters implemented\n");
+ } else {
+ INFO("Testing %u event counters\n", num_cnts);
}
- feature_flag |= RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts + 1U);
+ /*
+ * Check that number of event counters is less
+ * than maximum supported by architecture.
+ */
+ if (num_cnts < ((1U << RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS_WIDTH) - 1U)) {
+ feature_flag |= RMI_FEATURE_REGISTER_0_PMU_EN |
+ INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, num_cnts + 1U);
- /* 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, 0U)) {
- ERROR("Realm create should have failed\n");
- host_destroy_realm(&realm);
- return TEST_RESULT_FAIL;
+ if (is_feat_52b_on_4k_2_supported()) {
+ feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
+ }
+
+ /* Request more event counters than total, expect failure */
+ if (host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, 1U, 0U)) {
+ ERROR("Realm create should have failed\n");
+ host_destroy_realm(&realm);
+ return TEST_RESULT_FAIL;
+ }
}
- /* Request 0 PMU counter */
+ /* Request Cycle Counter with no event counters */
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, 0U);
+ INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, 0U);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
}
ret1 = host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, 1U, 0U);
+ feature_flag, sl, rec_flag, 1U, 0U);
+ host_destroy_realm(&realm);
if (!get_feat_hpmn0_supported()) {
if (ret1) {
- ERROR("Realm create with 0 PMU Counter should have failed\n");
- host_destroy_realm(&realm);
+ ERROR("Realm create with 0 event counters should have failed\n");
return TEST_RESULT_FAIL;
}
} else {
if (!ret1) {
- ERROR("Realm create with 0 PMU Counter should not have failed\n");
+ ERROR("Realm create with 0 event counters should not have failed\n");
return TEST_RESULT_FAIL;
}
- host_destroy_realm(&realm);
}
- /* Test 2 create first realm with max PMU counters */
+ /* Create first realm with number of PMU event counters */
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts);
+ INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, num_cnts);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
}
- /* Prepare realm0, create recs for realm0 later */
+ /* Prepare realm, create recs later */
if (!host_prepare_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
feature_flag, sl, rec_flag, rec_count, 0U)) {
- goto test_exit;
return TEST_RESULT_FAIL;
}
- /* Second realm with less num of PMU counters */
+ /*
+ * Second realm1 with less or equal number of event counters.
+ * When no event counters are implemented, only Cycle Counter
+ * will be tested.
+ */
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts - 1U);
+ INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
+ (num_cnts == 0U) ? num_cnts : num_cnts - 1U);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
}
- if (!host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
- feature_flag, sl, rec_flag, rec_count, 0U)) {
- goto test_exit2;
+ ret1 = host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
+ feature_flag, sl, rec_flag, rec_count, 0U);
+ if (!ret1) {
+ goto test_exit;
}
- /* create realm0 recs, activate realm0 */
+ /* Create realm recs, activate realm0 */
if (host_realm_rec_create(&realm) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_rec_create");
- goto test_exit2;
+ goto test_exit;
}
if (host_realm_init_ipa_state(&realm, sl, 0U, 1ULL << 32)
!= RMI_SUCCESS) {
ERROR("%s() failed\n", "host_realm_init_ipa_state");
- goto test_exit2;
+ goto test_exit;
}
if (host_realm_activate(&realm) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_activate");
- goto test_exit2;
+ goto test_exit;
}
- INFO("MAX PMU Counter=%u\n", num_cnts);
- /* Pass num of PMU counters programmed to realm */
+ /* Pass number of event counters programmed to realms */
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 == 0U) ? 0U : num_cnts - 1U);
}
/*
- * Enter realm0 rec0 test PMU counters available is same as that programmed by host
- * Validation is done by the Realm and will return error if the count does not match
+ * Enter realm rec0 test PMU counters available is same as that programmed by host.
+ * Validation is done by the Realm and will return error if the count does not match.
*/
ret1 = host_enter_realm_execute(&realm, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, 0U);
if (!ret1) {
- goto test_exit2;
+ goto test_exit;
}
/* Enter realm1 rec0 test PMU counters available is same as that programmed by host */
ret1 = host_enter_realm_execute(&realm1, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, 0U);
if (!ret1) {
- goto test_exit2;
+ goto test_exit;
}
- /* Test if Realm0 rec0 entering/exiting preserves PMU state */
+ /* Test if realm rec0 entering/exiting preserves PMU state */
ret1 = host_enter_realm_execute(&realm, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, 0U);
if (!ret1) {
- goto test_exit2;
+ goto test_exit;
}
- /* Test if Realm1 rec0 entering/exiting preserves PMU state */
+ /* Test if realm1 rec0 entering/exiting preserves PMU state */
ret1 = host_enter_realm_execute(&realm1, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, 0U);
if (!ret1) {
- goto test_exit2;
+ goto test_exit;
+ }
+
+ if (!host_check_pmu_state(&pmu_state[0U])) {
+ goto test_exit;
}
i = 0U;
@@ -787,7 +823,7 @@
ret = tftf_try_cpu_on(other_mpidr, (uintptr_t)cpu_on_handler_pmu, 0);
if (ret != PSCI_E_SUCCESS) {
ERROR("TFTF CPU ON failed\n");
- goto test_exit2;
+ goto test_exit;
}
i++;
}
@@ -808,21 +844,17 @@
}
}
-test_exit2:
+test_exit:
ret2 = host_destroy_realm(&realm1);
if (!ret1 || !ret2) {
ERROR("%s() enter=%u destroy=%u\n", __func__, ret1, ret2);
}
-test_exit:
+
ret2 = host_destroy_realm(&realm);
if (!ret1 || !ret2) {
ERROR("%s() enter=%u destroy=%u\n", __func__, ret1, ret2);
return TEST_RESULT_FAIL;
}
- if (!host_check_pmu_state()) {
- return TEST_RESULT_FAIL;
- }
-
- return TEST_RESULT_SUCCESS;
+ return host_cmp_result();
}
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 c25c58d..9b03393 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -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
*/
@@ -45,7 +188,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -63,7 +206,9 @@
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);
@@ -91,7 +236,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -130,7 +275,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -195,7 +340,7 @@
u_register_t feature_flag = 0U;
long sl = RTT_MIN_LEVEL;
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -296,12 +441,12 @@
}
num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
- host_set_pmu_state();
+ host_set_pmu_state(&pmu_state);
feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
- INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts);
+ INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, num_cnts);
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -312,9 +457,11 @@
}
ret1 = host_enter_realm_execute(&realm, cmd,
- (cmd == REALM_PMU_INTERRUPT) ?
+ ((cmd == REALM_PMU_CYCLE_INTERRUPT) ||
+ (cmd == REALM_PMU_EVENT_INTERRUPT)) ?
RMI_EXIT_IRQ : RMI_EXIT_HOST_CALL, 0U);
- if (!ret1 || (cmd != REALM_PMU_INTERRUPT)) {
+ if (!ret1 || ((cmd != REALM_PMU_CYCLE_INTERRUPT) &&
+ (cmd != REALM_PMU_EVENT_INTERRUPT))) {
goto test_exit;
}
@@ -327,7 +474,7 @@
return TEST_RESULT_FAIL;
}
- if (!host_check_pmu_state()) {
+ if (!host_check_pmu_state(&pmu_state)) {
return TEST_RESULT_FAIL;
}
@@ -347,6 +494,11 @@
*/
test_result_t host_realm_pmuv3_event_works(void)
{
+ if (GET_PMU_CNT == 0) {
+ tftf_testcase_printf("No event counters implemented\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
return host_test_realm_pmuv3(REALM_PMU_EVENT);
}
@@ -370,22 +522,50 @@
return -1;
}
-/*
- * Test PMU interrupt functionality in Realm
- */
-test_result_t host_realm_pmuv3_overflow_interrupt(void)
+static test_result_t host_realm_pmuv3_overflow_interrupt(uint8_t cmd)
{
- /* Register PMU IRQ handler */
- int ret = tftf_irq_register_handler(PMU_PPI, host_overflow_interrupt);
+ test_result_t ret;
- if (ret != 0) {
- tftf_testcase_printf("Failed to %sregister IRQ handler\n",
- "");
+ /* Register PMU IRQ handler */
+ if (tftf_irq_register_handler(PMU_PPI, host_overflow_interrupt) != 0) {
+ tftf_testcase_printf("Failed to %sregister IRQ handler\n", "");
return TEST_RESULT_FAIL;
}
tftf_irq_enable(PMU_PPI, GIC_HIGHEST_NS_PRIORITY);
- return host_test_realm_pmuv3(REALM_PMU_INTERRUPT);
+
+ ret = host_test_realm_pmuv3(cmd);
+ if (ret != TEST_RESULT_SUCCESS) {
+ tftf_irq_disable(PMU_PPI);
+ if (tftf_irq_unregister_handler(PMU_PPI) != 0) {
+ ERROR("Failed to %sregister IRQ handler\n", "un");
+ return TEST_RESULT_FAIL;
+ }
+ return ret;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * Test PMU cycle counter interrupt functionality in Realm
+ */
+test_result_t host_realm_pmuv3_cycle_overflow_interrupt(void)
+{
+ return host_realm_pmuv3_overflow_interrupt(REALM_PMU_CYCLE_INTERRUPT);
+}
+
+/*
+ * Test PMU event counter interrupt functionality in Realm
+ */
+test_result_t host_realm_pmuv3_event_overflow_interrupt(void)
+{
+ if (GET_PMU_CNT == 0) {
+ tftf_testcase_printf("No event counters implemented\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ return host_realm_pmuv3_overflow_interrupt(REALM_PMU_EVENT_INTERRUPT);
}
/*
@@ -405,7 +585,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -429,8 +609,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) {
@@ -479,7 +660,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -489,11 +670,11 @@
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++) {
@@ -578,7 +759,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -595,7 +776,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);
@@ -650,7 +831,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -681,8 +862,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) {
@@ -711,8 +892,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;
@@ -729,8 +910,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;
@@ -776,7 +957,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -811,8 +992,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,
@@ -821,8 +1002,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;
@@ -838,8 +1019,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;
@@ -885,7 +1066,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -913,8 +1094,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");
@@ -954,8 +1135,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;
@@ -971,8 +1152,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;
@@ -1020,7 +1201,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -1038,10 +1219,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,
@@ -1052,7 +1233,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;
@@ -1068,7 +1249,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;
@@ -1100,7 +1281,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;
@@ -1116,7 +1297,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);
}
@@ -1162,7 +1343,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -1185,8 +1366,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,
@@ -1197,7 +1378,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;
@@ -1212,8 +1393,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);
@@ -1233,7 +1414,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;
@@ -1266,7 +1447,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -1283,7 +1464,7 @@
/* 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) {
@@ -1500,7 +1681,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -1686,7 +1867,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -1747,8 +1928,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);
@@ -1764,7 +1945,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)) {
@@ -1784,7 +1965,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)) {
@@ -1799,8 +1980,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];
@@ -1814,8 +1995,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);
@@ -1834,8 +2015,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",
@@ -1879,7 +2060,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2036,7 +2217,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2211,7 +2392,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2326,7 +2507,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2439,7 +2620,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2552,7 +2733,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
SKIP_TEST_IF_DOUBLE_FAULT2_NOT_SUPPORTED();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2581,10 +2762,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 */
@@ -2615,7 +2796,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
@@ -2656,7 +2837,7 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
- if (is_feat_52b_on_4k_2_supported() == true) {
+ if (is_feat_52b_on_4k_2_supported()) {
feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
sl = RTT_MIN_LEVEL_LPA2;
}
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 235e093..40e8590 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
@@ -33,7 +33,7 @@
if (sve_en) {
feature_flag |= RMI_FEATURE_REGISTER_0_SVE_EN |
- INPLACE(FEATURE_SVE_VL, sve_vq);
+ INPLACE(RMI_FEATURE_REGISTER_0_SVE_VL, sve_vq);
}
/* Initialise Realm payload */
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/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
index 0baf471..91e5307 100644
--- a/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
+++ b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -387,7 +387,23 @@
em_cpu_t cortex_X4_errata_list = {
.cpu_pn = 0xD82,
.cpu_errata = {
- {2701112, 0x00, 0x00},
+ {2726228, 0x00, 0x01},
+ {2740089, 0x00, 0x01},
+ {2763018, 0x00, 0x01},
+ {2816013, 0x00, 0x01},
+ {2897503, 0x00, 0x01},
+ {2923985, 0x00, 0x01},
+ {2957258, 0x00, 0x01},
+ {3076789, 0x00, 0x01},
+ {-1}
+ },
+};
+
+em_cpu_t cortex_X925_errata_list = {
+ .cpu_pn = 0xD85,
+ .cpu_errata = {
+ {2963999, 0x00, 0x00},
+ {3701747, 0x00, 0x01},
{-1}
},
};
@@ -631,6 +647,12 @@
cpu_ptr = &cortex_X4_errata_list;
break;
}
+ case 0xD85:
+ {
+ VERBOSE("MIDR matches Cortex-X925 -> %x\n", midr_val);
+ cpu_ptr = &cortex_X925_errata_list;
+ break;
+ }
case 0xD4E:
{
VERBOSE("MIDR matches Cortex-X3 -> %x\n", midr_val);
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.mk b/tftf/tests/tests-realm-payload.mk
index b6833e1..1fe01ed 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -16,6 +16,7 @@
host_realm_spm.c \
host_realm_payload_simd_tests.c \
host_realm_lpa2_tests.c \
+ host_realm_mpam_tests.c \
)
TESTS_SOURCES += \
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index da88701..c8747f6 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"
@@ -66,8 +70,10 @@
function="host_realm_pmuv3_event_works" />
<testcase name="PMUv3 RSI SMC counter preservation"
function="host_realm_pmuv3_rmm_preserves" />
- <testcase name="PMUv3 overflow interrupt"
- function="host_realm_pmuv3_overflow_interrupt" />
+ <testcase name="PMUv3 cycle counter overflow interrupt"
+ function="host_realm_pmuv3_cycle_overflow_interrupt" />
+ <testcase name="PMUv3 event counter overflow interrupt"
+ function="host_realm_pmuv3_event_overflow_interrupt" />
<testcase name="PMUv3 multiple rec validations"
function="host_realm_pmuv3_mul_rec" />
<testcase name="Test Secure interrupt can preempt Realm EL1"
@@ -140,5 +146,10 @@
<!-- Invoke RMI calls related to PDEV management -->
<testcase name="Invoke RMI PDEV calls "
function="host_test_rmi_pdev_calls" />
+ <!-- Test cases related to FEAT_MPAM -->
+ <testcase name="Test that FEAT_MPAM is hidden to the Realm"
+ function="host_realm_hide_feat_mpam" />
+ <testcase name="Test that access to FEAT_MPAM from Realm causes an undef abort taken to the Realm"
+ function="host_realm_mpam_undef_abort" />
</testsuite>
</testsuites>
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 \
)
diff --git a/tools/generate_json/generate_json.sh b/tools/generate_json/generate_json.sh
index 5867700..9d51ba5 100755
--- a/tools/generate_json/generate_json.sh
+++ b/tools/generate_json/generate_json.sh
@@ -59,14 +59,16 @@
"image": "cactus.bin",
"pm": "cactus-secondary.dts",
"physical-load-address": "0x7100000",
- "owner": "Plat"
+ "owner": "Plat",
+ "package": "tl_pkg"
},
"cactus-tertiary" : {
"image": "cactus.bin",
"pm": "cactus-tertiary.dts",
"physical-load-address": "0x7200000",
- "owner": "Plat"
+ "owner": "Plat",
+ "package": "tl_pkg"
EOF
PARTITION_ALREADY_PRESENT=true
fi
@@ -81,7 +83,8 @@
"image": "ivy.bin",
"pm": "ivy-sel0.dts",
"physical-load-address": "0x7600000",
- "owner": "Plat"
+ "owner": "Plat",
+ "package": "tl_pkg"
}
EOF
@@ -95,7 +98,8 @@
"image": "ivy.bin",
"pm": "ivy-sel1.dts",
"physical-load-address": "0x7600000",
- "owner": "Plat"
+ "owner": "Plat",
+ "package":"tl_pkg"
}
EOF