SMMUv3: Abort DMA transactions

For security DMA should be blocked at the SMMU by default
unless explicitly enabled for a device. SMMU is disabled
after reset with all streams bypassing the SMMU, and
abortion of all incoming transactions implements a default
deny policy on reset.
This patch also moves "bl1_platform_setup()" function from
arm_bl1_setup.c to FVP platforms' fvp_bl1_setup.c and
fvp_ve_bl1_setup.c files.

Change-Id: Ie0ffedc10219b1b884eb8af625bd4b6753749b1a
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c
index ab2eb2b..5493b85 100644
--- a/drivers/arm/smmu/smmu_v3.c
+++ b/drivers/arm/smmu/smmu_v3.c
@@ -30,26 +30,63 @@
 }
 
 /*
+ * Abort all incoming transactions in order to implement a default
+ * deny policy on reset.
+ */
+int __init smmuv3_security_init(uintptr_t smmu_base)
+{
+	/* Attribute update has completed when SMMU_(S)_GBPA.Update bit is 0 */
+	if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
+		return -1;
+
+	/*
+	 * SMMU_(S)_CR0 resets to zero with all streams bypassing the SMMU,
+	 * so just abort all incoming transactions.
+	 */
+	mmio_setbits_32(smmu_base + SMMU_GBPA,
+			SMMU_GBPA_UPDATE | SMMU_GBPA_ABORT);
+
+	if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U)
+		return -1;
+
+	/* Check if the SMMU supports secure state */
+	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
+				SMMU_S_IDR1_SECURE_IMPL) == 0U)
+		return 0;
+
+	/* Abort all incoming secure transactions */
+	if (smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U) != 0U)
+		return -1;
+
+	mmio_setbits_32(smmu_base + SMMU_S_GBPA,
+			SMMU_S_GBPA_UPDATE | SMMU_S_GBPA_ABORT);
+
+	return smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U);
+}
+
+/*
  * Initialize the SMMU by invalidating all secure caches and TLBs.
  * Abort all incoming transactions in order to implement a default
  * deny policy on reset
  */
 int __init smmuv3_init(uintptr_t smmu_base)
 {
+	/* Abort all incoming transactions */
+	if (smmuv3_security_init(smmu_base) != 0)
+		return -1;
+
+	/* Check if the SMMU supports secure state */
+	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
+				SMMU_S_IDR1_SECURE_IMPL) == 0U)
+		return 0;
 	/*
-	 * Invalidation of secure caches and TLBs is required only if the SMMU
-	 * supports secure state. If not, it's implementation defined as to how
-	 * SMMU_S_INIT register is accessed.
+	 * Initiate invalidation of secure caches and TLBs if the SMMU
+	 * supports secure state. If not, it's implementation defined
+	 * as to how SMMU_S_INIT register is accessed.
 	 */
-	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
-			SMMU_S_IDR1_SECURE_IMPL) != 0U) {
-
-		/* Initiate invalidation */
-		mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL);
+	mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL);
 
-		/* Wait for global invalidation operation to finish */
-		return smmuv3_poll(smmu_base + SMMU_S_INIT,
-					SMMU_S_INIT_INV_ALL, 0U);
-	}
-	return 0;
+	/* Wait for global invalidation operation to finish */
+	return smmuv3_poll(smmu_base + SMMU_S_INIT,
+				SMMU_S_INIT_INV_ALL, 0U);
 }
diff --git a/include/drivers/arm/smmu_v3.h b/include/drivers/arm/smmu_v3.h
index 75c9465..a820a44 100644
--- a/include/drivers/arm/smmu_v3.h
+++ b/include/drivers/arm/smmu_v3.h
@@ -31,5 +31,6 @@
 #define SMMU_S_GBPA_ABORT		(1UL << 20)
 
 int smmuv3_init(uintptr_t smmu_base);
+int smmuv3_security_init(uintptr_t smmu_base);
 
 #endif /* SMMU_V3_H */
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index aa56716..420df45 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -1,11 +1,13 @@
 /*
- * 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
  */
 
 #include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/smmu_v3.h>
 #include <drivers/arm/sp805.h>
+#include <plat/arm/common/arm_config.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/common/arm_def.h>
 #include <plat/common/platform.h>
@@ -41,3 +43,12 @@
 {
 	sp805_stop(ARM_SP805_TWDG_BASE);
 }
+
+void bl1_platform_setup(void)
+{
+	arm_bl1_platform_setup();
+
+	/* On FVP RevC, initialize SMMUv3 */
+	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
+		smmuv3_security_init(PLAT_FVP_SMMUV3_BASE);
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 9b128a5..dbc5c21 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -119,7 +119,8 @@
 FVP_CPU_LIBS		+=	lib/cpus/aarch32/cortex_a32.S
 endif
 
-BL1_SOURCES		+=	drivers/arm/sp805/sp805.c			\
+BL1_SOURCES		+=	drivers/arm/smmu/smmu_v3.c			\
+				drivers/arm/sp805/sp805.c			\
 				drivers/io/io_semihosting.c			\
 				lib/semihosting/semihosting.c			\
 				lib/semihosting/${ARCH}/semihosting_call.S	\
diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
index 4338f6f..736cf42 100644
--- a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
+++ b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
@@ -26,3 +26,8 @@
 {
 	sp805_stop(ARM_SP805_TWDG_BASE);
 }
+
+void bl1_platform_setup(void)
+{
+	arm_bl1_platform_setup();
+}
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 8e0c046..8905bb0 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,7 +19,6 @@
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl1_early_platform_setup
 #pragma weak bl1_plat_arch_setup
-#pragma weak bl1_platform_setup
 #pragma weak bl1_plat_sec_mem_layout
 #pragma weak bl1_plat_prepare_exit
 #pragma weak bl1_plat_get_next_image_id
@@ -162,11 +161,6 @@
 #endif
 }
 
-void bl1_platform_setup(void)
-{
-	arm_bl1_platform_setup();
-}
-
 void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
 {
 #if !ARM_DISABLE_TRUSTED_WDOG