Introduce test to access pointer authentication register

EL3 runtime firmware currently enables unconditional access to pointer
authentication registers from lower EL [1]. The test performs a read
access on a pointer authentication system register to ensure that the
access is permitted from a lower EL, and doesn't result in a trap to
EL3.

[1] https://github.com/ARM-software/arm-trusted-firmware/commit/3ff4aaaca44b75504aec5ab5b72cd587a6fcd432

Change-Id: I893604ebcd9e5df830d97cce405c2a7518c0b23c
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 215730d..2da0630 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -159,6 +159,25 @@
 #define ID_AA64MMFR0_EL1_PARANGE_SHIFT	U(0)
 #define ID_AA64MMFR0_EL1_PARANGE_MASK	ULL(0xf)
 
+/* ID_AA64ISAR1_EL1 definitions */
+#define ID_AA64ISAR1_GPI_SHIFT	U(28)
+#define ID_AA64ISAR1_GPI_WIDTH	U(4)
+#define ID_AA64ISAR1_GPA_SHIFT	U(24)
+#define ID_AA64ISAR1_GPA_WIDTH	U(4)
+#define ID_AA64ISAR1_API_SHIFT	U(8)
+#define ID_AA64ISAR1_API_WIDTH	U(4)
+#define ID_AA64ISAR1_APA_SHIFT	U(4)
+#define ID_AA64ISAR1_APA_WIDTH	U(4)
+
+#define ID_AA64ISAR1_GPI_MASK \
+	(((ULL(1) << ID_AA64ISAR1_GPI_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPI_SHIFT)
+#define ID_AA64ISAR1_GPA_MASK \
+	(((ULL(1) << ID_AA64ISAR1_GPA_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPA_SHIFT)
+#define ID_AA64ISAR1_API_MASK \
+	(((ULL(1) << ID_AA64ISAR1_API_WIDTH) - ULL(1)) << ID_AA64ISAR1_API_SHIFT)
+#define ID_AA64ISAR1_APA_MASK \
+	(((ULL(1) << ID_AA64ISAR1_APA_WIDTH) - ULL(1)) << ID_AA64ISAR1_APA_SHIFT)
+
 #define PARANGE_0000	U(32)
 #define PARANGE_0001	U(36)
 #define PARANGE_0010	U(40)
@@ -618,4 +637,9 @@
 #define ERXPFGCTL_UEU_BIT	(1 << 2)
 #define ERXPFGCTL_CDEN_BIT	(1 << 31)
 
+/*******************************************************************************
+ * Armv8.3 Pointer Authentication Registers
+ *******************************************************************************/
+#define APGAKeyLo_EL1		S3_0_C2_C3_0
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index c313d60..0bd52de 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -128,6 +128,7 @@
  ******************************************************************************/
 
 DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
+DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
 DEFINE_SYSREG_READ_FUNC(CurrentEl)
 DEFINE_SYSREG_READ_FUNC(ctr_el0)
@@ -323,6 +324,9 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
 
+/* Armv8.3 Pointer Authentication Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(apgakeylo_el1, APGAKeyLo_EL1)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
 
diff --git a/tftf/tests/extensions/ptrauth/test_ptrauth_access.c b/tftf/tests/extensions/ptrauth/test_ptrauth_access.c
new file mode 100644
index 0000000..21efc18
--- /dev/null
+++ b/tftf/tests/extensions/ptrauth/test_ptrauth_access.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <arch_helpers.h>
+#include <stdbool.h>
+#include <tftf_lib.h>
+
+#ifndef AARCH32
+
+/*
+ * This function asserts that pointer authentication registers are accessible
+ * from lower ELs. If not permitted from EL3, the access will cause a crash.
+ */
+test_result_t test_ptrauth_access(void)
+{
+	bool has_ptrauth = false;
+	uint64_t id_aa64isar1 = read_id_aa64isar1_el1();
+
+	has_ptrauth = has_ptrauth || ((id_aa64isar1 & ID_AA64ISAR1_GPI_MASK) != 0U);
+	has_ptrauth = has_ptrauth || ((id_aa64isar1 & ID_AA64ISAR1_GPA_MASK) != 0U);
+	has_ptrauth = has_ptrauth || ((id_aa64isar1 & ID_AA64ISAR1_API_MASK) != 0U);
+	has_ptrauth = has_ptrauth || ((id_aa64isar1 & ID_AA64ISAR1_APA_MASK) != 0U);
+
+	if (!has_ptrauth) {
+		tftf_testcase_printf("Pointer authentication not supported.\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	(void) read_apgakeylo_el1();
+
+	return TEST_RESULT_SUCCESS;
+}
+
+#else
+
+test_result_t test_ptrauth_access(void)
+{
+	tftf_testcase_printf("Not supported on AArch32.\n");
+	return TEST_RESULT_SKIPPED;
+}
+
+#endif
diff --git a/tftf/tests/tests-ptrauth.mk b/tftf/tests/tests-ptrauth.mk
new file mode 100644
index 0000000..4e50d3a
--- /dev/null
+++ b/tftf/tests/tests-ptrauth.mk
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	tftf/tests/extensions/ptrauth/test_ptrauth_access.c
diff --git a/tftf/tests/tests-ptrauth.xml b/tftf/tests/tests-ptrauth.xml
new file mode 100644
index 0000000..a9179cf
--- /dev/null
+++ b/tftf/tests/tests-ptrauth.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2018, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+  <testsuite name="PtrAuth" description="Pointer Authentication">
+     <testcase name="Simple register access" function="test_ptrauth_access" />
+  </testsuite>
+</testsuites>