test(tftf): test PAuth in Realm

- Enable PAuth in Realm RL1 by default.
- Check if PAuth keys are accessible in Realm RL1.
- Check if Realm PAuth keys are preserved across RMM entry/exit.
- Check if NS PAuth keys are preserved across RMM entry/exit.
- Generate PAuth fault by cloberring LR.

Signed-off-by: Shruti Gupta <shruti.gupta@arm.com>
Change-Id: I85d8e03ec604c96117555e7aa866453cb2745cfe
diff --git a/lib/extensions/pauth/aarch64/pauth.c b/lib/extensions/pauth/aarch64/pauth.c
index 03de468..90e16d5 100644
--- a/lib/extensions/pauth/aarch64/pauth.c
+++ b/lib/extensions/pauth/aarch64/pauth.c
@@ -6,7 +6,18 @@
 
 #include <arch_helpers.h>
 #include <cdefs.h>
+#include <stdbool.h>
 #include <stdint.h>
+#include <debug.h>
+#include <pauth.h>
+
+/* Number of ARMv8.3-PAuth keys */
+#define NUM_KEYS        5U
+
+static const char * const key_name[] = {"IA", "IB", "DA", "DB", "GA"};
+
+static uint128_t pauth_keys_before[NUM_KEYS];
+static uint128_t pauth_keys_after[NUM_KEYS];
 
 /*
  * This is only a toy implementation to generate a seemingly random
@@ -24,3 +35,151 @@
 
 	return ((uint128_t)(key_hi) << 64) | key_lo;
 }
+
+/* Check if ARMv8.3-PAuth key is enabled */
+static bool is_pauth_key_enabled(uint64_t key_bit)
+{
+	unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
+
+	if (el == 1U) {
+		return ((read_sctlr_el1() & key_bit) != 0U);
+	} else if (el == 2U) {
+		return ((read_sctlr_el2() & key_bit) != 0U);
+	}
+	return false;
+}
+
+bool pauth_test_lib_compare_template(void)
+{
+	bool result = true;
+
+	pauth_test_lib_read_keys();
+	for (unsigned int i = 0U; i < NUM_KEYS; ++i) {
+		if (pauth_keys_before[i] != pauth_keys_after[i]) {
+			ERROR("AP%sKey_EL1 read 0x%llx:%llx "
+			"expected 0x%llx:%llx\n", key_name[i],
+			(uint64_t)(pauth_keys_after[i] >> 64U),
+			(uint64_t)(pauth_keys_after[i]),
+			(uint64_t)(pauth_keys_before[i] >> 64U),
+			(uint64_t)(pauth_keys_before[i]));
+
+			result = false;
+		}
+	}
+	return result;
+}
+
+/*
+ * Program or read ARMv8.3-PAuth keys (if already enabled)
+ * and store them in <pauth_keys_before> buffer
+ */
+void pauth_test_lib_fill_regs_and_template(void)
+{
+	uint128_t plat_key;
+
+	(void)memset(pauth_keys_before, 0, NUM_KEYS * sizeof(uint128_t));
+
+	if (is_pauth_key_enabled(SCTLR_EnIA_BIT)) {
+		/* Read APIAKey_EL1 */
+		plat_key = read_apiakeylo_el1() |
+			((uint128_t)(read_apiakeyhi_el1()) << 64U);
+		INFO("EnIA is set\n");
+	} else {
+		/* Program APIAKey_EL1 */
+		plat_key = init_apkey();
+		write_apiakeylo_el1((uint64_t)plat_key);
+		write_apiakeyhi_el1((uint64_t)(plat_key >> 64U));
+	}
+	pauth_keys_before[0] = plat_key;
+
+	if (is_pauth_key_enabled(SCTLR_EnIB_BIT)) {
+		/* Read APIBKey_EL1 */
+		plat_key = read_apibkeylo_el1() |
+			((uint128_t)(read_apibkeyhi_el1()) << 64U);
+		INFO("EnIB is set\n");
+	} else {
+		/* Program APIBKey_EL1 */
+		plat_key = init_apkey();
+		write_apibkeylo_el1((uint64_t)plat_key);
+		write_apibkeyhi_el1((uint64_t)(plat_key >> 64U));
+	}
+	pauth_keys_before[1] = plat_key;
+
+	if (is_pauth_key_enabled(SCTLR_EnDA_BIT)) {
+		/* Read APDAKey_EL1 */
+		plat_key = read_apdakeylo_el1() |
+			((uint128_t)(read_apdakeyhi_el1()) << 64U);
+		INFO("EnDA is set\n");
+	} else {
+		/* Program APDAKey_EL1 */
+		plat_key = init_apkey();
+		write_apdakeylo_el1((uint64_t)plat_key);
+		write_apdakeyhi_el1((uint64_t)(plat_key >> 64U));
+	}
+	pauth_keys_before[2] = plat_key;
+
+	if (is_pauth_key_enabled(SCTLR_EnDB_BIT)) {
+		/* Read APDBKey_EL1 */
+		plat_key = read_apdbkeylo_el1() |
+			((uint128_t)(read_apdbkeyhi_el1()) << 64U);
+		INFO("EnDB is set\n");
+	} else {
+		/* Program APDBKey_EL1 */
+		plat_key = init_apkey();
+		write_apdbkeylo_el1((uint64_t)plat_key);
+		write_apdbkeyhi_el1((uint64_t)(plat_key >> 64U));
+	}
+	pauth_keys_before[3] = plat_key;
+
+	pauth_keys_before[4] = read_apgakeylo_el1() |
+			       ((uint128_t)(read_apgakeyhi_el1()) << 64U);
+	if (pauth_keys_before[4] == 0ULL) {
+		/* Program APGAKey_EL1 */
+		plat_key = init_apkey();
+		write_apgakeylo_el1((uint64_t)plat_key);
+		write_apgakeyhi_el1((uint64_t)(plat_key >> 64U));
+		pauth_keys_before[4] = plat_key;
+	}
+
+	isb();
+}
+
+/*
+ * Read ARMv8.3-PAuth keys and store them in
+ * <pauth_keys_after> buffer
+ */
+void pauth_test_lib_read_keys(void)
+{
+	(void)memset(pauth_keys_after, 0, NUM_KEYS * sizeof(uint128_t));
+
+	/* Read APIAKey_EL1 */
+	pauth_keys_after[0] = read_apiakeylo_el1() |
+		((uint128_t)(read_apiakeyhi_el1()) << 64U);
+
+	/* Read APIBKey_EL1 */
+	pauth_keys_after[1] = read_apibkeylo_el1() |
+		((uint128_t)(read_apibkeyhi_el1()) << 64U);
+
+	/* Read APDAKey_EL1 */
+	pauth_keys_after[2] = read_apdakeylo_el1() |
+		((uint128_t)(read_apdakeyhi_el1()) << 64U);
+
+	/* Read APDBKey_EL1 */
+	pauth_keys_after[3] = read_apdbkeylo_el1() |
+		((uint128_t)(read_apdbkeyhi_el1()) << 64U);
+
+	/* Read APGAKey_EL1 */
+	pauth_keys_after[4] = read_apgakeylo_el1() |
+		((uint128_t)(read_apgakeyhi_el1()) << 64U);
+}
+
+/* Test execution of ARMv8.3-PAuth instructions */
+void pauth_test_lib_test_intrs(void)
+{
+	/* Pointer authentication instructions */
+	__asm__ volatile (
+			"paciasp\n"
+			"autiasp\n"
+			"paciasp\n"
+			"xpaclri");
+}