diff options
author | Alexei Fedorov <Alexei.Fedorov@arm.com> | 2019-05-09 12:14:40 +0100 |
---|---|---|
committer | Alexei Fedorov <Alexei.Fedorov@arm.com> | 2019-05-10 16:09:19 +0100 |
commit | 1461ad9febbcb625941a53d80e4fa792f21e6e65 (patch) | |
tree | ed51fe81522c15fc87b5ba8fcf5daa83aa2ecc9a /drivers/arm | |
parent | f2f0846598909cb905de5d4380bac5b1d4c89d09 (diff) |
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>
Diffstat (limited to 'drivers/arm')
-rw-r--r-- | drivers/arm/smmu/smmu_v3.c | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c index ab2eb2be..5493b850 100644 --- a/drivers/arm/smmu/smmu_v3.c +++ b/drivers/arm/smmu/smmu_v3.c @@ -30,26 +30,63 @@ static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask, } /* + * 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); } |