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 <olivier.deprez@arm.com>
Change-Id: I4f889be6b7afc2afb4d1d147c5c1c3ea68f32e07
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c
index a082a81..45f6df9 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 <drivers/arm/smmu_v3.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
+#include <arch_features.h>
/* SMMU poll number of retries */
#define SMMU_POLL_TIMEOUT_US U(1000)
@@ -79,14 +80,74 @@
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);