Merge "Revert "fvp: skip cpu cluster power-on check""
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 33c0ab9..b0ebc46 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -6,6 +6,7 @@
    :caption: Contents
    :hidden:
 
+   xilinx-versal2
    xilinx-versal_net
    xilinx-versal
    xilinx-zynqmp
diff --git a/docs/plat/xilinx-versal2.rst b/docs/plat/xilinx-versal2.rst
new file mode 100644
index 0000000..841340e
--- /dev/null
+++ b/docs/plat/xilinx-versal2.rst
@@ -0,0 +1,26 @@
+..
+  Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved. !
+
+  SPDX-License-Identifier: BSD-3-Clause !
+
+
+AMD Versal Gen 2
+=============
+
+- Logs are available only on console and not saved in memory(No NVM support).
+- Versal Gen 2 Platform uses TTC Timer
+
+
+Build Command
+-------------
+For individual tests/test suite:
+
+.. code-block:: shell
+
+        make CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 TESTS=<required tests> tftf
+
+For Versal2 Specific tests (includes AMD-Xilinx Tests cases + Standard Test Suite)
+
+.. code-block:: shell
+
+        make CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 TESTS=versal tftf
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index d29f5a6..8081ff4 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -226,6 +226,7 @@
 #define ID_AA64DFR0_TRACEBUFFER_SHIFT		U(44)
 #define ID_AA64DFR0_TRACEBUFFER_MASK		ULL(0xf)
 #define ID_AA64DFR0_TRACEBUFFER_SUPPORTED	ULL(1)
+#define ID_AA64DFR0_TRACEBUFFER_WIDTH		U(4)
 
 /* ID_DFR0_EL1.Tracefilt definitions */
 #define ID_AA64DFR0_TRACEFILT_SHIFT		U(40)
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index f5dd294..5822dc4 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -450,4 +450,10 @@
 		ID_AA64ISAR1_LS64_MASK);
 }
 
+static inline bool is_feat_trbe_present(void)
+{
+	return EXTRACT(ID_AA64DFR0_TRACEBUFFER, read_id_aa64dfr0_el1())
+		>= ID_AA64DFR0_TRACEBUFFER_SUPPORTED;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/plat/amd/versal2/aarch64/plat_helpers.S b/plat/amd/versal2/aarch64/plat_helpers.S
new file mode 100644
index 0000000..715d5f1
--- /dev/null
+++ b/plat/amd/versal2/aarch64/plat_helpers.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.global platform_get_core_pos
+	.global plat_crash_console_init
+	.global plat_crash_console_flush
+	.global plat_crash_console_putc
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(u_register_t mpid)
+ *
+ * Function to calculate the core position.
+ *
+ * clobbers: x0 - x3
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x3, #PLATFORM_CORE_COUNT_PER_CLUSTER
+	madd	x1, x2, x3, x1
+	mov	x3, #PLATFORM_MAX_PE_PER_CPU
+	madd	x0, x1, x3, x0
+	ret
+endfunc platform_get_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x4
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	mov_imm	x1, PL011_UART_CLK_IN_HZ
+	mov_imm	x2, PL011_BAUDRATE
+	b	console_core_init
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, CRASH_CONSOLE_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0 - r1
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_flush
+	mov_imm	x1, CRASH_CONSOLE_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
new file mode 100644
index 0000000..645a5eb
--- /dev/null
+++ b/plat/amd/versal2/include/platform_def.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+
+#define PLATFORM_LINKER_FORMAT			"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH			aarch64
+
+#define TFTF_BASE				U(0x8000000)
+
+#define CACHE_WRITEBACK_GRANULE			U(0x40)
+
+#define PLATFORM_CLUSTER_COUNT			U(4)
+#define PLATFORM_CORE_COUNT_PER_CLUSTER		U(2)
+#define PLATFORM_MAX_PE_PER_CPU			U(1)
+/* Because of make_mpid from include/lib/tftf_lib.h */
+#define PLAT_MAX_PE_PER_CPU		PLATFORM_MAX_PE_PER_CPU
+
+#define PLATFORM_CORE_COUNT			(PLATFORM_CLUSTER_COUNT * \
+						PLATFORM_CORE_COUNT_PER_CLUSTER)
+#define PLATFORM_NUM_AFFS			(PLATFORM_CORE_COUNT + \
+						PLATFORM_CLUSTER_COUNT + 1)
+#define PLATFORM_MAX_AFFLVL			MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LEVEL			MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_STATES_PER_LVL		U(2)
+
+
+#define PLATFORM_STACK_SIZE			U(0x440)
+#define PCPU_DV_MEM_STACK_SIZE			U(0x440)
+
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 32)
+#define MAX_XLAT_TABLES				U(8)
+#define MAX_MMAP_REGIONS			U(16)
+
+#define DRAM_BASE				U(0x0)
+#define DRAM_SIZE				U(0x80000000)
+
+/*
+ * TFTF_NVM_OFFSET/SIZE correspond to the NVM partition in the partition
+ * table
+ */
+#define TFTF_NVM_SIZE				U(0x600000)
+#define TFTF_NVM_OFFSET				U(0x20000000)
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH			U(4)
+
+/* GIC related addresses from datasheet */
+#define GICD_REG_BASE				U(0xe2000000)
+#define GICR_REG_BASE				U(0xe2060000)
+
+/* GICv3 is used, dummy definition to resolve build failure */
+#define GICC_REG_BASE				U(0xe2000000)
+
+/*
+ * Memory mapped devices that we must create MMU mappings for them
+ */
+#define GIC_BASE				GICD_REG_BASE
+#define GIC_SIZE				U(0x01000000)
+
+#define TTC_BASE				U(0xF1E70000)
+#define TTC_SIZE				U(0x00010000)
+
+#define SYS_CNT_BASE1				TTC_BASE
+#define SYS_CNT_SIZE				TTC_SIZE
+
+#define LPD_IOU_SLCR				U(0xEB410000)
+#define LPD_IOU_SLCR_SIZE			U(0x00010000)
+
+/* ARM PL011 UART */
+#define PL011_UART0_BASE			U(0xf1920000)
+#define PL011_BAUDRATE				U(115200)
+#define PL011_UART_CLK_IN_HZ			U(100000000)
+
+#define PLAT_ARM_UART_BASE                      PL011_UART0_BASE
+#define PLAT_ARM_UART_SIZE                      U(0x1000)
+
+#define CRASH_CONSOLE_BASE			PL011_UART0_BASE
+#define CRASH_CONSOLE_SIZE			PLAT_ARM_UART_SIZE
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interrupts IDs
+ ******************************************************************************/
+#define IRQ_NS_SGI_0				0
+#define IRQ_NS_SGI_1				1
+#define IRQ_NS_SGI_2				2
+#define IRQ_NS_SGI_3				3
+#define IRQ_NS_SGI_4				4
+#define IRQ_NS_SGI_5				5
+#define IRQ_NS_SGI_6				6
+#define IRQ_NS_SGI_7				7
+
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER			U(29)
+/* Datasheet: TIME00 event*/
+#define IRQ_CNTPSIRQ1				U(29)
+
+/* Refer to AM011(v1.5), Chapter 50, Page 430 */
+#define PLAT_MAX_SPI_OFFSET_ID			U(223)
+
+/*
+ * Times(in ms) used by test code for completion of different events.
+ */
+#define PLAT_SUSPEND_ENTRY_TIME			U(15)
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME		U(30)
+
+/*
+ * Dummy definitions that we need just to compile...
+ */
+#define ARM_SECURE_SERVICE_BUFFER_BASE		U(0)
+#define ARM_SECURE_SERVICE_BUFFER_SIZE		U(100)
+
+/* LPD_SWDT_INT, AM011(v1.5), Chapter 50, Page 428 */
+#define IRQ_TWDOG_INTID				U(0x51)
+
+#define TTC_TIMER_IRQ				U(75)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amd/versal2/platform.mk b/plat/amd/versal2/platform.mk
new file mode 100644
index 0000000..2304d2f
--- /dev/null
+++ b/plat/amd/versal2/platform.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+XLNX_COMMON_PATH :=	plat/xilinx/common
+VERSAL2_PATH :=	plat/amd/versal2
+
+PLAT_INCLUDES	:=	-I${XLNX_COMMON_PATH}/include/			\
+			-I${VERSAL2_PATH}/include/
+
+PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2v3.c                  \
+			drivers/arm/gic/gic_common.c                    \
+			drivers/arm/gic/gic_v2.c                        \
+			drivers/arm/gic/gic_v3.c                        \
+			drivers/arm/pl011/${ARCH}/pl011_console.S       \
+			drivers/arm/timer/private_timer.c		\
+			drivers/console/console.c                       \
+			${VERSAL2_PATH}/versal2_setup.c		\
+			${VERSAL2_PATH}/versal2_pwr_state.c	\
+			${VERSAL2_PATH}/aarch64/plat_helpers.S	\
+			${XLNX_COMMON_PATH}/timer/timers.c
+
+PLAT_TESTS_SKIP_LIST    := ${VERSAL2_PATH}/tests_to_skip.txt
+
+ifeq ($(USE_NVM),1)
+$(error "Versal2 port of TFTF doesn't currently support USE_NVM=1")
+endif
diff --git a/plat/amd/versal2/tests_to_skip.txt b/plat/amd/versal2/tests_to_skip.txt
new file mode 100644
index 0000000..2c286ec
--- /dev/null
+++ b/plat/amd/versal2/tests_to_skip.txt
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+################################################################################
+# Disable the listed tests for Versal2 Platform.
+################################################################################
+#TESTS: tftf-validation
+Framework Validation/Events API
+Framework Validation/NVM serialisation
+
+#TESTS: Timer framework Validation
+Timer framework Validation
+
+#TESTS: Boot requirement tests
+Boot requirement tests
+
+ARM_ARCH_SVC
+PMU Leakage
+
+#TESTS: CPU extensions
+CPU extensions/PMUv3 SMC counter preservation
+
+#TESTS: Performance tests
+Performance tests/Test cluster power up latency
+
+#TESTS: FF-A
+FF-A Setup and Discovery/FF-A RXTX unmap SP rxtx buffer
+FF-A Setup and Discovery/Test FFA_PARTITION_INFO_GET v1.0
+FF-A Memory Sharing/Lend memory, clear flag set
+SIMD,SVE Registers context/Check that SIMD registers context is preserved
+FF-A Interrupt
+FF-A Notifications
+
+#TESTS: AMD-Xilinx tests
+AMD-Xilinx tests
+
+#TESTS: psci
+PSCI Affinity Info/Affinity info level0 powerdown
+PSCI CPU Suspend/CPU suspend to powerdown at level 0
+PSCI CPU Suspend/CPU suspend to powerdown at level 1
+PSCI CPU Suspend/CPU suspend to powerdown at level 2
+PSCI CPU Suspend/CPU suspend to standby at level 0
+PSCI CPU Suspend/CPU suspend to standby at level 1
+PSCI CPU Suspend/CPU suspend to standby at level 2
+PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 0 in OSI mode
+PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 1 in OSI mode
+PSCI System Suspend Validation/System suspend multiple times
+PSCI System Suspend Validation/system suspend from all cores
+PSCI System Suspend Validation/Validate suspend to RAM functionality
+PSCI System Suspend Validation/Validate PSCI System Suspend API
+
+#PSCI
+PSCI Features
+PSCI CPU Suspend in OSI mode
+
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
+#TESTS: el3-power-state
+EL3 power state parser validation
diff --git a/plat/amd/versal2/versal2_pwr_state.c b/plat/amd/versal2/versal2_pwr_state.c
new file mode 100644
index 0000000..a9bff07
--- /dev/null
+++ b/plat/amd/versal2/versal2_pwr_state.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <arch.h>
+#include <platform.h>
+#include <psci.h>
+
+/*
+ * State IDs for local power states.
+ */
+#define VERSAL2_RETENTION_STATE_ID	1	/* Valid for only CPUs */
+#define VERSAL2_OFF_STATE_ID		0	/* Valid for CPUs and Clusters */
+
+/*
+ * Suspend depth definitions for each power state
+ */
+typedef enum {
+	VERSAL2_RUN_DEPTH = 0,
+	VERSAL2_RETENTION_DEPTH,
+	VERSAL2_OFF_DEPTH,
+} suspend_depth_t;
+
+/* The state property array with details of idle state possible for the core */
+static const plat_state_prop_t core_state_prop[] = {
+	{VERSAL2_RETENTION_DEPTH, VERSAL2_RETENTION_STATE_ID, PSTATE_TYPE_STANDBY},
+	{VERSAL2_OFF_DEPTH, VERSAL2_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/* The state property array with details of idle state possible for the cluster */
+static const plat_state_prop_t cluster_state_prop[] = {
+	{VERSAL2_OFF_DEPTH, VERSAL2_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+/* The state property array with details of idle state possible for the system level */
+static const plat_state_prop_t system_state_prop[] = {
+	{VERSAL2_OFF_DEPTH, VERSAL2_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0},
+};
+
+const plat_state_prop_t *plat_get_state_prop(unsigned int level)
+{
+	switch (level) {
+	case MPIDR_AFFLVL0:
+		return core_state_prop;
+	case MPIDR_AFFLVL1:
+		return cluster_state_prop;
+	case MPIDR_AFFLVL2:
+		return system_state_prop;
+	default:
+		return NULL;
+	}
+}
diff --git a/plat/amd/versal2/versal2_setup.c b/plat/amd/versal2/versal2_setup.c
new file mode 100644
index 0000000..0db69d6
--- /dev/null
+++ b/plat/amd/versal2/versal2_setup.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <drivers/arm/arm_gic.h>
+#include <drivers/console.h>
+#include <platform.h>
+#include <tftf_lib.h>
+
+#include <platform_def.h>
+#include <util.h>
+
+static const struct {
+	unsigned int cluster_id;
+	unsigned int cpu_id;
+} versal2_cores[PLATFORM_CORE_COUNT] = {
+	CLUSTER_DEF(0),
+	CLUSTER_DEF(1),
+	CLUSTER_DEF(2),
+	CLUSTER_DEF(3)
+};
+
+
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(DRAM_BASE + TFTF_NVM_OFFSET, TFTF_NVM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+	MAP_REGION_FLAT(GIC_BASE, GIC_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(CRASH_CONSOLE_BASE, CRASH_CONSOLE_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(TTC_BASE, TTC_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(LPD_IOU_SLCR, LPD_IOU_SLCR_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	{0}
+};
+
+/* Power Domain Tree Descriptor array */
+const unsigned char versal2_pwr_tree_desc[] = {
+	/* Number of root nodes */
+	1,
+	/* Number of clusters */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster node */
+	PLATFORM_CORE_COUNT_PER_CLUSTER,
+	/* Number of children for the second cluster node */
+	PLATFORM_CORE_COUNT_PER_CLUSTER,
+	/* Number of children for the third cluster node */
+	PLATFORM_CORE_COUNT_PER_CLUSTER,
+	/* Number of children for the fourth cluster node */
+	PLATFORM_CORE_COUNT_PER_CLUSTER
+};
+
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+	return versal2_pwr_tree_desc;
+}
+
+/*
+ * Generate the MPID from the core position.
+ */
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+	assert(core_pos < PLATFORM_CORE_COUNT);
+
+	return (uint64_t)make_mpid(versal2_cores[core_pos].cluster_id,
+				versal2_cores[core_pos].cpu_id);
+}
+
+void tftf_plat_arch_setup(void)
+{
+	tftf_plat_configure_mmu();
+}
+
+void tftf_early_platform_setup(void)
+{
+	console_init(CRASH_CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
+}
+
+void tftf_platform_setup(void)
+{
+	arm_gic_init(GICC_REG_BASE, GICD_REG_BASE, GICR_REG_BASE);
+	arm_gic_setup_global();
+	arm_gic_setup_local();
+}
+
+const mmap_region_t *tftf_platform_get_mmap(void)
+{
+	return mmap;
+}
diff --git a/plat/xilinx/common/include/util.h b/plat/xilinx/common/include/util.h
new file mode 100644
index 0000000..c6d16ce
--- /dev/null
+++ b/plat/xilinx/common/include/util.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <platform_def.h>
+
+#define CPU_DEF(cluster, cpu)	{ cluster, cpu }
+
+#if (PLATFORM_CORE_COUNT_PER_CLUSTER == 1U)
+#define CLUSTER_DEF(cluster)	\
+	CPU_DEF(cluster, 0)
+#elif (PLATFORM_CORE_COUNT_PER_CLUSTER == 2U)
+#define CLUSTER_DEF(cluster)	\
+	CPU_DEF(cluster, 0),		\
+	CPU_DEF(cluster, 1)
+#elif (PLATFORM_CORE_COUNT_PER_CLUSTER == 4U)
+#define CLUSTER_DEF(cluster)	\
+	CPU_DEF(cluster, 0),		\
+	CPU_DEF(cluster, 1),		\
+	CPU_DEF(cluster, 2),		\
+	CPU_DEF(cluster, 3)
+#endif
+
+#endif /* UTIL_H */
diff --git a/plat/xilinx/common/timer/timers.c b/plat/xilinx/common/timer/timers.c
index f53cd84..a6e1afa 100644
--- a/plat/xilinx/common/timer/timers.c
+++ b/plat/xilinx/common/timer/timers.c
@@ -27,6 +27,7 @@
 
 #define TTC_CNT_CNTRL_DISABLE_MASK	BIT(0)
 
+#define TTC_CLK_SEL_OFFSET		U(0x360)
 #define TTC_CLK_SEL_MASK		GENMASK(1, 0)
 
 #define TTC_CLK_SEL_PS_REF		BIT(0)
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index 6e7fe1a..e7dd720 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -33,6 +33,7 @@
 		.properties = (FFA_PARTITION_AARCH64_EXEC |
 			       FFA_PARTITION_DIRECT_REQ_RECV |
 			       FFA_PARTITION_DIRECT_REQ_SEND |
+			       FFA_PARTITION_INDIRECT_MSG |
 			       FFA_PARTITION_NOTIFICATION),
 		.uuid = {PRIMARY_UUID}
 	},
@@ -84,13 +85,16 @@
 	/* Get common features between tftf and cactus. */
 	unsigned int test_target_size =
 		get_ffa_feature_test_target(&func_id_targets);
-	struct ffa_features_test feature_id_targets[3] = {
+	/* Specific to SPs. */
+	struct ffa_features_test feature_id_targets[] = {
 		{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_SUCCESS_SMC32, 0,
 			FFA_VERSION_1_1},
 		{"FFA_FEATURE_SRI", FFA_FEATURE_SRI, FFA_ERROR, 0,
 			FFA_VERSION_1_1},
 		{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_SUCCESS_SMC32, 0,
 			FFA_VERSION_1_1},
+		{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_SUCCESS_SMC32,
+			FFA_VERSION_1_0},
 	};
 
 	INFO("Test FFA_FEATURES.\n");
diff --git a/tftf/tests/misc_tests/test_asymmetric_features.c b/tftf/tests/misc_tests/test_asymmetric_features.c
index 25b2421..630cc69 100644
--- a/tftf/tests/misc_tests/test_asymmetric_features.c
+++ b/tftf/tests/misc_tests/test_asymmetric_features.c
@@ -19,15 +19,39 @@
 
 static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT];
 
-static volatile bool undef_injection_triggered;
+/* Used when catching synchronous exceptions. */
+static volatile bool exception_triggered[PLATFORM_CORE_COUNT];
 
-static unsigned int test_result;
+/*
+ * The whole test should only be skipped if the test was skipped on all CPUs.
+ * The test on each CPU can't return TEST_RESULT_SKIPPED, because the whole test
+ * is skipped if any of the CPUs return TEST_RESULT_SKIPPED. Instead, to skip a
+ * test, the test returns TEST_RESULT_SUCCESS, then sets a flag in the
+ * test_skipped array. This array is checked at the end by the
+ * run_asymmetric_test function.
+ */
+static volatile bool test_skipped[PLATFORM_CORE_COUNT];
 
-static bool undef_injection_handler(void)
+/*
+ * Test function which is run on each CPU. It is global so it is visible to all
+ * CPUS.
+ */
+static test_result_t (*asymmetric_test_function)(void);
+
+static bool exception_handler(void)
 {
+	unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+	unsigned int core_pos = platform_get_core_pos(mpid);
+
 	uint64_t esr_el2 = read_esr_el2();
+
 	if (EC_BITS(esr_el2) == EC_UNKNOWN) {
-		undef_injection_triggered = true;
+		/*
+		 * This may be an undef injection, or a trap to EL2 due to a
+		 * register not being present. Both cases have the same EC
+		 * value.
+		 */
+		exception_triggered[core_pos] = true;
 		return true;
 	}
 
@@ -38,24 +62,32 @@
 {
 	unsigned int mpid = read_mpidr_el1() & MPID_MASK;
 	unsigned int core_pos = platform_get_core_pos(mpid);
-	bool check_if_affected = is_trbe_errata_affected_core();
+	bool should_trigger_exception = is_trbe_errata_affected_core();
 
-	read_trblimitr_el1();
-
-	if (undef_injection_triggered == true && check_if_affected == true) {
-		test_result = TEST_RESULT_SUCCESS;
-		undef_injection_triggered = false;
-		tftf_testcase_printf("Undef injection triggered for core = %d "
-				     "when accessing TRB_LIMTR\n", core_pos);
-	} else if (undef_injection_triggered == false && check_if_affected == false) {
-		test_result = TEST_RESULT_SUCCESS;
-		tftf_testcase_printf("TRB_LIMITR register accessible for core "
-				     "= %d\n", core_pos);
-	} else {
-		test_result = TEST_RESULT_FAIL;
+	if (!is_feat_trbe_present()) {
+		test_skipped[core_pos] = true;
+		return TEST_RESULT_SUCCESS;
 	}
 
-	return test_result;
+	register_custom_sync_exception_handler(exception_handler);
+	exception_triggered[core_pos] = false;
+	read_trblimitr_el1();
+	unregister_custom_sync_exception_handler();
+
+	/**
+	 * NOTE: TRBE as an asymmetric feature is as exceptional one.
+	 * Even if the hardware supports the feature, TF-A deliberately disables
+	 * it at EL3. In this scenario, when the register "TRBLIMITR_EL1" is
+	 * accessed, the registered undef injection handler should kick in and
+	 * the exception will be handled synchronously at EL2.
+	 */
+	if (exception_triggered[core_pos] != should_trigger_exception) {
+		tftf_testcase_printf("Exception triggered for core = %d "
+				     "when accessing TRB_LIMTR\n", core_pos);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
 }
 
 static test_result_t test_spe(void)
@@ -63,54 +95,36 @@
 	unsigned int mpid = read_mpidr_el1() & MPID_MASK;
 	unsigned int core_pos = platform_get_core_pos(mpid);
 
-	read_pmscr_el1();
-
-	if (undef_injection_triggered == true && !is_feat_spe_supported()) {
-		test_result = TEST_RESULT_SUCCESS;
-		undef_injection_triggered = false;
-		tftf_testcase_printf("Undef injection triggered for core = %d "
-				     "when accessing PMSCR_EL1\n", core_pos);
-	} else if (undef_injection_triggered == false &&
-		   is_feat_spe_supported()) {
-		test_result = TEST_RESULT_SUCCESS;
-		tftf_testcase_printf("PMSCR_EL1 register accessible for core = "
-				     "%d\n", core_pos);
-	} else {
-		test_result = TEST_RESULT_FAIL;
+	/**
+	 * NOTE: SPE as an asymmetric feature, we expect to access the
+	 * PMSCR_EL1 register, when supported in the hardware.
+	 * If the feature isn't supported, we skip the test.
+	 * So on each individual CPU, we verify whether the feature's presence
+	 * and based on it we access (if feature supported) or skip the test.
+	 */
+	if (!is_feat_spe_supported()) {
+		test_skipped[core_pos] = true;
+		return TEST_RESULT_SUCCESS;
 	}
 
-	return test_result;
+	read_pmscr_el1();
+
+	return TEST_RESULT_SUCCESS;
 }
 
 /*
- * Non-lead cpu function that checks if trblimitr_el1 is accessible,
- * on affected cores this causes a undef injection and passes.In cores that
- * are not affected test just passes. It fails in other cases.
+ * Runs on one CPU, and runs asymmetric_test_function.
  */
 static test_result_t non_lead_cpu_fn(void)
 {
 	unsigned int mpid = read_mpidr_el1() & MPID_MASK;
 	unsigned int core_pos = platform_get_core_pos(mpid);
-	test_result_t result;
-
-	test_result = TEST_RESULT_SUCCESS;
+	test_result_t test_result;
 
 	/* Signal to the lead CPU that the calling CPU has entered the test */
 	tftf_send_event(&cpu_has_entered_test[core_pos]);
 
-	result = test_trbe();
-	if (result != TEST_RESULT_SUCCESS) {
-		tftf_testcase_printf("test_trbe_enabled failed with result "
-				     "%d\n", result);
-		test_result = result;
-	}
-
-	result = test_spe();
-	if (result != TEST_RESULT_SUCCESS) {
-		tftf_testcase_printf("test_spe_support failed with result %d\n",
-				     result);
-		test_result = result;
-	}
+	test_result = asymmetric_test_function();
 
 	/* Ensure that EL3 still functional */
 	smc_args args;
@@ -126,43 +140,46 @@
 	return test_result;
 }
 
-/* This function kicks off non-lead cpus and the non-lead cpu function
- * checks if errata is applied or not using the test.
+/* Set some variables that are accessible to all CPUs. */
+void test_init(test_result_t (*test_function)(void))
+{
+	int i;
+
+	for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
+		test_skipped[i] = false;
+		tftf_init_event(&cpu_has_entered_test[i]);
+	}
+
+	asymmetric_test_function = test_function;
+
+	/* Ensure the above writes are seen before any read */
+	dmbsy();
+}
+
+/*
+ * Run the given test function on all CPUs. If the test is skipped on all CPUs,
+ * the whole test is skipped. This is checked using the test_skipped array.
  */
-test_result_t test_asymmetric_features(void)
+test_result_t run_asymmetric_test(test_result_t (*test_function)(void))
 {
 	unsigned int lead_mpid;
 	unsigned int cpu_mpid, cpu_node;
 	unsigned int core_pos;
 	int psci_ret;
-
-	test_result_t result;
-
-	test_result = TEST_RESULT_SUCCESS;
-
-	undef_injection_triggered = false;
-
-	register_custom_sync_exception_handler(undef_injection_handler);
+	bool all_cpus_skipped;
+	int i;
+	uint32_t aff_info;
+	test_result_t test_result;
 
 	lead_mpid = read_mpidr_el1() & MPID_MASK;
 
-	/* Testing TRBE and SPE feature in Lead core */
-	result = test_trbe();
-	if (result != TEST_RESULT_SUCCESS) {
-		tftf_testcase_printf("test_trbe_enabled failed with result "
-				     "%d\n", result);
-		test_result = result;
-	}
-
-	result = test_spe();
-	if (result != TEST_RESULT_SUCCESS) {
-		tftf_testcase_printf("test_spe_support failed with result %d\n",
-				     result);
-		test_result = result;
-	}
-
 	SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
 
+	test_init(test_function);
+
+	/* run test on lead CPU */
+	test_result = test_function();
+
 	/* Power on all CPUs */
 	for_each_cpu(cpu_node) {
 		cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
@@ -188,11 +205,49 @@
 
 		core_pos = platform_get_core_pos(cpu_mpid);
 		tftf_wait_for_event(&cpu_has_entered_test[core_pos]);
-		if (test_result == TEST_RESULT_FAIL)
-			break;
 	}
 
-	unregister_custom_sync_exception_handler();
+	/* Wait for all non-lead CPUs to power down */
+	for_each_cpu(cpu_node) {
+		cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+		/* Skip lead CPU */
+		if (cpu_mpid == lead_mpid)
+			continue;
 
-	return test_result;
+		do {
+			aff_info = tftf_psci_affinity_info(cpu_mpid,
+							   MPIDR_AFFLVL0);
+		} while (aff_info != PSCI_STATE_OFF);
+	}
+
+	/*
+	 * If the test was skipped on all CPUs, the whole test should be
+	 * skipped.
+	 */
+
+	all_cpus_skipped = true;
+	for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
+		if (!test_skipped[i]) {
+			all_cpus_skipped = false;
+			break;
+		}
+	}
+
+	if (all_cpus_skipped) {
+		return TEST_RESULT_SKIPPED;
+	} else {
+		return test_result;
+	}
+}
+
+/* Test Asymmetric Support for FEAT_TRBE */
+test_result_t test_trbe_errata_asymmetric(void)
+{
+	return run_asymmetric_test(test_trbe);
+}
+
+/* Test Asymmetric Support for FEAT_SPE */
+test_result_t test_spe_asymmetric(void)
+{
+	return run_asymmetric_test(test_spe);
 }
diff --git a/tftf/tests/plat/amd/versal2/test_all_cores.c b/tftf/tests/plat/amd/versal2/test_all_cores.c
new file mode 100644
index 0000000..d7342bf
--- /dev/null
+++ b/tftf/tests/plat/amd/versal2/test_all_cores.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <events.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <power_management.h>
+#include <psci.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <timer.h>
+
+static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT];
+
+/*
+ * Test entry point function for non-lead CPUs.
+ * Specified by the lead CPU when bringing up other CPUs.
+ */
+static test_result_t non_lead_cpu_fn(void)
+{
+	unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+	unsigned int core_pos = platform_get_core_pos(mpid);
+
+	VERBOSE("%s\n", __func__);
+
+	/* Signal to the lead CPU that the calling CPU has entered the test */
+	tftf_send_event(&cpu_has_entered_test[core_pos]);
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Code for a test running on multiple CPUs.
+ *
+ * This "test" powers on all CPUs on the platform and report test success.
+ * The function test_multi_core() runs on the lead CPU only.
+ * The test entrypoint for other CPUs is non_lead_cpu_fn(), as specified when
+ * bringing them up.
+ * 1) Power on all secondary cores
+ * 2) after a delay power off all secondary cores
+ *
+ * The test is skipped if an error occurs during the bring-up of non-lead CPUs.
+ */
+test_result_t test_power_on_cores(void)
+{
+	unsigned int lead_mpid;
+	unsigned int cpu_mpid, cpu_node;
+	unsigned int core_pos;
+	int psci_ret;
+
+	lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+	VERBOSE("%s: lead_mpid = 0x%x\n", __func__, lead_mpid);
+
+	SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
+
+	/* Power on all CPUs */
+	for_each_cpu(cpu_node) {
+		cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+		/* Skip lead CPU as it is already powered on */
+		if (cpu_mpid == lead_mpid)
+			continue;
+
+		VERBOSE("%s getting cpu_mpid = 0x%x powered on\n", __func__,
+				cpu_mpid);
+		psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) non_lead_cpu_fn, 0);
+		if (psci_ret != PSCI_E_SUCCESS) {
+			tftf_testcase_printf("Failed to power on CPU 0x%x (%d)\n",
+					cpu_mpid, psci_ret);
+			/*return TEST_RESULT_SKIPPED; */
+		}
+	}
+
+	/* Wait for non-lead CPUs to enter the test */
+	for_each_cpu(cpu_node) {
+		cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+		/* Skip lead CPU */
+		if (cpu_mpid == lead_mpid)
+			continue;
+
+		core_pos = platform_get_core_pos(cpu_mpid);
+		tftf_wait_for_event(&cpu_has_entered_test[core_pos]);
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 06e76db..4fac119 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -202,7 +202,6 @@
 		FFA_SUCCESS_SMC32},
 	{"FFA_NOTIFICATION_INFO_GET_64", FFA_NOTIFICATION_INFO_GET_SMC64,
 		FFA_SUCCESS_SMC32},
-	{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
 	{"Check non-existent command", 0xFFFF, FFA_ERROR},
 };
 
@@ -721,13 +720,13 @@
 	}
 
 	if (info->exec_context != expected->exec_context) {
-		ERROR("Wrong context. Expected %d, got %d\n",
+		ERROR("Wrong context. Expected %x, got %x\n",
 		      expected->exec_context,
 		      info->exec_context);
 		result = false;
 	}
 	if (info->properties != expected->properties) {
-		ERROR("Wrong properties. Expected %d, got %d\n",
+		ERROR("Wrong properties. Expected %x, got %x\n",
 		      expected->properties,
 		      info->properties);
 		result = false;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
index 8ca57f9..5effe53 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -45,6 +45,7 @@
 		.exec_context = PRIMARY_EXEC_CTX_COUNT,
 		.properties = FFA_PARTITION_AARCH64_EXEC |
 			      FFA_PARTITION_DIRECT_REQ_RECV |
+			      FFA_PARTITION_INDIRECT_MSG |
 			      FFA_PARTITION_NOTIFICATION,
 		.uuid = {PRIMARY_UUID}
 	},
@@ -95,6 +96,7 @@
 			FFA_VERSION_1_1},
 		{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_ERROR, 0,
 			FFA_VERSION_1_1},
+		{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
 	};
 	unsigned int test_target_size =
 		get_ffa_feature_test_target(&func_ids_target);
diff --git a/tftf/tests/tests-asymmetric-features.xml b/tftf/tests/tests-asymmetric-features.xml
index 413ef2c..29dfd7a 100644
--- a/tftf/tests/tests-asymmetric-features.xml
+++ b/tftf/tests/tests-asymmetric-features.xml
@@ -8,7 +8,9 @@
 
 <testsuites>
   <testsuite name="Asymmetric Features" description="Asymmetric features support">
-      <testcase name="Asymmetric Features"
-                function="test_asymmetric_features" />
+      <testcase name="TRBE Errata Asymmetric Test"
+                function="test_trbe_errata_asymmetric" />
+      <testcase name="Asymmetric SPE Test"
+                function="test_spe_asymmetric" />
   </testsuite>
 </testsuites>
diff --git a/tftf/tests/tests-versal2.mk b/tftf/tests/tests-versal2.mk
new file mode 100644
index 0000000..a76fdb7
--- /dev/null
+++ b/tftf/tests/tests-versal2.mk
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+TESTS_SOURCES   +=      $(addprefix tftf/tests/plat/amd/versal2/,          \
+	        test_all_cores.c                                           \
+		)
diff --git a/tftf/tests/tests-versal2.xml b/tftf/tests/tests-versal2.xml
new file mode 100644
index 0000000..1a47586
--- /dev/null
+++ b/tftf/tests/tests-versal2.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+  <!--
+     The "template" testsuite aims at providing template test code as a
+     starting point for developing new tests. These tests don't do anything
+     useful in terms of testing.
+  -->
+  <testsuite name="Versal2 Tests" description="AMD-Xilinx Versal2 platform test code">
+     <testcase name="Multi core test" function="test_power_on_cores" />
+  </testsuite>
+
+</testsuites>