From: Magnus Damm <damm+rene...@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+rene...@opensource.se>
---

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

--- 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[] = {

Reply via email to