From patchwork Fri Jul 17 00:16:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 11668607 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2FA2B138C for ; Fri, 17 Jul 2020 00:18:17 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0362B20787 for ; Fri, 17 Jul 2020 00:18:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ZtRucBnm"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="OiQXSDCW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0362B20787 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=aLH4HExkwWRy9t/otRa61XSSb5LusI/DYx6k8p8x98g=; b=ZtRucBnmWAcnKs7GJUEagrNME 5/qwxS+EtynDGCbyEKBzMe0yNXG92MtrHKvP2YCaWZYyQYczce0/4hp3CoulJq2pFkXmSsW9SMVxg nwhQJG8kbIYrGmJTs2x41aYvk5BQHncwndF4zNEBBvWiPBkSOC9AUGIjZ4HnzZV5+lsYEAMajhRAc 4ythfw78ITcTH+M/papik8z7ANTpVm2BfO/lE4ZmxWzWhK3CwB7ZxMM7udPqBNU5KMAY6gj8mpk+6 tGH7nt+L66SSYyjf2BMY4sAfnaAjjjBWUyF2/6X05zJgtJc+OSAkxDafrGeFY/xIDqS48EWnozHqt oi6O2P0rA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwE3T-0005gW-Pq; Fri, 17 Jul 2020 00:16:47 +0000 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwE3D-0005cP-DY for linux-arm-kernel@lists.infradead.org; Fri, 17 Jul 2020 00:16:35 +0000 Received: by mail-pg1-x544.google.com with SMTP id e8so5775913pgc.5 for ; Thu, 16 Jul 2020 17:16:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jlkntRV846aUEo1Gl28BULv9E1NJaLJ91w5u0IdGAqY=; b=OiQXSDCWqV8zDFUYVBAxlH0S9CUnxu5iNny+Dixx/cJuAc+BjwJxXZk2NeYdMn/4JM po5lfGXXIcu237rEjN9QS6alFZsksWl0OsLnUjjmyoaa2VSLFxdsx9c0wclqDlpeCrG+ HRYy2HNZYiYfhM2z1JteVTx0DOTm7aLn3aPGOp6Yk9NTjXrXsTnLwm+GzAFBMlrvxdCO 5WvH2VytlFQke6xH+sVsHW2uCY9veYAsGGSk8znuUpUCJso0sxiUmXUosE/WnKW05fVp 9FfENWzbuDXCv41HbdfGyWbqsblDV4Cjq1n/ZcglHrIDq1Ec1+Wt0ywHHY9bNqrHZcHq rA8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jlkntRV846aUEo1Gl28BULv9E1NJaLJ91w5u0IdGAqY=; b=V1fyohpLKbhCvk7Tsxgr3x4zRxQdCs30wDbQDvVi6wnrWcrOa0LHTWmbRR+FoZEUxB jIXrNZKDEzIE44YUe2ShZdiwf0vuQkkedw6ANe7ZjvChJPbI2XGgD+uM9qUdH7j0VrSD YMI5vLr9LKsrraC/ok/had/w5RchX23+pRmM5UdBIQIV2GCG/Xc4fTMHox8qI2MANugI wjY7kUwAIjMSiS5IYM63BFpmJZyALuSCcM/H7TW76CSdm5LxNIF5HYBabcS7pXHGSNqA GvfLH1KXlIB91jXSB6hInfQU1ldpnRp5j8eolLHIumw0Y4w8WKtzInZ5HkXF+G2rp52D bboQ== X-Gm-Message-State: AOAM531SFeXdz4/JwTuSYsfDik/LcumN67qdud8f8Irj1C08k5+QK4MP cG6znm7GNOZ74z+QNusx2ZuG7g== X-Google-Smtp-Source: ABdhPJyOw+rZ5tyQFkUplkrS1otZKw4EmrIzCvAXE7cq7d57IJm0Q+MOF5/GsoqJxLnC2KC8CmI1AQ== X-Received: by 2002:a63:d40d:: with SMTP id a13mr6437251pgh.225.1594944989377; Thu, 16 Jul 2020 17:16:29 -0700 (PDT) Received: from localhost.localdomain (104-188-17-28.lightspeed.sndgca.sbcglobal.net. [104.188.17.28]) by smtp.gmail.com with ESMTPSA id r7sm6211950pgu.51.2020.07.16.17.16.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jul 2020 17:16:28 -0700 (PDT) From: Bjorn Andersson To: Will Deacon , Robin Murphy , Joerg Roedel , Thierry Reding , Laurentiu Tudor Subject: [PATCH v2 5/5] iommu/arm-smmu: Setup identity domain for boot mappings Date: Thu, 16 Jul 2020 17:16:19 -0700 Message-Id: <20200717001619.325317-6-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200717001619.325317-1-bjorn.andersson@linaro.org> References: <20200717001619.325317-1-bjorn.andersson@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200716_201631_533945_63891CA2 X-CRM114-Status: GOOD ( 26.36 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:544 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Vinod Koul , Jonathan Marek , linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, John Stultz , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org With many Qualcomm platforms not having functional S2CR BYPASS a temporary IOMMU domain, without translation, needs to be allocated in order to allow these memory transactions. Unfortunately the boot loader uses the first few context banks, so rather than overwriting a active bank the last context bank is used and streams are diverted here during initialization. This also performs the readback of SMR registers for the Qualcomm platform, to trigger the mechanism. This is based on prior work by Thierry Reding and Laurentiu Tudor. Tested-by: John Stultz Tested-by: Vinod Koul Signed-off-by: Bjorn Andersson --- Changes since v1: - Rebased to avoid conflict - Picked up tested-by drivers/iommu/arm-smmu-qcom.c | 11 +++++ drivers/iommu/arm-smmu.c | 79 +++++++++++++++++++++++++++++++++-- drivers/iommu/arm-smmu.h | 3 ++ 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c index 10eb024981d1..147af11049eb 100644 --- a/drivers/iommu/arm-smmu-qcom.c +++ b/drivers/iommu/arm-smmu-qcom.c @@ -26,6 +26,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = { static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) { unsigned int last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 1); + u32 smr; u32 reg; int i; @@ -56,6 +57,16 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) } } + for (i = 0; i < smmu->num_mapping_groups; i++) { + smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i)); + + if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) { + smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr); + smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr); + smmu->smrs[i].valid = true; + } + } + return 0; } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 08a650fe02e3..69bd8ee03516 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -652,7 +652,8 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx) } static int arm_smmu_init_domain_context(struct iommu_domain *domain, - struct arm_smmu_device *smmu) + struct arm_smmu_device *smmu, + bool boot_domain) { int irq, start, ret = 0; unsigned long ias, oas; @@ -770,6 +771,15 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ret = -EINVAL; goto out_unlock; } + + /* + * Use the last context bank for identity mappings during boot, to + * avoid overwriting in-use bank configuration while we're setting up + * the new mappings. + */ + if (boot_domain) + start = smmu->num_context_banks - 1; + ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, smmu->num_context_banks); if (ret < 0) @@ -1149,7 +1159,10 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); struct arm_smmu_master_cfg *cfg; struct arm_smmu_device *smmu; + bool free_identity_domain = false; + int idx; int ret; + int i; if (!fwspec || fwspec->ops != &arm_smmu_ops) { dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); @@ -1174,7 +1187,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return ret; /* Ensure that the domain is finalised */ - ret = arm_smmu_init_domain_context(domain, smmu); + ret = arm_smmu_init_domain_context(domain, smmu, false); if (ret < 0) goto rpm_put; @@ -1190,9 +1203,33 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) goto rpm_put; } + /* Decrement use counter for any references to the identity domain */ + mutex_lock(&smmu->stream_map_mutex); + if (smmu->identity) { + struct arm_smmu_domain *identity = to_smmu_domain(smmu->identity); + + for_each_cfg_sme(cfg, fwspec, i, idx) { + if (smmu->s2crs[idx].cbndx == identity->cfg.cbndx) { + smmu->num_identity_masters--; + if (smmu->num_identity_masters == 0) + free_identity_domain = true; + } + } + } + mutex_unlock(&smmu->stream_map_mutex); + /* Looks ok, so add the device to the domain */ ret = arm_smmu_domain_add_master(smmu_domain, cfg, fwspec); + /* + * The last stream map to reference the identity domain has been + * overwritten, so it's now okay to free it. + */ + if (free_identity_domain) { + arm_smmu_domain_free(smmu->identity); + smmu->identity = NULL; + } + /* * Setup an autosuspend delay to avoid bouncing runpm state. * Otherwise, if a driver for a suspended consumer device @@ -1922,17 +1959,51 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) static int arm_smmu_setup_identity(struct arm_smmu_device *smmu) { + struct device *dev = smmu->dev; + int cbndx = 0xff; + int type = S2CR_TYPE_BYPASS; + int ret; int i; + if (smmu->qcom_bypass_quirk) { + /* Create a IDENTITY domain to use for all inherited streams */ + smmu->identity = arm_smmu_domain_alloc(IOMMU_DOMAIN_IDENTITY); + if (!smmu->identity) { + dev_err(dev, "failed to create identity domain\n"); + return -ENOMEM; + } + + smmu->identity->pgsize_bitmap = smmu->pgsize_bitmap; + smmu->identity->type = IOMMU_DOMAIN_IDENTITY; + smmu->identity->ops = &arm_smmu_ops; + + ret = arm_smmu_init_domain_context(smmu->identity, smmu, true); + if (ret < 0) { + dev_err(dev, "failed to initialize identity domain: %d\n", ret); + return ret; + } + + type = S2CR_TYPE_TRANS; + cbndx = to_smmu_domain(smmu->identity)->cfg.cbndx; + } + for (i = 0; i < smmu->num_mapping_groups; i++) { if (smmu->smrs[i].valid) { - smmu->s2crs[i].type = S2CR_TYPE_BYPASS; + smmu->s2crs[i].type = type; smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT; - smmu->s2crs[i].cbndx = 0xff; + smmu->s2crs[i].cbndx = cbndx; smmu->s2crs[i].count++; + + smmu->num_identity_masters++; } } + /* If no mappings where found, free the identiy domain again */ + if (smmu->identity && !smmu->num_identity_masters) { + arm_smmu_domain_free(smmu->identity); + smmu->identity = NULL; + } + return 0; } diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index bcd160d01c53..37257ede86fa 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -321,6 +321,9 @@ struct arm_smmu_device { /* IOMMU core code handle */ struct iommu_device iommu; + struct iommu_domain *identity; + unsigned int num_identity_masters; + bool qcom_bypass_quirk; };