This is another iteration to support split pagetables for Adreno GPUs as part of an incremental process to enable per-context pagetables. In order to support per-context pagetables the GPU needs to enable split pagetables so that we can store the global buffers in the TTBR1 space leaving the GPU free to program the TTBR0 register with the page address of a context specific pt. Previous revisions of this series can be found at [1] and [2]. This iteration is built on top of the arm-smmu-impl and arm-smmu-v2 rework code from Robin Murphy [3] and [4]. This code is based on the realization that when split pagetables are enabled the configuration for the T1 address space is identical to that of the T0 space, so we can just take the TCR configuration provided by io-pgtable, duplicate it and shift it by 16 bits. Since the current split pagetable implementation is specific to the Adreno GPUs we can also take a small shortcut and only allow split pagetables for SMMUs with a 49 bit upstream bus which allows us to use the default configuration for the sign extension bit and we can avoid a lot of extra code to handle different upstream bus sizes that will never get used. The first patch implements the split pagetable support for arm-smmu-v2. The second adds a SMMU model for the Adreno GPU SMMU and enables the split pagetables if conditions warrant. The 3rd and 4th patches add a domain attribute to query the status of split pagetables. The remaining patches modify drm/msm slightly to allow a6xx targets to recognize if split pagetables are enabled and adjust the address space accordingly. This series only includes support for split pagetables because I wanted to get this out for discussion and I haven't ported over the aux domain code to this kernel version, but I don't suspect it will end up being much different than previous versions [5]. [1] https://patchwork.freedesktop.org/series/63403/ [2] https://patchwork.freedesktop.org/series/64874/ [3] https://lists.linuxfoundation.org/pipermail/iommu/2019-August/037905.html [4] https://lists.linuxfoundation.org/pipermail/iommu/2019-August/038244.html [5] https://patchwork.freedesktop.org/patch/307601/ Jordan Crouse (7): iommu/arm-smmu: Support split pagetables dt-bindings: arm-smmu: Add Adreno GPU variant iommu/arm-smmu: Add a SMMU variant for the Adreno GPU iommu: Add DOMAIN_ATTR_SPLIT_TABLES iommu/arm-smmu: Support DOMAIN_ATTR_SPLIT_TABLES drm/msm: Create the msm_mmu object independently from the address space drm/msm: Use per-target functions to set up address spaces .../devicetree/bindings/iommu/arm,smmu.txt | 7 +++ drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 28 +++++++++++ drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 ++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 43 ++++++++++++++--- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 5 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 ++++--- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 16 ++++--- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 4 -- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 13 ++++- drivers/gpu/drm/msm/msm_drv.h | 8 +--- drivers/gpu/drm/msm/msm_gem_vma.c | 30 ++---------- drivers/gpu/drm/msm/msm_gpu.c | 51 ++------------------ drivers/gpu/drm/msm/msm_gpu.h | 4 +- drivers/iommu/arm-smmu-impl.c | 15 ++++++ drivers/iommu/arm-smmu.c | 46 ++++++++++++++++-- drivers/iommu/arm-smmu.h | 2 + include/linux/iommu.h | 1 + 20 files changed, 237 insertions(+), 111 deletions(-) -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Support a split pagetable format for SMMU models that support it. If enabled, mirror the TTBR0 setup for TTBR1 and program the pagetable address in TTBR1 instead of TTBR0. For now only allow split pagetables for ARM64 stage 1 IOMMUs with 49 bit upstream buses. This is the only real-life use case for split pagetables on arm-smmu-v2 to date and it is the easiest configuration to support without a bunch of extra logic. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> --- drivers/iommu/arm-smmu.c | 41 +++++++++++++++++++++++++++++++++++++---- drivers/iommu/arm-smmu.h | 1 + 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 49c734a..39e81ef 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -461,7 +461,17 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, cb->tcr[0] = pgtbl_cfg->arm_v7s_cfg.tcr; } else { cb->tcr[0] = pgtbl_cfg->arm_lpae_s1_cfg.tcr; - cb->tcr[0] |= TCR_EPD1; + + /* + * For split pagetables, duplicate the T0 configuration + * for T1. Otherwise, disable walks through TTBR1 + */ + if (smmu_domain->split_pagetables) + cb->tcr[0] |= (pgtbl_cfg->arm_lpae_s1_cfg.tcr & + 0xffff) << 16; + else + cb->tcr[0] |= TCR_EPD1; + cb->tcr[1] = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32; cb->tcr[1] |= FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM); if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64) @@ -477,9 +487,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, cb->ttbr[0] = pgtbl_cfg->arm_v7s_cfg.ttbr; cb->ttbr[1] = 0; } else { - cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; + if (smmu_domain->split_pagetables) { + cb->ttbr[0] = 0; + cb->ttbr[1] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; + } else { + cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; + cb->ttbr[1] = 0; + } + cb->ttbr[0] |= FIELD_PREP(TTBRn_ASID, cfg->asid); - cb->ttbr[1] = FIELD_PREP(TTBRn_ASID, cfg->asid); + cb->ttbr[1] |= FIELD_PREP(TTBRn_ASID, cfg->asid); } } else { cb->ttbr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr; @@ -720,6 +737,14 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, goto out_unlock; } + /* + * For now, only support a ias of 48 and SEP_UPSTREAM for split + * pagetables. This doesn't preclude using other sign extension bits but + * since the group of split-pagetable users is very small we don't want + * to add a lot of extra code that won't be useful + */ + WARN_ON(smmu_domain->split_pagetables && ias != 48); + pgtbl_cfg = (struct io_pgtable_cfg) { .pgsize_bitmap = smmu->pgsize_bitmap, .ias = ias, @@ -740,7 +765,15 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, /* Update the domain's page sizes to reflect the page table format */ domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; - domain->geometry.aperture_end = (1UL << ias) - 1; + + if (smmu_domain->split_pagetables) { + domain->geometry.aperture_start = ~(1UL << ias); + domain->geometry.aperture_end = ~0UL; + } else { + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = (1UL << ias) - 1; + } + domain->geometry.force_aperture = true; /* Initialise the context bank with our page table cfg */ diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index 7b0e4d2..91a4eb8 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -316,6 +316,7 @@ struct arm_smmu_domain { struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */ struct iommu_domain domain; + bool split_pagetables; }; -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Add a compatible string to identify SMMUs that are attached to Adreno GPU devices that wish to support split pagetables. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> --- Documentation/devicetree/bindings/iommu/arm,smmu.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 3133f3b..3b07896 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -18,6 +18,7 @@ conditions. "arm,mmu-500" "cavium,smmu-v2" "qcom,smmu-v2" + "qcom,adreno-smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. @@ -31,6 +32,12 @@ conditions. as below, SoC-specific compatibles: "qcom,sdm845-smmu-500", "arm,mmu-500" + "qcom,adreno-smmu-v2" is a special implementation for + SMMU devices attached to the Adreno GPU on Qcom devices. + If selected, this will enable split pagetable (TTBR1) + support. Only use this if the GPU target is capable of + supporting 64 bit addresses. + - reg : Base address and size of the SMMU. - #global-interrupts : The number of global interrupts exposed by the -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Add a SMMU model for the Adreno GPU and use it to enable split pagetable support if the conditions are right. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> --- drivers/iommu/arm-smmu-impl.c | 15 +++++++++++++++ drivers/iommu/arm-smmu.c | 2 ++ drivers/iommu/arm-smmu.h | 1 + 3 files changed, 18 insertions(+) diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c index 3f88cd0..5d197dd 100644 --- a/drivers/iommu/arm-smmu-impl.c +++ b/drivers/iommu/arm-smmu-impl.c @@ -147,6 +147,18 @@ static const struct arm_smmu_impl arm_mmu500_impl = { .reset = arm_mmu500_reset, }; +static int qcom_adreno_init_context(struct arm_smmu_domain *smmu_domain) +{ + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && + smmu_domain->cfg.fmt == ARM_SMMU_CTX_FMT_AARCH64) + smmu_domain->split_pagetables = true; + + return 0; +} + +static const struct arm_smmu_impl qcom_adreno_impl = { + .init_context = qcom_adreno_init_context, +}; struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) { @@ -162,6 +174,9 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) break; case CAVIUM_SMMUV2: return cavium_smmu_impl_init(smmu); + case QCOM_ADRENO_SMMUV2: + smmu->impl = &qcom_adreno_impl; + break; default: break; } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 39e81ef..3f41cf7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1858,6 +1858,7 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2); +ARM_SMMU_MATCH_DATA(qcom_adreno_smmuv2, ARM_SMMU_V2, QCOM_ADRENO_SMMUV2); static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 }, @@ -1867,6 +1868,7 @@ static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,mmu-500", .data = &arm_mmu500 }, { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 }, { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 }, + { .compatible = "qcom,adreno-smmu-v2", .data = &qcom_adreno_smmuv2 }, { }, }; diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index 91a4eb8..e5a2cc8 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -222,6 +222,7 @@ enum arm_smmu_implementation { ARM_MMU500, CAVIUM_SMMUV2, QCOM_SMMUV2, + QCOM_ADRENO_SMMUV2, }; struct arm_smmu_device { -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Add a new attribute to query the state of split pagetables for the domain. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index fdc355c..b06db6c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -125,6 +125,7 @@ enum iommu_attr { DOMAIN_ATTR_FSL_PAMUV1, DOMAIN_ATTR_NESTING, /* two stages of translation */ DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE, + DOMAIN_ATTR_SPLIT_TABLES, DOMAIN_ATTR_MAX, }; -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Support the DOMAIN_ATTR_SPLIT_TABLES attribute to let the leaf driver know if split pagetables are enabled for the domain. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> --- drivers/iommu/arm-smmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 3f41cf7..6a512ff 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1442,6 +1442,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, case DOMAIN_ATTR_NESTING: *(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED); return 0; + case DOMAIN_ATTR_SPLIT_TABLES: + *(int *)data = !!(smmu_domain->split_pagetables); + return 0; default: return -ENODEV; } -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
On Tue, 20 Aug 2019 13:06:27 -0600, Jordan Crouse wrote: > Add a compatible string to identify SMMUs that are attached > to Adreno GPU devices that wish to support split pagetables. > > Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> > --- > > Documentation/devicetree/bindings/iommu/arm,smmu.txt | 7 +++++++ > 1 file changed, 7 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
On Tue, Aug 20, 2019 at 01:06:30PM -0600, Jordan Crouse wrote: > Support the DOMAIN_ATTR_SPLIT_TABLES attribute to let the leaf driver > know if split pagetables are enabled for the domain. > > Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> > --- > > drivers/iommu/arm-smmu.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index 3f41cf7..6a512ff 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -1442,6 +1442,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, > case DOMAIN_ATTR_NESTING: > *(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED); > return 0; > + case DOMAIN_ATTR_SPLIT_TABLES: > + *(int *)data = !!(smmu_domain->split_pagetables); > + return 0; Hmm. Could you move the setting of this attribute into arm_smmu_domain_set_attr() and reject it if the ias != 48 in there? That way the user of the domain can request this feature, rather than us enforcing it based on the compatible string. I'd also prefer to call it DOMAIN_ATTR_USE_TTBR1 instead, since it's pretty ARM specific at this point. Will _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoting Jordan Crouse (2019-08-20 12:06:28) > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index 39e81ef..3f41cf7 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -1858,6 +1858,7 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU); > ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); > ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); > ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2); > +ARM_SMMU_MATCH_DATA(qcom_adreno_smmuv2, ARM_SMMU_V2, QCOM_ADRENO_SMMUV2); > > static const struct of_device_id arm_smmu_of_match[] = { > { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 }, > @@ -1867,6 +1868,7 @@ static const struct of_device_id arm_smmu_of_match[] = { > { .compatible = "arm,mmu-500", .data = &arm_mmu500 }, > { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 }, > { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 }, > + { .compatible = "qcom,adreno-smmu-v2", .data = &qcom_adreno_smmuv2 }, Can this be sorted on compat? > { }, > }; > > diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h > index 91a4eb8..e5a2cc8 100644 > --- a/drivers/iommu/arm-smmu.h > +++ b/drivers/iommu/arm-smmu.h > @@ -222,6 +222,7 @@ enum arm_smmu_implementation { > ARM_MMU500, > CAVIUM_SMMUV2, > QCOM_SMMUV2, > + QCOM_ADRENO_SMMUV2, Can this be sorted alphabetically? _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoting Jordan Crouse (2019-08-20 12:06:27) > Add a compatible string to identify SMMUs that are attached > to Adreno GPU devices that wish to support split pagetables. > > Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> > --- > > Documentation/devicetree/bindings/iommu/arm,smmu.txt | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > index 3133f3b..3b07896 100644 > --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt > +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt > @@ -18,6 +18,7 @@ conditions. > "arm,mmu-500" > "cavium,smmu-v2" > "qcom,smmu-v2" > + "qcom,adreno-smmu-v2" Is the tabbing weird here or just my MUA is failing? > > depending on the particular implementation and/or the > version of the architecture implemented. > @@ -31,6 +32,12 @@ conditions. > as below, SoC-specific compatibles: > "qcom,sdm845-smmu-500", "arm,mmu-500" > > + "qcom,adreno-smmu-v2" is a special implementation for Heh, special. > + SMMU devices attached to the Adreno GPU on Qcom devices. > + If selected, this will enable split pagetable (TTBR1) Is this selected? Sounds like Kconfig here. > + support. Only use this if the GPU target is capable of > + supporting 64 bit addresses. > + > - reg : Base address and size of the SMMU. > _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu