Tegra194: mce: enable strict checking

"Strict checking" is a mode where secure world can access
secure-only areas unlike legacy mode where secure world could
access non-secure spaces as well. Secure-only areas are defined
as the TZ-DRAM carveout and any GSC with the CPU_SECURE bit set.
This mode not only helps prevent issues with IO-Coherency but aids
with security as well.

This patch implements the programming sequence required to enable
strict checking mode for Tegra194 SoCs.

Change-Id: Ic2e594f79ec7c5bc1339b509e67c4c62efb9d0c0
Signed-off-by: Dilan Lee <dilee@nvidia.com>
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
index 1970a2d..3994b2d 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
@@ -36,6 +36,12 @@
  ******************************************************************************/
 #define MCE_STAT_ID_SHIFT			16U
 
+/*******************************************************************************
+ * Security config macros
+ ******************************************************************************/
+#define STRICT_CHECKING_ENABLED_SET		(1UL << 0)
+#define STRICT_CHECKING_LOCKED_SET		(1UL << 1)
+
 /* declarations for NVG handler functions */
 uint64_t nvg_get_version(void);
 int32_t nvg_enable_power_perf_mode(void);
@@ -54,12 +60,16 @@
 int32_t nvg_roc_flush_cache(void);
 int32_t nvg_roc_clean_cache_trbits(void);
 int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time);
-
 void nvg_set_request_data(uint64_t req, uint64_t data);
 void nvg_set_request(uint64_t req);
 uint64_t nvg_get_result(void);
 uint64_t nvg_cache_clean(void);
 uint64_t nvg_cache_clean_inval(void);
 uint64_t nvg_cache_inval_all(void);
+int32_t nvg_roc_clean_cache_trbits(void);
+void nvg_enable_strict_checking_mode(void);
+
+/* MCE helper functions */
+void mce_enable_strict_checking(void);
 
 #endif /* __MCE_PRIVATE_H__ */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
index 8c7854e..ba8436b 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
@@ -21,6 +21,7 @@
 #include <t194_nvg.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
+#include <tegra_private.h>
 
 /* Handler to check if MCE firmware is supported */
 static bool mce_firmware_not_supported(void)
@@ -184,3 +185,53 @@
 		panic();
 	}
 }
+
+/*******************************************************************************
+ * Handler to enable the strict checking mode
+ ******************************************************************************/
+void mce_enable_strict_checking(void)
+{
+	uint64_t sctlr = read_sctlr_el3();
+	int32_t ret = 0;
+
+	if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
+		/*
+		 * Step1: TZ-DRAM and TZRAM should be setup before the MMU is
+		 * enabled.
+		 *
+		 * The common code makes sure that TZDRAM/TZRAM are already
+		 * enabled before calling into this handler. If this is not the
+		 * case, the following sequence must be executed before moving
+		 * on to step 2.
+		 *
+		 * tlbialle1is();
+		 * tlbialle3is();
+		 * dsbsy();
+		 * isb();
+		 *
+		 */
+		if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) {
+			tlbialle1is();
+			tlbialle3is();
+			dsbsy();
+			isb();
+		}
+
+		/*
+		 * Step2: SCF flush - Clean and invalidate caches and clear the
+		 * TR-bits
+		 */
+		ret = nvg_roc_clean_cache_trbits();
+		if (ret < 0) {
+			ERROR("%s: flush cache_trbits failed(%d)\n", __func__,
+				ret);
+			return;
+		}
+
+		/*
+		 * Step3: Issue the SECURITY_CONFIG request to MCE to enable
+		 * strict checking mode.
+		 */
+		nvg_enable_strict_checking_mode();
+	}
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
index 96b2b91..1dd1f51 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
@@ -284,3 +284,16 @@
 
 	return ret;
 }
+
+/*
+ * Enable strict checking mode
+ *
+ * NVGDATA[3] strict_check ON + lock
+ */
+void nvg_enable_strict_checking_mode(void)
+{
+	uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
+				     STRICT_CHECKING_LOCKED_SET);
+
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_SECURITY_CONFIG, params);
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 6facc18..948fade 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -17,6 +17,7 @@
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/psci/psci.h>
 #include <mce.h>
+#include <mce_private.h>
 #include <plat/common/platform.h>
 #include <se.h>
 #include <smmu.h>
@@ -356,6 +357,13 @@
 	 * context if we are.
 	 */
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+		/*
+		 * Enable strict checking after programming the GSC for
+		 * enabling TZSRAM and TZDRAM
+		 */
+		mce_enable_strict_checking();
+
 		/* Init SMMU */
 		tegra_smmu_init();
 
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index 4b6ec8e..278dabe 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -19,6 +19,7 @@
 #include <drivers/arm/gicv2.h>
 #include <bl31/interrupt_mgmt.h>
 #include <mce.h>
+#include <mce_private.h>
 #include <plat/common/platform.h>
 #include <tegra_def.h>
 #include <tegra_mc_def.h>
@@ -257,3 +258,12 @@
 
 	return (plat_params_from_bl2_t *)(uintptr_t)val;
 }
+
+void plat_late_platform_setup(void)
+{
+	/*
+	 * Enable strict checking after programming the GSC for
+	 * enabling TZSRAM and TZDRAM
+	 */
+	mce_enable_strict_checking();
+}