feat(rme): add SVE Realm tests

Verifies Realm with SVE support. Below tests are added
- Check whether RMI features reports proper SVE VL
- Create SVE Realm and check rdvl result
- Create SVE Realm with invalid VL and check if it fails
- Create SVE Realm and test ID registers
- Create non SVE Realm and test ID registers
- Create SVE Realm and probe all supported VLs
- Check RMM preserves NS ZCR_EL2 register

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I98a20f34ce72c7c1a353ed13678870168fa27c48
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index f3ff0ca..f3c98d8 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -140,6 +140,7 @@
 #define ID_AA64PFR0_AMU_V1P1	U(0x2)
 #define ID_AA64PFR0_ELX_MASK	ULL(0xf)
 #define ID_AA64PFR0_SVE_SHIFT	U(32)
+#define ID_AA64PFR0_SVE_WIDTH	U(4)
 #define ID_AA64PFR0_SVE_MASK	ULL(0xf)
 #define ID_AA64PFR0_SVE_LENGTH	U(4)
 #define ID_AA64PFR0_MPAM_SHIFT	U(40)
@@ -389,6 +390,11 @@
 #define CPACR_EL1_FP_TRAP_ALL	U(0x2)
 #define CPACR_EL1_FP_TRAP_NONE	U(0x3)
 
+#define CPACR_EL1_ZEN(x)	((x) << 16)
+#define CPACR_EL1_ZEN_TRAP_EL0	U(0x1)
+#define CPACR_EL1_ZEN_TRAP_ALL	U(0x2)
+#define CPACR_EL1_ZEN_TRAP_NONE	U(0x3)
+
 /* SCR definitions */
 #define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
 #define SCR_AMVOFFEN_BIT	(UL(1) << 35)
@@ -852,14 +858,17 @@
 /*******************************************************************************
  * Definitions for system register interface to SVE
  ******************************************************************************/
-#define ZCR_EL3			S3_6_C1_C2_0
-#define ZCR_EL2			S3_4_C1_C2_0
-
-/* ZCR_EL3 definitions */
-#define ZCR_EL3_LEN_MASK	U(0xf)
+#define ID_AA64ZFR0_EL1		S3_0_C0_C4_4
 
 /* ZCR_EL2 definitions */
-#define ZCR_EL2_LEN_MASK	U(0xf)
+#define ZCR_EL2			S3_4_C1_C2_0
+#define ZCR_EL2_SVE_VL_SHIFT	UL(0)
+#define ZCR_EL2_SVE_VL_WIDTH	UL(4)
+
+/* ZCR_EL1 definitions */
+#define ZCR_EL1			S3_0_C1_C2_0
+#define ZCR_EL1_SVE_VL_SHIFT	UL(0)
+#define ZCR_EL1_SVE_VL_WIDTH	UL(4)
 
 /*******************************************************************************
  * Definitions for system register interface to SME
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index b7c0418..77dc881 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -509,8 +509,10 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(pmbsr_el1, PMBSR_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(pmscr_el2, PMSCR_EL2)
 
-DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
-DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
+/* Definitions for system register interface to SVE */
+DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64zfr0_el1, ID_AA64ZFR0_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(zcr_el2, ZCR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(zcr_el1, ZCR_EL1)
 
 DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(svcr, SVCR)
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 07bd663..994fbfe 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,8 @@
 #ifndef SVE_H
 #define SVE_H
 
+#include <arch.h>
+
 #define fill_sve_helper(num) "ldr z"#num", [%0, #"#num", MUL VL];"
 #define read_sve_helper(num) "str z"#num", [%0, #"#num", MUL VL];"
 
@@ -17,10 +19,21 @@
 #define SVE_VECTOR_LEN_BYTES		256
 #define SVE_NUM_VECTORS			32
 
+#define SVE_VQ_ARCH_MAX			((1 << ZCR_EL2_SVE_VL_WIDTH) - 1)
+
+/* convert SVE VL in bytes to VQ */
+#define SVE_VL_TO_VQ(vl_bytes)		(((vl_bytes) >> 4U) - 1)
+
+/* convert SVE VQ to bits */
+#define SVE_VQ_TO_BITS(vq)		(((vq) + 1U) << 7U)
+
 #ifndef __ASSEMBLY__
 
 typedef uint8_t sve_vector_t[SVE_VECTOR_LEN_BYTES];
 
+void sve_config_vq(uint8_t sve_vq);
+uint32_t sve_probe_vl(uint8_t sve_max_vq);
+
 #ifdef __aarch64__
 
 /* Returns the SVE implemented VL in bytes (constrained by ZCR_EL3.LEN) */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 9dcf58d..8a54e60 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -162,7 +162,10 @@
 
 #define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory")
 
-#define MASK(regfield) \
+#define INPLACE(regfield, val)						\
+	(((val) + UL(0)) << (regfield##_SHIFT))
+
+#define MASK(regfield)							\
 	((~0ULL >> (64ULL - (regfield##_WIDTH))) << (regfield##_SHIFT))
 
 #define EXTRACT(regfield, reg) \
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 923c003..a208833 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -243,8 +243,10 @@
 
 #define RMI_FEATURE_REGISTER_0_S2SZ		GENMASK(7, 0)
 #define RMI_FEATURE_REGISTER_0_LPA2		BIT(8)
-#define RMI_FEATURE_REGISTER_0_SVE_EN		BIT(9)
-#define RMI_FEATURE_REGISTER_0_SVE_VL		GENMASK(13, 10)
+#define RMI_FEATURE_REGISTER_0_SVE_EN_SHIFT	UL(9)
+#define RMI_FEATURE_REGISTER_0_SVE_EN_WIDTH	UL(1)
+#define RMI_FEATURE_REGISTER_0_SVE_VL_SHIFT	UL(10)
+#define RMI_FEATURE_REGISTER_0_SVE_VL_WIDTH	UL(4)
 #define RMI_FEATURE_REGISTER_0_NUM_BPS		GENMASK(17, 14)
 #define RMI_FEATURE_REGISTER_0_NUM_WPS		GENMASK(21, 18)
 #define RMI_FEATURE_REGISTER_0_PMU_EN		BIT(22)
diff --git a/include/runtime_services/host_realm_managment/host_realm_sve.h b/include/runtime_services/host_realm_managment/host_realm_sve.h
new file mode 100644
index 0000000..8ec4cd7
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_realm_sve.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HOST_REALM_SVE_H
+#define HOST_REALM_SVE_H
+
+#include <stdint.h>
+
+struct sve_cmd_rdvl {
+	uint64_t rdvl;
+};
+
+struct sve_cmd_id_regs {
+	uint64_t id_aa64pfr0_el1;
+	uint64_t id_aa64zfr0_el1;
+};
+
+struct sve_cmd_probe_vl {
+	uint32_t vl_bitmap;
+};
+
+#endif /* HOST_REALM_SVE_H */
diff --git a/include/runtime_services/host_realm_managment/host_shared_data.h b/include/runtime_services/host_realm_managment/host_shared_data.h
index 7720334..cd19640 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -13,6 +13,8 @@
 #define MAX_BUF_SIZE		10240U
 #define MAX_DATA_SIZE		5U
 
+#define REALM_CMD_BUFFER_SIZE	1024U
+
 /*
  * This structure maps the shared memory to be used between the Host and Realm
  * payload
@@ -30,6 +32,9 @@
 	/* array of output results passed from Realm to Host */
 	u_register_t realm_out_val[MAX_DATA_SIZE];
 
+	/* Buffer to save Realm command results */
+	uint8_t realm_cmd_output_buffer[REALM_CMD_BUFFER_SIZE];
+
 	/* Lock to avoid concurrent accesses to log_buffer */
 	spinlock_t printf_lock;
 } host_shared_data_t;
@@ -45,7 +50,10 @@
 	REALM_PMU_PRESERVE,
 	REALM_PMU_INTERRUPT,
 	REALM_REQ_FPU_FILL_CMD,
-	REALM_REQ_FPU_CMP_CMD
+	REALM_REQ_FPU_CMP_CMD,
+	REALM_SVE_RDVL,
+	REALM_SVE_ID_REGISTERS,
+	REALM_SVE_PROBE_VL
 };
 
 /*
diff --git a/lib/extensions/sve/aarch64/sve.c b/lib/extensions/sve/aarch64/sve.c
new file mode 100644
index 0000000..698e78b
--- /dev/null
+++ b/lib/extensions/sve/aarch64/sve.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <lib/extensions/sve.h>
+
+static inline uint64_t sve_read_zcr_elx(void)
+{
+	return IS_IN_EL2() ? read_zcr_el2() : read_zcr_el1();
+}
+
+static inline void sve_write_zcr_elx(uint64_t reg_val)
+{
+	if (IS_IN_EL2()) {
+		write_zcr_el2(reg_val);
+	} else {
+		write_zcr_el1(reg_val);
+	}
+	isb();
+}
+
+static void _sve_config_vq(uint8_t sve_vq)
+{
+	u_register_t zcr_elx;
+
+	zcr_elx = sve_read_zcr_elx();
+	if (IS_IN_EL2()) {
+		zcr_elx &= ~(MASK(ZCR_EL2_SVE_VL));
+		zcr_elx |= INPLACE(ZCR_EL2_SVE_VL, sve_vq);
+	} else {
+		zcr_elx &= ~(MASK(ZCR_EL1_SVE_VL));
+		zcr_elx |= INPLACE(ZCR_EL1_SVE_VL, sve_vq);
+	}
+	sve_write_zcr_elx(zcr_elx);
+}
+
+/* Set the SVE vector length in the current EL's ZCR_ELx register */
+void sve_config_vq(uint8_t sve_vq)
+{
+	assert(is_armv8_2_sve_present());
+
+	/* cap vq to arch supported max value */
+	if (sve_vq > SVE_VQ_ARCH_MAX) {
+		sve_vq = SVE_VQ_ARCH_MAX;
+	}
+
+	_sve_config_vq(sve_vq);
+}
+
+/*
+ * Probes all valid vector length upto 'sve_max_vq'. Configures ZCR_ELx with 0
+ * to 'sve_max_vq'. And for each step, call sve_rdvl to get the vector length.
+ * Convert the vector length to VQ and set the bit corresponding to the VQ.
+ * Returns:
+ *	bitmap corresponding to each support VL
+ */
+uint32_t sve_probe_vl(uint8_t sve_max_vq)
+{
+	uint32_t vl_bitmap = 0;
+	uint8_t vq, rdvl_vq;
+
+	assert(is_armv8_2_sve_present());
+
+	/* cap vq to arch supported max value */
+	if (sve_max_vq > SVE_VQ_ARCH_MAX) {
+		sve_max_vq = SVE_VQ_ARCH_MAX;
+	}
+
+	for (vq = 0; vq <= sve_max_vq; vq++) {
+		_sve_config_vq(vq);
+		rdvl_vq = SVE_VL_TO_VQ(sve_vector_length_get());
+		if (vl_bitmap & BIT_32(rdvl_vq)) {
+			continue;
+		}
+		vl_bitmap |= BIT_32(rdvl_vq);
+	}
+
+	return vl_bitmap;
+}
diff --git a/realm/aarch64/realm_entrypoint.S b/realm/aarch64/realm_entrypoint.S
index 97c4ff5..0fd4f9b 100644
--- a/realm/aarch64/realm_entrypoint.S
+++ b/realm/aarch64/realm_entrypoint.S
@@ -72,6 +72,8 @@
 	mov	x1, CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)
 	mrs	x0, cpacr_el1
 	orr	x0, x0, x1
+	mov	x1, CPACR_EL1_ZEN(CPACR_EL1_ZEN_TRAP_NONE)
+	orr	x0, x0, x1
 	msr	cpacr_el1, x0
 	isb
 
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index 0e653ba..c1c780b 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -12,6 +12,9 @@
 bool test_pmuv3_event_works_realm(void);
 bool test_pmuv3_rmm_preserves(void);
 bool test_pmuv3_overflow_interrupt(void);
+bool test_realm_sve_rdvl(void);
+bool test_realm_sve_read_id_registers(void);
+bool test_realm_sve_probe_vl(void);
 
 #endif /* REALM_TESTS_H */
 
diff --git a/realm/realm.mk b/realm/realm.mk
index 923a687..e12f3e1 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -32,6 +32,7 @@
 	realm_pmuv3.c							\
 	realm_rsi.c							\
 	realm_shared_data.c						\
+	realm_sve.c							\
 	)
 
 REALM_SOURCES += lib/${ARCH}/cache_helpers.S				\
@@ -41,7 +42,8 @@
 	lib/exceptions/${ARCH}/sync.c					\
 	lib/locks/${ARCH}/spinlock.S					\
 	lib/delay/delay.c						\
-	lib/extensions/fpu/fpu.c
+	lib/extensions/fpu/fpu.c					\
+	lib/extensions/sve/aarch64/sve.c
 
 # TODO: Remove dependency on TFTF files.
 REALM_SOURCES	+=							\
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index c6665b4..f19dd3e 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -93,6 +93,14 @@
 			break;
 		case REALM_REQ_FPU_CMP_CMD:
 			test_succeed = fpu_state_compare_template(&fpu_temp_rl);
+		case REALM_SVE_RDVL:
+			test_succeed = test_realm_sve_rdvl();
+			break;
+		case REALM_SVE_ID_REGISTERS:
+			test_succeed = test_realm_sve_read_id_registers();
+			break;
+		case REALM_SVE_PROBE_VL:
+			test_succeed = test_realm_sve_probe_vl();
 			break;
 		default:
 			realm_printf("%s() invalid cmd %u\n", __func__, cmd);
diff --git a/realm/realm_sve.c b/realm/realm_sve.c
new file mode 100644
index 0000000..349b8d7
--- /dev/null
+++ b/realm/realm_sve.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <lib/extensions/sve.h>
+
+#include <host_realm_sve.h>
+#include <host_shared_data.h>
+
+/* Returns the maximum supported VL. This test is called only by sve Realm */
+bool test_realm_sve_rdvl(void)
+{
+	host_shared_data_t *sd = realm_get_shared_structure();
+	struct sve_cmd_rdvl *output;
+
+	assert(is_armv8_2_sve_present());
+
+	output = (struct sve_cmd_rdvl *)sd->realm_cmd_output_buffer;
+	memset((void *)output, 0, sizeof(struct sve_cmd_rdvl));
+
+	sve_config_vq(SVE_VQ_ARCH_MAX);
+	output->rdvl = sve_vector_length_get();
+
+	return true;
+}
+
+/*
+ * Reads and returns the ID_AA64PFR0_EL1 and ID_AA64ZFR0_EL1 registers
+ * This test could be called from sve or non-sve Realm
+ */
+bool test_realm_sve_read_id_registers(void)
+{
+	host_shared_data_t *sd = realm_get_shared_structure();
+	struct sve_cmd_id_regs *output;
+
+	output = (struct sve_cmd_id_regs *)sd->realm_cmd_output_buffer;
+	memset((void *)output, 0, sizeof(struct sve_cmd_id_regs));
+
+	realm_printf("Realm: reading ID registers: ID_AA64PFR0_EL1, "
+		    " ID_AA64ZFR0_EL1\n");
+	output->id_aa64pfr0_el1 = read_id_aa64pfr0_el1();
+	output->id_aa64zfr0_el1 = read_id_aa64zfr0_el1();
+
+	return true;
+}
+
+/*
+ * Probes all VLs and return the bitmap with the bit set for each corresponding
+ * valid VQ. This test is called only by sve Realm
+ */
+bool test_realm_sve_probe_vl(void)
+{
+	host_shared_data_t *sd = realm_get_shared_structure();
+	struct sve_cmd_probe_vl *output;
+
+	assert(is_armv8_2_sve_present());
+
+	output = (struct sve_cmd_probe_vl *)&sd->realm_cmd_output_buffer;
+	memset((void *)output, 0, sizeof(struct sve_cmd_probe_vl));
+
+	/* Probe all VLs */
+	output->vl_bitmap = sve_probe_vl(SVE_VQ_ARCH_MAX);
+
+	return true;
+}
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index 188e9af..ab9033a 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -87,7 +87,8 @@
 	lib/extensions/sme/aarch64/sme.c				\
 	lib/extensions/sme/aarch64/sme2.c				\
 	lib/extensions/sme/aarch64/sme_helpers.S			\
-	lib/extensions/sme/aarch64/sme2_helpers.S
+	lib/extensions/sme/aarch64/sme2_helpers.S			\
+	lib/extensions/sve/aarch64/sve.c
 endif
 
 TFTF_LINKERFILE		:=	tftf/framework/tftf.ld.S
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 e529c29..f535e11 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
@@ -215,7 +215,7 @@
 	/* Read Realm Feature Reg 0 */
 	if (host_rmi_features(0UL, &realm.rmm_feat_reg0) != REALM_SUCCESS) {
 		ERROR("%s() failed\n", "host_rmi_features");
-		goto destroy_realm;
+		return false;
 	}
 
 	/* Disable PMU if not required */
@@ -225,6 +225,16 @@
 			  RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS);
 	}
 
+	/* Set SVE bits from feature_flag */
+	realm.rmm_feat_reg0 &= ~(MASK(RMI_FEATURE_REGISTER_0_SVE_EN) |
+				 MASK(RMI_FEATURE_REGISTER_0_SVE_VL));
+	realm.rmm_feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_SVE_EN,
+				       EXTRACT(RMI_FEATURE_REGISTER_0_SVE_EN,
+					       feature_flag));
+	realm.rmm_feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_SVE_VL,
+				       EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL,
+					       feature_flag));
+
 	/* Create Realm */
 	if (host_realm_create(&realm) != REALM_SUCCESS) {
 		ERROR("%s() failed\n", "host_realm_create");
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_sve_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_sve_tests.c
new file mode 100644
index 0000000..554a497
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_sve_tests.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+#include <assert.h>
+#include <arch_features.h>
+#include <debug.h>
+#include <test_helpers.h>
+#include <lib/extensions/sve.h>
+
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_realm_sve.h>
+#include <host_shared_data.h>
+
+/* Skip test if SVE is not supported in H/W or in RMI features */
+#define CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(_reg0)				\
+	do {									\
+		SKIP_TEST_IF_SVE_NOT_SUPPORTED();				\
+										\
+		/* Get RMM support for SVE and its max SVE VL */		\
+		if (host_rmi_features(0UL, &_reg0) != REALM_SUCCESS) {		\
+			ERROR("Failed to get RMI feat_reg0\n");			\
+			return TEST_RESULT_FAIL;				\
+		}								\
+										\
+		/* SVE not supported in RMI features? */			\
+		if (EXTRACT(RMI_FEATURE_REGISTER_0_SVE_EN, _reg0) == 0UL) {	\
+			ERROR("SVE not in RMI features, skipping\n");		\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
+static test_result_t host_create_sve_realm_payload(bool sve_en, uint8_t sve_vq)
+{
+	u_register_t rmi_feat_reg0;
+
+	if (sve_en == true) {
+		rmi_feat_reg0 = INPLACE(RMI_FEATURE_REGISTER_0_SVE_EN, true);
+		rmi_feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_SVE_VL, sve_vq);
+	} else {
+		rmi_feat_reg0 = INPLACE(RMI_FEATURE_REGISTER_0_SVE_EN, false);
+	}
+
+	/* Initialise Realm payload */
+	if (!host_create_realm_payload((u_register_t)REALM_IMAGE_BASE,
+				       (u_register_t)PAGE_POOL_BASE,
+				       (u_register_t)(PAGE_POOL_MAX_SIZE +
+						      NS_REALM_SHARED_MEM_SIZE),
+				       (u_register_t)PAGE_POOL_MAX_SIZE,
+				       rmi_feat_reg0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Create shared memory between Host and Realm */
+	if (!host_create_shared_mem(NS_REALM_SHARED_MEM_BASE,
+				    NS_REALM_SHARED_MEM_SIZE)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * RMI should report SVE VL in RMI features and it must be the same value as the
+ * max SVE VL seen by the NS world.
+ */
+test_result_t host_check_rmi_reports_proper_sve_vl(void)
+{
+	u_register_t rmi_feat_reg0;
+	uint8_t rmi_sve_vq;
+	uint8_t ns_sve_vq;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+
+	rmi_sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+
+	/*
+	 * configure NS to arch supported max VL and get the value reported
+	 * by rdvl
+	 */
+	sve_config_vq(SVE_VQ_ARCH_MAX);
+	ns_sve_vq = SVE_VL_TO_VQ(sve_vector_length_get());
+
+	if (rmi_sve_vq != ns_sve_vq) {
+		ERROR("RMI max SVE VL %u bits doesn't matches NS max "
+		      "SVE VL %u bits\n", SVE_VQ_TO_BITS(rmi_sve_vq),
+		      SVE_VQ_TO_BITS(ns_sve_vq));
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/* Test Realm creation with SVE enabled and run command rdvl */
+test_result_t host_sve_realm_cmd_rdvl(void)
+{
+	host_shared_data_t *sd;
+	struct sve_cmd_rdvl *rl_output;
+	uint8_t sve_vq, rl_max_sve_vq;
+	u_register_t rmi_feat_reg0;
+	test_result_t rc;
+	bool realm_rc;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+
+	sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+
+	rc = host_create_sve_realm_payload(true, sve_vq);
+	if (rc != TEST_RESULT_SUCCESS) {
+		ERROR("Failed to create Realm with SVE\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	realm_rc = host_enter_realm_execute(REALM_SVE_RDVL, NULL,
+					    RMI_EXIT_HOST_CALL);
+	if (realm_rc != true) {
+		rc = TEST_RESULT_FAIL;
+		goto rm_realm;
+	}
+
+	/* check if rdvl matches the SVE VL created */
+	sd = host_get_shared_structure();
+	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) {
+		rc = TEST_RESULT_SUCCESS;
+	} else {
+		ERROR("Realm created with max VL: %u bits, but Realm reported "
+		      "max VL as: %u bits\n", SVE_VQ_TO_BITS(sve_vq),
+		      SVE_VQ_TO_BITS(rl_max_sve_vq));
+		rc = TEST_RESULT_FAIL;
+	}
+
+rm_realm:
+	if (!host_destroy_realm()) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return rc;
+}
+
+/* Test Realm creation with SVE enabled but with invalid SVE VL */
+test_result_t host_sve_realm_test_invalid_vl(void)
+{
+	u_register_t rmi_feat_reg0;
+	test_result_t rc;
+	uint8_t sve_vq;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+
+	sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+
+	/*
+	 * If RMM supports MAX SVE VQ, we can't pass in an invalid sve_vq to
+	 * create a realm, so skip the test. Else pass a sve_vq that is greater
+	 * than the value supported by RMM and check whether creating Realm fails
+	 */
+	if (sve_vq == SVE_VQ_ARCH_MAX) {
+		INFO("RMI supports arch max SVE VL, skipping\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	rc = host_create_sve_realm_payload(true, (sve_vq + 1));
+
+	if (rc == TEST_RESULT_SUCCESS) {
+		ERROR("Error: Realm created with invalid SVE VL\n");
+		host_destroy_realm();
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t _host_sve_realm_check_id_registers(bool sve_en)
+{
+	host_shared_data_t *sd;
+	struct sve_cmd_id_regs *r_regs;
+	u_register_t rmi_feat_reg0;
+	test_result_t rc;
+	bool realm_rc;
+	uint8_t sve_vq = 0U;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (sve_en) {
+		CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+		sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+	}
+
+	rc = host_create_sve_realm_payload(sve_en, sve_vq);
+	if (rc != TEST_RESULT_SUCCESS) {
+		return rc;
+	}
+
+	realm_rc = host_enter_realm_execute(REALM_SVE_ID_REGISTERS, NULL,
+					    RMI_EXIT_HOST_CALL);
+	if (!realm_rc) {
+		rc = TEST_RESULT_FAIL;
+		goto rm_realm;
+	}
+
+	sd = host_get_shared_structure();
+	r_regs = (struct sve_cmd_id_regs *)sd->realm_cmd_output_buffer;
+
+	/* Check ID register SVE flags */
+	if (sve_en) {
+		rc = TEST_RESULT_SUCCESS;
+		if (EXTRACT(ID_AA64PFR0_SVE, r_regs->id_aa64pfr0_el1) == 0UL) {
+			ERROR("ID_AA64PFR0_EL1: SVE not enabled\n");
+			rc = TEST_RESULT_FAIL;
+		}
+		if (r_regs->id_aa64zfr0_el1 == 0UL) {
+			ERROR("ID_AA64ZFR0_EL1: No SVE features present\n");
+			rc = TEST_RESULT_FAIL;
+		}
+	} else {
+		rc = TEST_RESULT_SUCCESS;
+		if (EXTRACT(ID_AA64PFR0_SVE, r_regs->id_aa64pfr0_el1) != 0UL) {
+			ERROR("ID_AA64PFR0_EL1: SVE enabled\n");
+			rc = TEST_RESULT_FAIL;
+		}
+		if (r_regs->id_aa64zfr0_el1 != 0UL) {
+			ERROR("ID_AA64ZFR0_EL1: Realm reported non-zero value\n");
+			rc = TEST_RESULT_FAIL;
+		}
+	}
+
+rm_realm:
+	host_destroy_realm();
+	return rc;
+}
+
+/* Test ID_AA64PFR0_EL1, ID_AA64ZFR0_EL1_SVE values in SVE Realm */
+test_result_t host_sve_realm_cmd_id_registers(void)
+{
+	return _host_sve_realm_check_id_registers(true);
+}
+
+/* Test ID_AA64PFR0_EL1, ID_AA64ZFR0_EL1_SVE values in non SVE Realm */
+test_result_t host_non_sve_realm_cmd_id_registers(void)
+{
+	return _host_sve_realm_check_id_registers(false);
+}
+
+static void print_sve_vl_bitmap(uint32_t vl_bitmap)
+{
+	uint8_t vq;
+
+	for (vq = 0U; vq <= SVE_VQ_ARCH_MAX; vq++) {
+		if ((vl_bitmap & BIT_32(vq)) != 0U) {
+			INFO("\t%u\n", SVE_VQ_TO_BITS(vq));
+		}
+	}
+}
+
+/* Create SVE Realm and probe all the supported VLs */
+test_result_t host_sve_realm_cmd_probe_vl(void)
+{
+	host_shared_data_t *sd;
+	struct sve_cmd_probe_vl *rl_output;
+	uint32_t vl_bitmap_expected;
+	u_register_t rmi_feat_reg0;
+	test_result_t rc;
+	bool realm_rc;
+	uint8_t sve_vq;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+
+	sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+
+	rc = host_create_sve_realm_payload(true, sve_vq);
+	if (rc != TEST_RESULT_SUCCESS) {
+		return rc;
+	}
+
+	/*
+	 * Configure TFTF with sve_vq and probe all VLs and compare it with
+	 * the bitmap returned from Realm
+	 */
+	vl_bitmap_expected = sve_probe_vl(sve_vq);
+
+	realm_rc = host_enter_realm_execute(REALM_SVE_PROBE_VL, NULL,
+					    RMI_EXIT_HOST_CALL);
+	if (!realm_rc) {
+		rc = TEST_RESULT_FAIL;
+		goto rm_realm;
+	}
+
+	sd = host_get_shared_structure();
+	rl_output = (struct sve_cmd_probe_vl *)sd->realm_cmd_output_buffer;
+
+	INFO("Supported SVE vector length in bits (expected):\n");
+	print_sve_vl_bitmap(vl_bitmap_expected);
+
+	INFO("Supported SVE vector length in bits (probed):\n");
+	print_sve_vl_bitmap(rl_output->vl_bitmap);
+
+	if (vl_bitmap_expected == rl_output->vl_bitmap) {
+		rc = TEST_RESULT_SUCCESS;
+	} else {
+		rc = TEST_RESULT_FAIL;
+	}
+
+rm_realm:
+	if (!host_destroy_realm()) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return rc;
+}
+
+/* Check whether RMM preserves NS ZCR_EL2 register. */
+test_result_t host_sve_realm_check_config_register(void)
+{
+	u_register_t ns_zcr_el2, ns_zcr_el2_cur;
+	u_register_t rmi_feat_reg0;
+	test_result_t rc;
+	uint8_t vq;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	CHECK_SVE_SUPPORT_IN_HW_AND_IN_RMI(rmi_feat_reg0);
+
+	vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
+
+	rc = host_create_sve_realm_payload(true, vq);
+	if (rc != TEST_RESULT_SUCCESS) {
+		return rc;
+	}
+
+	/*
+	 * Configure TFTF from 0 to SVE_VQ_ARCH_MAX, and in each iteration check
+	 * if NS ZCR_EL2 is same before and after call to run Realm.
+	 */
+	rc = TEST_RESULT_SUCCESS;
+	for (vq = 0U; vq <= SVE_VQ_ARCH_MAX; vq++) {
+		bool realm_rc;
+
+		sve_config_vq(vq);
+		ns_zcr_el2 = read_zcr_el2();
+
+		/* Call Realm to run SVE command */
+		realm_rc = host_enter_realm_execute(REALM_SVE_RDVL, NULL,
+						    RMI_EXIT_HOST_CALL);
+		if (!realm_rc) {
+			ERROR("Realm command REALM_SVE_RDVL failed\n");
+			rc = TEST_RESULT_FAIL;
+			break;
+		}
+		ns_zcr_el2_cur = read_zcr_el2();
+
+		if (ns_zcr_el2 != ns_zcr_el2_cur) {
+			ERROR("NS ZCR_EL2 expected: 0x%lx, got: 0x%lx\n",
+			      ns_zcr_el2, ns_zcr_el2_cur);
+			rc = TEST_RESULT_FAIL;
+		}
+	}
+
+	if (!host_destroy_realm()) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return rc;
+}
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index b3b7d4a..0e0d148 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -12,6 +12,7 @@
 	$(addprefix tftf/tests/runtime_services/realm_payload/,		\
 		host_realm_payload_tests.c				\
 		host_realm_spm.c					\
+		host_realm_payload_sve_tests.c				\
 	)
 
 TESTS_SOURCES	+=							\
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 7518934..4d4bf81 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -32,5 +32,20 @@
 	  function="host_realm_sec_interrupt_can_preempt_rl" />
 	  <testcase name="Check that FPU state registers context is preserved in RL/SE/NS"
 	  function="host_realm_fpu_access_in_rl_ns_se" />
+	  <!-- Test Realm with SVE support -->
+	  <testcase name="Check RMI reports proper SVE VL"
+	  function="host_check_rmi_reports_proper_sve_vl" />
+	  <testcase name="Create SVE Realm with invalid VL"
+	  function="host_sve_realm_test_invalid_vl" />
+	  <testcase name="Create SVE Realm and test ID registers"
+	  function="host_sve_realm_cmd_id_registers" />
+	  <testcase name="Create non SVE Realm and test ID registers"
+	  function="host_non_sve_realm_cmd_id_registers" />
+	  <testcase name="Create SVE Realm and check rdvl result"
+	  function="host_sve_realm_cmd_rdvl" />
+	  <testcase name="Create SVE Realm and probe all supported VLs"
+	  function="host_sve_realm_cmd_probe_vl" />
+	  <testcase name="Check whether RMM preserves NS ZCR_EL2 register"
+	  function="host_sve_realm_check_config_register" />
   </testsuite>
 </testsuites>