From 52a314af254966a604e192fcc3326737354f217a Mon Sep 17 00:00:00 2001 From: Olivier Deprez Date: Fri, 4 Feb 2022 12:30:11 +0100 Subject: [PATCH] feat(smmu): configure SMMU Root interface This change performs a basic configuration of the SMMU root registers interface on an RME enabled system. This permits enabling GPC checks for transactions originated from a non-secure or secure device upstream to an SMMU. It re-uses the boot time GPT base address and configuration programmed on the PE. The root register file offset is platform dependent and has to be supplied on a model command line. Signed-off-by: Olivier Deprez Change-Id: I4f889be6b7afc2afb4d1d147c5c1c3ea68f32e07 --- drivers/arm/smmu/smmu_v3.c | 71 +++++++++++++++++++++-- include/drivers/arm/smmu_v3.h | 30 +++++++++- plat/arm/board/fvp/include/platform_def.h | 1 + 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c index a082a8107..45f6df9f1 100644 --- a/drivers/arm/smmu/smmu_v3.c +++ b/drivers/arm/smmu/smmu_v3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +9,7 @@ #include #include #include +#include /* SMMU poll number of retries */ #define SMMU_POLL_TIMEOUT_US U(1000) @@ -79,14 +80,74 @@ int __init smmuv3_init(uintptr_t smmu_base) 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; +#if ENABLE_RME + + if (get_armv9_2_feat_rme_support() != 0U) { + if ((mmio_read_32(smmu_base + SMMU_ROOT_IDR0) & + SMMU_ROOT_IDR0_ROOT_IMPL) == 0U) { + WARN("Skip SMMU GPC configuration.\n"); + } else { + uint64_t gpccr_el3 = read_gpccr_el3(); + uint64_t gptbr_el3 = read_gptbr_el3(); + + /* SMMU_ROOT_GPT_BASE_CFG[16] is RES0. */ + gpccr_el3 &= ~(1UL << 16); + + /* + * TODO: SMMU_ROOT_GPT_BASE_CFG is 64b in the spec, + * but SMMU model only accepts 32b access. + */ + mmio_write_32(smmu_base + SMMU_ROOT_GPT_BASE_CFG, + gpccr_el3); + + /* + * pa_gpt_table_base[51:12] maps to GPTBR_EL3[39:0] + * whereas it maps to SMMU_ROOT_GPT_BASE[51:12] + * hence needs a 12 bit left shit. + */ + mmio_write_64(smmu_base + SMMU_ROOT_GPT_BASE, + gptbr_el3 << 12); + + /* + * ACCESSEN=1: SMMU- and client-originated accesses are + * not terminated by this mechanism. + * GPCEN=1: All clients and SMMU-originated accesses, + * except GPT-walks, are subject to GPC. + */ + mmio_setbits_32(smmu_base + SMMU_ROOT_CR0, + SMMU_ROOT_CR0_GPCEN | + SMMU_ROOT_CR0_ACCESSEN); + + /* Poll for ACCESSEN and GPCEN ack bits. */ + if (smmuv3_poll(smmu_base + SMMU_ROOT_CR0ACK, + SMMU_ROOT_CR0_GPCEN | + SMMU_ROOT_CR0_ACCESSEN, + SMMU_ROOT_CR0_GPCEN | + SMMU_ROOT_CR0_ACCESSEN) != 0) { + WARN("Failed enabling SMMU GPC.\n"); + + /* + * Do not return in error, but fall back to + * invalidating all entries through the secure + * register file. + */ + } + } + } + +#endif /* ENABLE_RME */ + /* * 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. + * Arm SMMU Arch RME supplement, section 3.4: all SMMU registers + * specified to be accessible only in secure physical address space are + * additionally accessible in root physical address space in an SMMU + * with RME. + * Section 3.3: as GPT information is permitted to be cached in a TLB, + * the SMMU_S_INIT.INV_ALL mechanism also invalidates GPT information + * cached in TLBs. */ mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL); diff --git a/include/drivers/arm/smmu_v3.h b/include/drivers/arm/smmu_v3.h index a820a4421..e60c75445 100644 --- a/include/drivers/arm/smmu_v3.h +++ b/include/drivers/arm/smmu_v3.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +9,7 @@ #include #include +#include /* SMMUv3 register offsets from device base */ #define SMMU_GBPA U(0x0044) @@ -16,6 +17,26 @@ #define SMMU_S_INIT U(0x803c) #define SMMU_S_GBPA U(0x8044) +/* + * TODO: SMMU_ROOT_PAGE_OFFSET is platform specific. + * Currently defined as a command line model parameter. + */ +#if ENABLE_RME + +#define SMMU_ROOT_PAGE_OFFSET (PLAT_ARM_SMMUV3_ROOT_REG_OFFSET) +#define SMMU_ROOT_IDR0 U(SMMU_ROOT_PAGE_OFFSET + 0x0000) +#define SMMU_ROOT_IIDR U(SMMU_ROOT_PAGE_OFFSET + 0x0008) +#define SMMU_ROOT_CR0 U(SMMU_ROOT_PAGE_OFFSET + 0x0020) +#define SMMU_ROOT_CR0ACK U(SMMU_ROOT_PAGE_OFFSET + 0x0024) +#define SMMU_ROOT_GPT_BASE U(SMMU_ROOT_PAGE_OFFSET + 0x0028) +#define SMMU_ROOT_GPT_BASE_CFG U(SMMU_ROOT_PAGE_OFFSET + 0x0030) +#define SMMU_ROOT_GPF_FAR U(SMMU_ROOT_PAGE_OFFSET + 0x0038) +#define SMMU_ROOT_GPT_CFG_FAR U(SMMU_ROOT_PAGE_OFFSET + 0x0040) +#define SMMU_ROOT_TLBI U(SMMU_ROOT_PAGE_OFFSET + 0x0050) +#define SMMU_ROOT_TLBI_CTRL U(SMMU_ROOT_PAGE_OFFSET + 0x0058) + +#endif /* ENABLE_RME */ + /* SMMU_GBPA register fields */ #define SMMU_GBPA_UPDATE (1UL << 31) #define SMMU_GBPA_ABORT (1UL << 20) @@ -30,6 +51,13 @@ #define SMMU_S_GBPA_UPDATE (1UL << 31) #define SMMU_S_GBPA_ABORT (1UL << 20) +/* SMMU_ROOT_IDR0 register fields */ +#define SMMU_ROOT_IDR0_ROOT_IMPL (1UL << 0) + +/* SMMU_ROOT_CR0 register fields */ +#define SMMU_ROOT_CR0_GPCEN (1UL << 1) +#define SMMU_ROOT_CR0_ACCESSEN (1UL << 0) + int smmuv3_init(uintptr_t smmu_base); int smmuv3_security_init(uintptr_t smmu_base); diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 5e5ddce0d..aa55b5974 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -261,6 +261,7 @@ #define PLAT_ARM_TRP_UART_CLK_IN_HZ V2M_IOFPGA_UART3_CLK_IN_HZ #define PLAT_FVP_SMMUV3_BASE UL(0x2b400000) +#define PLAT_ARM_SMMUV3_ROOT_REG_OFFSET UL(0x20000) /* CCI related constants */ #define PLAT_FVP_CCI400_BASE UL(0x2c090000)