From ac252f95dd5089cfa9676d15a11018f8f41e692e Mon Sep 17 00:00:00 2001
From: Dilan Lee <dilee@nvidia.com>
Date: Thu, 10 Aug 2017 16:01:42 +0800
Subject: [PATCH] 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>
---
 .../soc/t194/drivers/include/mce_private.h    | 12 ++++-
 plat/nvidia/tegra/soc/t194/drivers/mce/mce.c  | 51 +++++++++++++++++++
 plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c  | 13 +++++
 .../tegra/soc/t194/plat_psci_handlers.c       |  8 +++
 plat/nvidia/tegra/soc/t194/plat_setup.c       | 10 ++++
 5 files changed, 93 insertions(+), 1 deletion(-)

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 1970a2d17..3994b2d75 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_clean_cache(void);
 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 8c7854e9c..ba8436be4 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 @@ void mce_verify_firmware_version(void)
 		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 96b2b9113..1dd1f51b9 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 @@ int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time)
 
 	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 6facc1860..948fadec9 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 @@ int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
 	 * 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 4b6ec8eaf..278dabe32 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 @@ plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
 
 	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();
+}
-- 
GitLab