SMMUv3: Abort DMA transactions
authorAlexei Fedorov <Alexei.Fedorov@arm.com>
Thu, 9 May 2019 11:14:40 +0000 (12:14 +0100)
committerAlexei Fedorov <Alexei.Fedorov@arm.com>
Fri, 10 May 2019 15:09:19 +0000 (16:09 +0100)
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>
drivers/arm/smmu/smmu_v3.c
include/drivers/arm/smmu_v3.h
plat/arm/board/fvp/fvp_bl1_setup.c
plat/arm/board/fvp/platform.mk
plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
plat/arm/common/arm_bl1_setup.c

index ab2eb2bedec78f2b24481a11d01f5dba701680a3..5493b850a920a2e1677fa3df1cb7cc3dcb290518 100644 (file)
@@ -29,6 +29,41 @@ static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask,
        return -1;
 }
 
+/*
+ * 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
@@ -36,20 +71,22 @@ static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask,
  */
 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);
 }
index 75c9465af7ac48e13903f64329798fe47c6b95d7..a820a4421d64288aaf77276dfbd5277599766900 100644 (file)
@@ -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 */
index aa567166a1cf239fff424340dc177adfed300bff..420df45595b0af6c4cab1f07cc6f303ecba60fe9 100644 (file)
@@ -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 @@ void plat_arm_secure_wdt_stop(void)
 {
        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);
+}
index 9b128a564174aa28aced81bfa412c66842e7773a..dbc5c21ba6f5aad9b85c231b9d25bf81eff64272 100644 (file)
@@ -119,7 +119,8 @@ else
 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      \
index 4338f6f2a0a3826c24ab4319f7f98dac93b70089..736cf429c276a56074dc47304a570bc74e922f97 100644 (file)
@@ -26,3 +26,8 @@ void plat_arm_secure_wdt_stop(void)
 {
        sp805_stop(ARM_SP805_TWDG_BASE);
 }
+
+void bl1_platform_setup(void)
+{
+       arm_bl1_platform_setup();
+}
index 8e0c046f9ad3472b98dbc2dd55fe8482ad5ef958..8905bb05fa05dcf210d554ace74fce0722028d79 100644 (file)
@@ -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 @@ void arm_bl1_platform_setup(void)
 #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