feat(cm): add tests to validate EL1 regs during context switch

* This patch adds a test to verify the integrity of the el1_context
  registers across world-switch.

* It aims at testing the save and restore functionality provided
  by the EL3 context management library.

* It validates the EL1 ctx register entries after interaction with
  TSP (S-EL1) software.

Change-Id: Id435d9d7699231d66e9e7acdbb3459ec439d2aef
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index 0bae3cf..3bff5ed 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -95,6 +95,12 @@
 	lib/extensions/sve/aarch64/sve_helpers.S
 endif
 
+ifeq (${ARCH},aarch64)
+# Context Management Library support files
+FRAMEWORK_SOURCES	+=						\
+	lib/context_mgmt/aarch64/context_el1.c
+endif
+
 TFTF_LINKERFILE		:=	tftf/framework/tftf.ld.S
 
 
diff --git a/tftf/tests/context_mgmt_tests/el1/test_tsp_el1_context_mgmt.c b/tftf/tests/context_mgmt_tests/el1/test_tsp_el1_context_mgmt.c
new file mode 100644
index 0000000..78a6416
--- /dev/null
+++ b/tftf/tests/context_mgmt_tests/el1/test_tsp_el1_context_mgmt.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/context_mgmt/context_el1.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+#define TSP_MODIFY_WITH_DUMMY_VALUE	1
+#define TSP_RESTORE_WITH_DEFAULT	0
+
+#ifdef	__aarch64__
+/**
+ * Global place holders for the entire test
+ */
+static el1_ctx_regs_t el1_ctx_original = {0};
+static el1_ctx_regs_t el1_ctx_before_smc = {0};
+static el1_ctx_regs_t el1_ctx_after_eret = {0};
+#endif
+
+/**
+ * Public Function: test_tsp_el1_ctx_regs_ctx_mgmt.
+ *
+ * @Test_Aim: This Test aims to validate EL1 context registers are restored to
+ * correct values upon returning from context switch triggered by an Standard
+ * SMC to TSP. This will ensure the context-management library at EL3 precisely
+ * saves and restores the appropriate world specific context during world switch
+ * and prevents data leakage in all cases.
+ */
+test_result_t test_tsp_el1_regs_ctx_mgmt(void)
+{
+	SKIP_TEST_IF_AARCH32();
+
+#ifdef __aarch64__
+	smc_args tsp_svc_params;
+	smc_ret_values tsp_result = {0};
+	test_result_t ret_value;
+	bool result;
+
+	SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+	/**
+	 * 1. Read the values of EL1 registers and save them into the
+	 * global buffer before the world switch.
+	 * This will be safe copy of registers which will be restored
+	 * back at the end of the test.
+	 */
+	save_el1_sysregs_context(&el1_ctx_original);
+
+	/**
+	 * 2. Modify/Corrupt the EL1 registers with some dummy values.
+	 * This will be essential for the test to ensure registers are
+	 * accessed and modified in both the security states, which will
+	 * be an ideal usecase in realtime.
+	 */
+	modify_el1_context_sysregs(&el1_ctx_original, NS_CORRUPT_EL1_REGS);
+
+	/**
+	 * 3. Read the values of EL1 registers again after modification
+	 * and save them into an other buffer before the world switch.
+	 * This will be used for comparison at the later stage on ERET.
+	 */
+	save_el1_sysregs_context(&el1_ctx_before_smc);
+
+	/* 4. Standard SMC to TSP, to modify EL1 registers in secure world */
+	tsp_svc_params.fid = TSP_STD_FID(TSP_MODIFY_EL1_CTX);
+	tsp_svc_params.arg1 = TSP_MODIFY_WITH_DUMMY_VALUE;
+	tsp_result = tftf_smc(&tsp_svc_params);
+
+	/* Check the result of the TSP_MODIFY_EL1_CTX STD_SMC call */
+	if (tsp_result.ret0 != 0) {
+		ERROR("TSP_MODIFY_EL1_CTX returned wrong result: "
+				     "got %d expected: 0 \n",
+				     (unsigned int)tsp_result.ret0);
+		return TEST_RESULT_FAIL;
+	}
+
+	/**
+	 * 5. Read the values of EL1 registers and save them into
+	 * the global buffer after the ERET.
+	 */
+	save_el1_sysregs_context(&el1_ctx_after_eret);
+
+	/* 6. Validate the EL1 contexts */
+	result = compare_el1_contexts(&el1_ctx_before_smc, &el1_ctx_after_eret);
+
+	if (result) {
+		INFO("EL1 context is safely handled by the "
+					"EL3 Ctx-management Library\n");
+		ret_value = TEST_RESULT_SUCCESS;
+	} else {
+		ERROR("EL1 context is corrupted during world switch\n");
+		ret_value = TEST_RESULT_FAIL;
+
+		/* Print the saved EL1 context before world switch. */
+		INFO("EL1 context registers list before SMC in NWd:\n");
+		print_el1_sysregs_context(&el1_ctx_before_smc);
+
+		/* Print the saved EL1 context after ERET */
+		INFO("EL1 context registers list after ERET in NWd:\n");
+		print_el1_sysregs_context(&el1_ctx_after_eret);
+	}
+
+	/**
+	 * 7. Restore the EL1 registers to their original value in order
+	 * to avoid any unintended crash for next tests.
+	 */
+	modify_el1_context_sysregs(&el1_ctx_original, NS_RESTORE_EL1_REGS);
+
+	/* 8. Standard SMC to TSP, to restore EL1 regs in secure world */
+	tsp_svc_params.fid = TSP_STD_FID(TSP_MODIFY_EL1_CTX);
+	tsp_svc_params.arg1 = TSP_RESTORE_WITH_DEFAULT;
+	tsp_result = tftf_smc(&tsp_svc_params);
+
+	/* Check the result of the TSP_MODIFY_EL1_CTX STD_SMC call */
+	if (tsp_result.ret0 != 0) {
+		ERROR("TSP_MODIFY_EL1_CTX returned wrong result: "
+				     "got %d expected: 0 \n",
+				     (unsigned int)tsp_result.ret0);
+		return TEST_RESULT_FAIL;
+	}
+	return ret_value;
+
+#endif /* __aarch64__ */
+}
diff --git a/tftf/tests/tests-cpu-context-mgmt.mk b/tftf/tests/tests-cpu-context-mgmt.mk
new file mode 100644
index 0000000..0919f5f
--- /dev/null
+++ b/tftf/tests/tests-cpu-context-mgmt.mk
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	$(addprefix tftf/tests/,				\
+		context_mgmt_tests/el1/test_tsp_el1_context_mgmt.c		\
+)
diff --git a/tftf/tests/tests-cpu-context-mgmt.xml b/tftf/tests/tests-cpu-context-mgmt.xml
new file mode 100644
index 0000000..eb86f08
--- /dev/null
+++ b/tftf/tests/tests-cpu-context-mgmt.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2024, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+  <testsuite name="CPU Context Management" description="Validate CPU context switch between NWd and SWd">
+     <testcase name="Test EL1 regs preserved across context switch with TSP"
+               function="test_tsp_el1_regs_ctx_mgmt" />
+  </testsuite>
+</testsuites>