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/include/lib/context_mgmt/context_el1.h b/include/lib/context_mgmt/context_el1.h
new file mode 100644
index 0000000..6b516da
--- /dev/null
+++ b/include/lib/context_mgmt/context_el1.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CONTEXT_EL1_H
+#define CONTEXT_EL1_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <tftf_lib.h>
+
+#define NS_CORRUPT_EL1_REGS		1
+#define NS_RESTORE_EL1_REGS		0
+/**
+ * Structure template to define individual EL1 register.
+ */
+typedef struct el1_reg {
+	char *reg_name;
+	uint64_t reg_value;
+} el1_reg_t;
+
+/*******************************************************************************
+ * EL1 Registers:
+ * AArch64 EL1 system registers which are intended to be saved and restored as
+ * part of context management library during world switch.
+ ******************************************************************************/
+
+typedef struct el1_common_regs {
+	el1_reg_t spsr_el1;
+	el1_reg_t elr_el1;
+	el1_reg_t sctlr_el1;
+	el1_reg_t tcr_el1;
+	el1_reg_t cpacr_el1;
+	el1_reg_t csselr_el1;
+	el1_reg_t sp_el1;
+	el1_reg_t esr_el1;
+	el1_reg_t ttbr0_el1;
+	el1_reg_t ttbr1_el1;
+	el1_reg_t mair_el1;
+	el1_reg_t amair_el1;
+	el1_reg_t actlr_el1;
+	el1_reg_t tpidr_el1;
+	el1_reg_t tpidr_el0;
+	el1_reg_t tpidrro_el0;
+	el1_reg_t par_el1;
+	el1_reg_t far_el1;
+	el1_reg_t afsr0_el1;
+	el1_reg_t afsr1_el1;
+	el1_reg_t contextidr_el1;
+	el1_reg_t vbar_el1;
+	el1_reg_t mdccint_el1;
+	el1_reg_t mdscr_el1;
+} el1_common_regs_t;
+
+typedef struct el1_aarch32_regs {
+	el1_reg_t spsr_abt;
+	el1_reg_t spsr_und;
+	el1_reg_t spsr_irq;
+	el1_reg_t spsr_fiq;
+	el1_reg_t dacr32_el2;
+	el1_reg_t ifsr32_el2;
+} el1_aarch32_regs_t;
+
+typedef struct el1_arch_timer_regs {
+	el1_reg_t cntp_ctl_el0;
+	el1_reg_t cntp_cval_el0;
+	el1_reg_t cntv_ctl_el0;
+	el1_reg_t cntv_cval_el0;
+	el1_reg_t cntkctl_el1;
+} el1_arch_timer_regs_t;
+
+typedef struct el1_mte2_regs {
+	el1_reg_t tfsre0_el1;
+	el1_reg_t tfsr_el1;
+	el1_reg_t rgsr_el1;
+	el1_reg_t gcr_el1;
+} el1_mte2_regs_t;
+
+typedef struct el1_ras_regs {
+	el1_reg_t disr_el1;
+} el1_ras_regs_t;
+
+typedef struct el1_s1pie_regs {
+	el1_reg_t pire0_el1;
+	el1_reg_t pir_el1;
+} el1_s1pie_regs_t;
+
+typedef struct el1_s1poe_regs {
+	el1_reg_t por_el1;
+} el1_s1poe_regs_t;
+
+typedef struct el1_s2poe_regs {
+	el1_reg_t s2por_el1;
+} el1_s2poe_regs_t;
+
+typedef struct el1_tcr2_regs {
+	el1_reg_t tcr2_el1;
+} el1_tcr2_regs_t;
+
+typedef struct el1_trf_regs {
+	el1_reg_t trfcr_el1;
+} el1_trf_regs_t;
+
+typedef struct el1_csv2_2_regs {
+	el1_reg_t scxtnum_el0;
+	el1_reg_t scxtnum_el1;
+} el1_csv2_2_regs_t;
+
+typedef struct el1_gcs_regs {
+	el1_reg_t gcscr_el1;
+	el1_reg_t gcscre0_el1;
+	el1_reg_t gcspr_el1;
+	el1_reg_t gcspr_el0;
+} el1_gcs_regs_t;
+typedef struct el1_ctx_regs {
+	el1_common_regs_t common;
+	el1_aarch32_regs_t el1_aarch32;
+	el1_arch_timer_regs_t arch_timer;
+	el1_mte2_regs_t mte2;
+	el1_ras_regs_t ras;
+	el1_s1pie_regs_t s1pie;
+	el1_s1poe_regs_t s1poe;
+	el1_s2poe_regs_t s2poe;
+	el1_tcr2_regs_t tcr2;
+	el1_trf_regs_t trf;
+	el1_csv2_2_regs_t csv2_2;
+	el1_gcs_regs_t gcs;
+} el1_ctx_regs_t;
+
+/*
+ * Helper macros to access and print members of the el1_ctx_regs_t structure.
+ */
+
+#define PRINT_CTX_MEM_SEPARATOR()						\
+		printf("+-----------------------+--------------------+\n");	\
+
+#define PRINT_CTX_MEMBER(feat, reg)					\
+	{								\
+		printf("|    %-15s    | 0x%016llx |\n", 		\
+			(feat->reg).reg_name, (feat->reg).reg_value);	\
+		PRINT_CTX_MEM_SEPARATOR();				\
+	}
+
+#define write_el1_ctx_reg(feat, reg, name, val)	\
+{						\
+	(feat->reg).reg_name = name;		\
+	(feat->reg).reg_value = (uint64_t)val;	\
+}
+
+/* Macros to access members of the 'el1_ctx_regs_t' structure */
+#define get_el1_common_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->common)
+#define get_el1_aarch32_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->el1_aarch32)
+#define get_el1_arch_timer_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->arch_timer)
+#define get_el1_mte2_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->mte2)
+#define get_el1_ras_regs_ctx(h)		(&((el1_ctx_regs_t *) h)->ras)
+#define get_el1_s1pie_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->s1pie)
+#define get_el1_s1poe_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->s1poe)
+#define get_el1_s2poe_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->s2poe)
+#define get_el1_tcr2_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->tcr2)
+#define get_el1_trf_regs_ctx(h)		(&((el1_ctx_regs_t *) h)->trf)
+#define get_el1_csv2_2_regs_ctx(h)	(&((el1_ctx_regs_t *) h)->csv2_2)
+#define get_el1_gcs_regs_ctx(h)		(&((el1_ctx_regs_t *) h)->gcs)
+
+/**
+ * --------------------------------------
+ * EL1 context accessor public functions.
+ * --------------------------------------
+ */
+void print_el1_sysregs_context(const el1_ctx_regs_t *el1_ctx);
+void save_el1_sysregs_context(const el1_ctx_regs_t *el1_ctx);
+void modify_el1_context_sysregs(const el1_ctx_regs_t *el1_ctx, const bool modify_option);
+bool compare_el1_contexts(const el1_ctx_regs_t *el1_ctx1, const el1_ctx_regs_t *el1_ctx2);
+
+#endif /* CONTEXT_EL1_H */