Add support for pointer authentication

The previous commit added the infrastructure to load and save
ARMv8.3-PAuth registers during Non-secure <-> Secure world switches, but
didn't actually enable pointer authentication in the firmware.

This patch adds the functionality needed for platforms to provide
authentication keys for the firmware, and a new option (ENABLE_PAUTH) to
enable pointer authentication in the firmware itself. This option is
disabled by default, and it requires CTX_INCLUDE_PAUTH_REGS to be
enabled.

Change-Id: I35127ec271e1198d43209044de39fa712ef202a5
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/common/bl_common.c b/common/bl_common.c
index 84ff99c..4e76dd3 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
@@ -243,3 +244,53 @@
 #endif
 #undef PRINT_IMAGE_ARG
 }
+
+#ifdef AARCH64
+/*******************************************************************************
+ * Handle all possible cases regarding ARMv8.3-PAuth.
+ ******************************************************************************/
+void bl_handle_pauth(void)
+{
+#if ENABLE_PAUTH
+	/*
+	 * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1
+	 *
+	 * Check that the system supports address authentication to avoid
+	 * getting an access fault when accessing the registers. This is all
+	 * that is needed to check. If any of the authentication mechanisms is
+	 * supported, the system knows about ARMv8.3-PAuth, so all the registers
+	 * are available and accessing them won't generate a fault.
+	 *
+	 * Obtain 128-bit instruction key A from the platform and save it to the
+	 * system registers. Pointer authentication can't be enabled here or the
+	 * authentication will fail when returning from this function.
+	 */
+	assert(is_armv8_3_pauth_api_present());
+
+	uint64_t *apiakey = plat_init_apiakey();
+
+	write_apiakeylo_el1(apiakey[0]);
+	write_apiakeyhi_el1(apiakey[1]);
+#else /* if !ENABLE_PAUTH */
+
+# if CTX_INCLUDE_PAUTH_REGS
+	/*
+	 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1
+	 *
+	 * Assert that the ARMv8.3-PAuth registers are present or an access
+	 * fault will be triggered when they are being saved or restored.
+	 */
+	assert(is_armv8_3_pauth_present());
+# else
+	/*
+	 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0
+	 *
+	 * Pointer authentication is allowed in the Non-secure world, but
+	 * prohibited in the Secure world. The Trusted Firmware doesn't save the
+	 * registers during a world switch. No check needed.
+	 */
+# endif /* CTX_INCLUDE_PAUTH_REGS */
+
+#endif /* ENABLE_PAUTH */
+}
+#endif /* AARCH64 */