feat(cpufeat): add support for FEAT_PAUTH_LR

This patch enables FEAT_PAUTH_LR at EL3 on systems that support it when
the new ENABLE_FEAT_PAUTH_LR flag is set.

Currently, PAUTH_LR is only supported by arm clang compiler and not GCC.

Change-Id: I7db1e34b661ed95cad75850b62878ac5d98466ea
Signed-off-by: John Powell <john.powell@arm.com>
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3707520..83e5867 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -606,6 +606,11 @@
 #define SCTLR_EPAN_BIT		(ULL(1) << 57)
 #define SCTLR_RESET_VAL		SCTLR_EL3_RES1
 
+#define SCTLR2_EnPACM_BIT	(ULL(1) << 7)
+
+/* SCTLR2 currently has no RES1 fields so reset to 0 */
+#define SCTLR2_RESET_VAL	ULL(0)
+
 /* CPACR_EL1 definitions */
 #define CPACR_EL1_FPEN(x)	((x) << 20)
 #define CPACR_EL1_FP_TRAP_EL0	UL(0x1)
@@ -855,6 +860,7 @@
 #define SPSR_PPEND_BIT		BIT(33)
 #define SPSR_EXLOCK_BIT_AARCH64	BIT_64(34)
 #define SPSR_NZCV		(SPSR_V_BIT | SPSR_C_BIT | SPSR_Z_BIT | SPSR_N_BIT)
+#define SPSR_PACM_BIT_AARCH64	BIT_64(35)
 
 #define DISABLE_ALL_EXCEPTIONS \
 		(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT)
@@ -1531,6 +1537,7 @@
 /*******************************************************************************
  * FEAT_SCTLR2 - Extension to SCTLR_ELx Registers
  ******************************************************************************/
+#define SCTLR2_EL3		S3_6_C1_C0_3
 #define SCTLR2_EL2		S3_4_C1_C0_3
 #define SCTLR2_EL1		S3_0_C1_C0_3
 
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index e3068d1..757ce06 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -146,6 +146,8 @@
  * +----------------------------+
  * |	FEAT_MOPS		|
  * +----------------------------+
+ * |	FEAT_PAUTH_LR		|
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -196,6 +198,35 @@
 CREATE_FEATURE_SUPPORTED(feat_pauth, is_feat_pauth_present, ENABLE_PAUTH)
 CREATE_FEATURE_SUPPORTED(ctx_pauth, is_feat_pauth_present, CTX_INCLUDE_PAUTH_REGS)
 
+/*
+ * FEAT_PAUTH_LR
+ * This feature has a non-standard discovery method so define this function
+ * manually then call use the CREATE_FEATURE_SUPPORTED macro with it. This
+ * feature is enabled with ENABLE_PAUTH when present.
+ */
+__attribute__((always_inline))
+static inline bool is_feat_pauth_lr_present(void)
+{
+	/*
+	 * FEAT_PAUTH_LR support is indicated by up to 3 fields, if one or more
+	 * of these is 0b0110 then the feature is present.
+	 *   1) id_aa64isr1_el1.api
+	 *   2) id_aa64isr1_el1.apa
+	 *   3) id_aa64isr2_el1.apa3
+	 */
+	if (ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_API_SHIFT, ID_AA64ISAR1_API_MASK) == 0b0110) {
+		return true;
+	}
+	if (ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_APA_SHIFT, ID_AA64ISAR1_APA_MASK) == 0b0110) {
+		return true;
+	}
+	if (ISOLATE_FIELD(read_id_aa64isar2_el1(), ID_AA64ISAR2_APA3_SHIFT, ID_AA64ISAR2_APA3_MASK) == 0b0110) {
+		return true;
+	}
+	return false;
+}
+CREATE_FEATURE_SUPPORTED(feat_pauth_lr, is_feat_pauth_lr_present, ENABLE_FEAT_PAUTH_LR)
+
 /* FEAT_TTST: Small translation tables */
 CREATE_FEATURE_PRESENT(feat_ttst, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_ST_SHIFT,
 			ID_AA64MMFR2_EL1_ST_MASK, 1U)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 9419583..50a5832 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -733,6 +733,7 @@
 /* FEAT_SCTLR2 Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el3, SCTLR2_EL3)
 
 /* FEAT_LS64_ACCDATA Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(accdata_el1, ACCDATA_EL1)
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index da51bf8..078c414 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -351,6 +351,11 @@
 	tst	\reg, \clobber
 	.endm
 
+	.macro is_feat_sctlr2_present_asm reg:req
+	mrs	\reg, ID_AA64MMFR3_EL1
+	ands	\reg, \reg, #(ID_AA64MMFR3_EL1_SCTLR2_MASK << ID_AA64MMFR3_EL1_SCTLR2_SHIFT)
+	.endm
+
 .macro call_reset_handler
 #if !(defined(IMAGE_BL2) && ENABLE_RME)
 	/* ---------------------------------------------------------------------
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 07dffb1..fce0f2c 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -45,6 +45,16 @@
 	msr	sctlr_el3, x0
 	isb
 
+#if ENABLE_FEAT_SCTLR2
+#if ENABLE_FEAT_SCTLR2 > 1
+	is_feat_sctlr2_present_asm x1
+	beq	feat_sctlr2_not_supported\@
+#endif
+	mov	x1, #SCTLR2_RESET_VAL
+	msr	SCTLR2_EL3, x1
+feat_sctlr2_not_supported\@:
+#endif
+
 #ifdef IMAGE_BL31
 	/* ---------------------------------------------------------------------
 	 * Initialise the per-cpu cache pointer to the CPU.