Re: [PATCH 4/6] iommu/qcom: Add support for AArch64 IOMMU pagetables
On Fri, May 27, 2022 at 11:28:59PM +0200, Konrad Dybcio wrote: > From: AngeloGioacchino Del Regno > > Some IOMMUs associated with some TZ firmwares may support switching > to the AArch64 pagetable format by sending a "set pagetable format" > scm command indicating the IOMMU secure ID and the context number > to switch. > > Add a DT property "qcom,use-aarch64-pagetables" for this driver to > send this command to the secure world and to switch the pagetable > format to benefit of the ARM64 IOMMU pagetables, where possible. > > Note that, even though the command should be valid to switch each > context, the property is made global because: > 1. It doesn't make too much sense to switch only one or two >context(s) to AA64 instead of just the entire thing > 2. Some IOMMUs will go crazy and produce spectacular results when >trying to mix up the pagetables on a per-context basis. > > Signed-off-by: AngeloGioacchino Del Regno > > Signed-off-by: Marijn Suijten > Signed-off-by: Konrad Dybcio > --- > .../devicetree/bindings/iommu/qcom,iommu.txt | 2 + Bindings should be separate patch. As you are making multiple changes, please convert this to DT schema first. > drivers/iommu/arm/arm-smmu/qcom_iommu.c | 54 +++ > 2 files changed, 47 insertions(+), 9 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 4/6] iommu/qcom: Add support for AArch64 IOMMU pagetables
Hi Konrad, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on joro-iommu/next] [also build test WARNING on v5.18 next-20220527] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Konrad-Dybcio/iommu-qcom-Use-the-asid-read-from-device-tree-if-specified/20220528-062952 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20220528/202205280904.vsncfpph-...@intel.com/config) compiler: arceb-elf-gcc (GCC) 11.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/0744f7d6ebfff8d6854a24d0f95f8e58885b5212 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Konrad-Dybcio/iommu-qcom-Use-the-asid-read-from-device-tree-if-specified/20220528-062952 git checkout 0744f7d6ebfff8d6854a24d0f95f8e58885b5212 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash drivers/iommu/arm/arm-smmu/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot All warnings (new ones prefixed by >>): drivers/iommu/arm/arm-smmu/qcom_iommu.c: In function 'qcom_iommu_tlb_inv_range_nosync': >> drivers/iommu/arm/arm-smmu/qcom_iommu.c:174:58: warning: left shift count >= >> width of type [-Wshift-count-overflow] 174 | iova |= (unsigned long)ctx->asid << 48; | ^~ vim +174 drivers/iommu/arm/arm-smmu/qcom_iommu.c 157 158 static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, 159 size_t granule, bool leaf, void *cookie) 160 { 161 struct qcom_iommu_domain *qcom_domain = cookie; 162 struct iommu_fwspec *fwspec = qcom_domain->fwspec; 163 unsigned i, reg; 164 165 reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA; 166 167 for (i = 0; i < fwspec->num_ids; i++) { 168 struct qcom_iommu_dev *qcom_iommu = qcom_domain->iommu; 169 struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); 170 size_t s = size; 171 172 if (qcom_iommu->use_aarch64_pt) { 173 iova >>= 12; > 174 iova |= (unsigned long)ctx->asid << 48; 175 } else { 176 iova &= (1UL << 12) - 1UL; 177 iova |= ctx->asid; 178 } 179 do { 180 iommu_writel(ctx, reg, iova); 181 iova += granule; 182 } while (s -= granule); 183 } 184 } 185 -- 0-DAY CI Kernel Test Service https://01.org/lkp ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/6] iommu/qcom: Add support for AArch64 IOMMU pagetables
From: AngeloGioacchino Del Regno Some IOMMUs associated with some TZ firmwares may support switching to the AArch64 pagetable format by sending a "set pagetable format" scm command indicating the IOMMU secure ID and the context number to switch. Add a DT property "qcom,use-aarch64-pagetables" for this driver to send this command to the secure world and to switch the pagetable format to benefit of the ARM64 IOMMU pagetables, where possible. Note that, even though the command should be valid to switch each context, the property is made global because: 1. It doesn't make too much sense to switch only one or two context(s) to AA64 instead of just the entire thing 2. Some IOMMUs will go crazy and produce spectacular results when trying to mix up the pagetables on a per-context basis. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Marijn Suijten Signed-off-by: Konrad Dybcio --- .../devicetree/bindings/iommu/qcom,iommu.txt | 2 + drivers/iommu/arm/arm-smmu/qcom_iommu.c | 54 +++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt index ba0b77889f02..72ae0595efff 100644 --- a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt +++ b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt @@ -47,6 +47,8 @@ to non-secure vs secure interrupt line. secure lines. (Ie. if the iommu contains secure context banks) - qcom,ctx-num : The number associated to the context bank +- qcom,use-aarch64-pagetables : Switch to AArch64 pagetable format on all +contexts declared in this IOMMU ** Examples: diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c index 129e322f56a6..530aa92bf6a1 100644 --- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c +++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c @@ -52,6 +52,7 @@ struct qcom_iommu_dev { void __iomem*local_base; u32 sec_id; u8 num_ctxs; + bool use_aarch64_pt; struct qcom_iommu_ctx *ctxs[]; /* indexed by asid-1 */ }; @@ -164,11 +165,17 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA; for (i = 0; i < fwspec->num_ids; i++) { + struct qcom_iommu_dev *qcom_iommu = qcom_domain->iommu; struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); size_t s = size; - iova = (iova >> 12) << 12; - iova |= ctx->asid; + if (qcom_iommu->use_aarch64_pt) { + iova >>= 12; + iova |= (unsigned long)ctx->asid << 48; + } else { + iova &= (1UL << 12) - 1UL; + iova |= ctx->asid; + } do { iommu_writel(ctx, reg, iova); iova += granule; @@ -248,6 +255,8 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); struct io_pgtable_ops *pgtbl_ops; struct io_pgtable_cfg pgtbl_cfg; + enum io_pgtable_fmt pgtbl_fmt; + unsigned long ias, oas; int i, ret = 0; u32 reg; @@ -255,10 +264,19 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, if (qcom_domain->iommu) goto out_unlock; + if (qcom_iommu->use_aarch64_pt) { + pgtbl_fmt = ARM_64_LPAE_S1; + ias = oas = 48; + } else { + pgtbl_fmt = ARM_32_LPAE_S1; + ias = 32; + oas = 40; + } + pgtbl_cfg = (struct io_pgtable_cfg) { .pgsize_bitmap = qcom_iommu_ops.pgsize_bitmap, - .ias= 32, - .oas= 40, + .ias= ias, + .oas= oas, .tlb= &qcom_flush_ops, .iommu_dev = qcom_iommu->dev, }; @@ -266,7 +284,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, qcom_domain->iommu = qcom_iommu; qcom_domain->fwspec = fwspec; - pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, qcom_domain); + pgtbl_ops = alloc_io_pgtable_ops(pgtbl_fmt, &pgtbl_cfg, qcom_domain); if (!pgtbl_ops) { dev_err(qcom_iommu->dev, "failed to allocate pagetable ops\n"); ret = -ENOMEM; @@ -280,6 +298,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, for (i = 0; i < fwspec->num_ids; i++) { struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); + u32 tcr
[PATCH 4/6] iommu/qcom: Add support for AArch64 IOMMU pagetables
From: AngeloGioacchino Del Regno Some IOMMUs associated with some TZ firmwares may support switching to the AArch64 pagetable format by sending a "set pagetable format" scm command indicating the IOMMU secure ID and the context number to switch. Add a DT property "qcom,use-aarch64-pagetables" for this driver to send this command to the secure world and to switch the pagetable format to benefit of the ARM64 IOMMU pagetables, where possible. Note that, even though the command should be valid to switch each context, the property is made global because: 1. It doesn't make too much sense to switch only one or two context(s) to AA64 instead of just the entire thing 2. Some IOMMUs will go crazy and produce spectacular results when trying to mix up the pagetables on a per-context basis. Signed-off-by: AngeloGioacchino Del Regno --- .../devicetree/bindings/iommu/qcom,iommu.txt | 2 + drivers/iommu/qcom_iommu.c| 55 +++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt index 98102b323196..a4dd76b8c566 100644 --- a/Documentation/devicetree/bindings/iommu/qcom,iommu.txt +++ b/Documentation/devicetree/bindings/iommu/qcom,iommu.txt @@ -39,6 +39,8 @@ to non-secure vs secure interrupt line. - reg: Base address and size of context bank within the iommu - interrupts : The context fault irq. - qcom,ctx-num : The number associated to the context bank + - qcom,use-aarch64-pagetables : Switch to AArch64 pagetable format on all + contexts declared in this IOMMU ** Optional properties: diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 2f31da2e7add..233ef496af27 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -48,6 +48,7 @@ struct qcom_iommu_dev { void __iomem*local_base; u32 sec_id; u8 num_ctxs; + bool use_aarch64_pt; struct qcom_iommu_ctx *ctxs[0]; /* indexed by asid-1 */ }; @@ -153,11 +154,17 @@ static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA; for (i = 0; i < fwspec->num_ids; i++) { + struct qcom_iommu_dev *qcom_iommu = to_iommu(fwspec); struct qcom_iommu_ctx *ctx = to_ctx(fwspec, fwspec->ids[i]); size_t s = size; - iova &= ~12UL; - iova |= ctx->asid; + if (qcom_iommu->use_aarch64_pt) { + iova >>= 12; + iova |= (u64)ctx->asid << 48; + } else { + iova &= ~12UL; + iova |= ctx->asid; + } do { iommu_writel(ctx, reg, iova); iova += granule; @@ -222,6 +229,8 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain); struct io_pgtable_ops *pgtbl_ops; struct io_pgtable_cfg pgtbl_cfg; + enum io_pgtable_fmt pgtbl_fmt; + unsigned long ias, oas; int i, ret = 0; u32 reg; @@ -229,16 +238,25 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, if (qcom_domain->iommu) goto out_unlock; + if (qcom_iommu->use_aarch64_pt) { + pgtbl_fmt = ARM_64_LPAE_S1; + ias = oas = 48; + } else { + pgtbl_fmt = ARM_32_LPAE_S1; + ias = 32; + oas = 40; + } + pgtbl_cfg = (struct io_pgtable_cfg) { .pgsize_bitmap = qcom_iommu_ops.pgsize_bitmap, - .ias= 32, - .oas= 40, + .ias= ias, + .oas= oas, .tlb= &qcom_gather_ops, .iommu_dev = qcom_iommu->dev, }; qcom_domain->iommu = qcom_iommu; - pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, fwspec); + pgtbl_ops = alloc_io_pgtable_ops(pgtbl_fmt, &pgtbl_cfg, fwspec); if (!pgtbl_ops) { dev_err(qcom_iommu->dev, "failed to allocate pagetable ops\n"); ret = -ENOMEM; @@ -252,6 +270,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, for (i = 0; i < fwspec->num_ids; i++) { struct qcom_iommu_ctx *ctx = to_ctx(fwspec, fwspec->ids[i]); + u32 tcr[2]; if (!ctx->secure_init) { ret = qcom_scm_restore_sec_cfg(qcom_iommu->sec_id, ctx->asid); @@ -264,12 +283,25 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, qcom_iommu_