test(el3-runtime): dit is retained on world switch

Add tsp service to check the value of the PSTATE DIT bit is as
expected and toggle it's value. This is used to ensure that
the DIT bit is maintained during a switch from the Normal to
Secure worlds and back.

Change-Id: I4e8bdfa6530e5e75925c0079d4fa2795133c5105
Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index 55e1532..522c1b4 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -370,6 +370,7 @@
 	uint64_t service_arg1;
 	uint64_t results[2];
 	uint32_t linear_id = plat_my_core_pos();
+	u_register_t dit;
 
 	/* Update this cpu's statistics */
 	tsp_stats[linear_id].smc_count++;
@@ -424,6 +425,23 @@
 		results[0] /= service_arg0 ? service_arg0 : 1;
 		results[1] /= service_arg1 ? service_arg1 : 1;
 		break;
+	case TSP_CHECK_DIT:
+		if (!is_armv8_4_dit_present()) {
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+			spin_lock(&console_lock);
+			ERROR("DIT not supported\n");
+			spin_unlock(&console_lock);
+#endif
+			results[0] = 0;
+			results[1] = 0xffff;
+			break;
+		}
+		dit = read_dit();
+		results[0] = dit == service_arg0;
+		results[1] = dit;
+		/* Toggle the dit bit */
+		write_dit(service_arg0 != 0U ? 0 : DIT_BIT);
+		break;
 	default:
 		break;
 	}
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 46cd1c9..a260f03 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,12 @@
 	return (read_id_aa64isar1_el1() & mask) != 0U;
 }
 
+static inline bool is_armv8_4_dit_present(void)
+{
+	return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) &
+		ID_AA64PFR0_DIT_MASK) == 1U;
+}
+
 static inline bool is_armv8_4_ttst_present(void)
 {
 	return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 733bb23..009eb90 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -529,6 +529,9 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1)
 
+/* Armv8.4 Data Independent Timing Register */
+DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT)
+
 /* Armv8.5 MTE Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1)
diff --git a/include/bl32/tsp/tsp.h b/include/bl32/tsp/tsp.h
index 637e14a..285bfbe 100644
--- a/include/bl32/tsp/tsp.h
+++ b/include/bl32/tsp/tsp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,6 +41,7 @@
 #define TSP_MUL		0x2002
 #define TSP_DIV		0x2003
 #define TSP_HANDLE_SEL1_INTR_AND_RETURN	0x2004
+#define TSP_CHECK_DIT	0x2005
 
 /*
  * Identify a TSP service from function ID filtering the last 16 bits from the
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index 29fc238..6cb4992 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -570,6 +570,11 @@
 	case TSP_YIELD_FID(TSP_SUB):
 	case TSP_YIELD_FID(TSP_MUL):
 	case TSP_YIELD_FID(TSP_DIV):
+		/*
+		 * Request from non-secure client to perform a check
+		 * of the DIT PSTATE bit.
+		 */
+	case TSP_YIELD_FID(TSP_CHECK_DIT):
 		if (ns) {
 			/*
 			 * This is a fresh request from the non-secure client.