From patchwork Fri May 27 21:28:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 12863848 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E8F68C433F5 for ; Fri, 27 May 2022 21:31:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=IITX2lMDwT6wiCNZBTkh9KmTWCA8aJF3xttEmkvuTFQ=; b=CP0M2rnBOM2dLh lv9fo7OityqNam4n3j9oor5IZs6tUC7+c981UbQPtwYBNAh8tAw98kZs5/cgmtOAHbuhQxt45oC0S u3f30e7j4wB9YhgG+Y67sGZLLVbukM7j4D9z269usyj0dUn61xvl6Vvdy/uOgqoMWAgkB864PibD0 V0AwVvJMkNwMVr4IIMeV/b9iZbSXIJ1cEqvIIF/VYPAA+yh2vUFQUBw1ixFGyqU82R83YczwUxEQD uHcqi2wZfvlmutvD2No43E0jebmrQbLzWri5wAsXMkDFUfLe6E8WVh6GbHFIiktpqu2p4n1RHENUD FCEV40c1jPgxBIUeQPTA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nuhXV-000yze-C5; Fri, 27 May 2022 21:30:33 +0000 Received: from relay03.th.seeweb.it ([5.144.164.164]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nuhWl-000ype-1h for linux-arm-kernel@lists.infradead.org; Fri, 27 May 2022 21:29:50 +0000 Received: from localhost.localdomain (abxh119.neoplus.adsl.tpnet.pl [83.9.1.119]) by m-r1.th.seeweb.it (Postfix) with ESMTPA id C74EB2058B; Fri, 27 May 2022 23:29:40 +0200 (CEST) From: Konrad Dybcio To: ~postmarketos/upstreaming@lists.sr.ht, linux-arm-msm@vger.kernel.org, bjorn.andersson@linaro.org, linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org Cc: martin.botka@somainline.org, angelogioacchino.delregno@somainline.org, marijn.suijten@somainline.org, jamipkettunen@somainline.org, Konrad Dybcio , Andy Gross , Joerg Roedel , Will Deacon , Rob Herring , Krzysztof Kozlowski , Rob Clark , Robin Murphy , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/6] iommu/qcom: Add support for AArch64 IOMMU pagetables Date: Fri, 27 May 2022 23:28:59 +0200 Message-Id: <20220527212901.29268-5-konrad.dybcio@somainline.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220527212901.29268-1-konrad.dybcio@somainline.org> References: <20220527212901.29268-1-konrad.dybcio@somainline.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220527_142947_458987_EE9A2E58 X-CRM114-Status: GOOD ( 20.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 Reported-by: kernel test robot --- .../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[2]; if (!ctx->secure_init) { ret = qcom_scm_restore_sec_cfg(qcom_iommu->sec_id, ctx->asid); @@ -292,11 +311,25 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, qcom_iommu_reset_ctx(ctx); + + tcr[0] = arm_smmu_lpae_tcr(&pgtbl_cfg); + tcr[1] = arm_smmu_lpae_tcr2(&pgtbl_cfg); + + if (!qcom_iommu->use_aarch64_pt) { + tcr[0] |= ARM_SMMU_TCR_EAE; + } else { + /* This shall not fail, or spectacular things happen! */ + if (qcom_scm_iommu_set_pt_format(qcom_iommu->sec_id, ctx->asid, 1)) { + dev_warn(qcom_iommu->dev, "Cannot set AArch64 pt format\n"); + goto out_clear_iommu; + } + + tcr[1] |= ARM_SMMU_TCR2_AS; + } + /* TCR */ - iommu_writel(ctx, ARM_SMMU_CB_TCR2, - arm_smmu_lpae_tcr2(&pgtbl_cfg)); - iommu_writel(ctx, ARM_SMMU_CB_TCR, - arm_smmu_lpae_tcr(&pgtbl_cfg) | ARM_SMMU_TCR_EAE); + iommu_writel(ctx, ARM_SMMU_CB_TCR2, tcr[1]); + iommu_writel(ctx, ARM_SMMU_CB_TCR, tcr[0]); /* TTBRs */ iommu_writeq(ctx, ARM_SMMU_CB_TTBR0, @@ -844,6 +877,9 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) return -ENODEV; } + if (of_property_read_bool(dev->of_node, "qcom,use-aarch64-pagetables")) + qcom_iommu->use_aarch64_pt = true; + if (qcom_iommu_has_secure_context(qcom_iommu)) { ret = qcom_iommu_sec_ptbl_init(dev); if (ret) {