[PATCH/RFC,02/04] iommu/ipmmu-vmsa: VA64 mode with 32-bit IOVA
diff mbox

Message ID 151097917767.24365.455036878830340615.sendpatchset@little-apple
State Under Review
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Magnus Damm Nov. 18, 2017, 4:26 a.m. UTC
From: Magnus Damm <damm+renesas@opensource.se>

Hack up the IPMMU driver to enable VM64 mode with 32-bit IOVA.

For this configuration the IPMMU hardware is configured with IMTTBCR.SL=1
and TSZ0 bits set to 0x20. This will enable a 32-bit IOVA space and use
"Initial lookup level 1" (in Table D4-13 of armv8_arm.pdf) also known as
"Start at first level" in IPMMU documentation.

Not for upstream merge. Tested on ULCB with r8a7796 ES1.0.

Earlier version posted as:
[PATCH/RFC] iommu/ipmmu-vmsa: Initial R-Car Gen3 VA64 mode support

The SL bit position has since then been updated to match more recent
IPMMU hardware documentation.

Not-Yet-Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |   36 +++++++++++++++++++++++++-----------
 1 files changed, 25 insertions(+), 11 deletions(-)

Patch
diff mbox

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2017-11-17 13:17:33.510607110 +0900
@@ -42,6 +42,7 @@  struct ipmmu_features {
 	unsigned int number_of_contexts;
 	bool setup_imbuscr;
 	bool twobit_imttbcr_sl0;
+	bool imctr_va64;
 };
 
 struct ipmmu_vmsa_device {
@@ -97,6 +98,7 @@  static struct ipmmu_vmsa_iommu_priv *to_
 #define IM_CTX_SIZE			0x40
 
 #define IMCTR				0x0000
+#define IMCTR_VA64			(1 << 29)
 #define IMCTR_TRE			(1 << 17)
 #define IMCTR_AFE			(1 << 16)
 #define IMCTR_RTSEL_MASK		(3 << 4)
@@ -442,8 +444,9 @@  static int ipmmu_domain_init_context(str
 
 	domain->context_id = ret;
 
-	domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
-					   domain);
+	domain->iop = alloc_io_pgtable_ops(domain->mmu->features->imctr_va64 ?
+					   ARM_64_LPAE_S1 : ARM_32_LPAE_S1,
+					   &domain->cfg, domain);
 	if (!domain->iop) {
 		ipmmu_domain_free_context(domain->mmu->root,
 					  domain->context_id);
@@ -456,14 +459,22 @@  static int ipmmu_domain_init_context(str
 	ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
 	/*
-	 * TTBCR
-	 * We use long descriptors with inner-shareable WBWA tables and allocate
-	 * the whole 32-bit VA space to TTBR0.
-	 */
-	if (domain->mmu->features->twobit_imttbcr_sl0)
-		tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
-	else
-		tmp = IMTTBCR_SL0_LVL_1;
+	 * For IMCTR_VA64 and ARM_64_LPAE_S1 we need lowest bits of TTBCR
+	 */
+	if (domain->mmu->features->imctr_va64) {
+		tmp = (1 << 6) | 0x20;
+	} else {
+		/*
+		 * TTBCR
+		 * We use long descriptors with inner-shareable WBWA tables
+		 * and allocate the whole 32-bit VA space to TTBR0.
+		 */
+
+		if (domain->mmu->features->twobit_imttbcr_sl0)
+			tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+		else
+			tmp = IMTTBCR_SL0_LVL_1;
+	}
 
 	ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 			     IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
@@ -493,7 +504,8 @@  static int ipmmu_domain_init_context(str
 	 * required when modifying the context registers.
 	 */
 	ipmmu_ctx_write_all(domain, IMCTR,
-			    IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+			 (domain->mmu->features->imctr_va64 ? IMCTR_VA64 : 0)
+			 | IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
 	return 0;
 }
@@ -1018,6 +1030,7 @@  static const struct ipmmu_features ipmmu
 	.number_of_contexts = 1, /* software only tested with one context */
 	.setup_imbuscr = true,
 	.twobit_imttbcr_sl0 = false,
+	.imctr_va64 = false,
 };
 
 static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
@@ -1026,6 +1039,7 @@  static const struct ipmmu_features ipmmu
 	.number_of_contexts = 8,
 	.setup_imbuscr = false,
 	.twobit_imttbcr_sl0 = true,
+	.imctr_va64 = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {