From patchwork Thu Sep 14 19:44:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 9953807 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A8C5D602C9 for ; Thu, 14 Sep 2017 19:45:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B19852925A for ; Thu, 14 Sep 2017 19:45:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A68FB2925C; Thu, 14 Sep 2017 19:45:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 294DD2925A for ; Thu, 14 Sep 2017 19:45:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: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:In-Reply-To: References:List-Owner; bh=xibCfZpOa8pKimpFiKDyu77NPksVsLNrXo0jp12RPpM=; b=GQg PX/kNXLoRJ+NA07syhtDUsg6Y3AOcv6C6YaVvWVoLo7icAZNBU2x/INi+5C0QR2wMS1cCO3IGI1uS wfBuzz2d0CMDK//F19U43SNigA+xn+oeg618N9KxN5cYwGUKV8ZXaBxiWahpEF/NwJFfE4vSQaJR7 dqi6ul/Rn194aYDNWQGNFkFUDDwGwonR48eDkRL9zeB/p/OAiERdaKAboTDqnIdbiUOrxnYv9jerL p/XEJrdyFHO86nMCCs7wKUp/kmE7lqaJB84Rba2Kp1II6ihXdRsN4ofy06IJRP0P+nT9bjB2lJ0oy tWPP0AwgBEH7VNDOIqo6jYBGDkc1D0w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dsa4m-0007eK-AJ; Thu, 14 Sep 2017 19:45:28 +0000 Received: from mail-qk0-x243.google.com ([2607:f8b0:400d:c09::243]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dsa4j-0006XW-3V for linux-arm-kernel@lists.infradead.org; Thu, 14 Sep 2017 19:45:27 +0000 Received: by mail-qk0-x243.google.com with SMTP id c69so226973qke.5 for ; Thu, 14 Sep 2017 12:45:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=w3yTUkLspKBqDQJHWh+JoXDFo37Kmr6nOcS2+ZHLdto=; b=rVRCdN/3Whk2yUhtrjj2x1hzlD4o3wnbOzpJlTLDje27+yaet/RzS6BxEYVBiMiTZd BBeBmtZ0nLwdzsGcLkgR8U1lxSLYJxGgyYNYNYd9ntmo0FfoWpWSDHZNBmqfWRqKggv5 4xyVPTP/snU7+P7wJwaxw8zviiZChv4D+TReWQw6gt/SOm+iDm/uOfdNv1R32oi/6ari sv7apEPY5i9vnjg7aFr3mlykPGmAgRZUbzfl8V2XkH6m4K0T+bGKn7iS47xAk7qsUdc7 1uvA2R+QDVu/eKivknSL4d3mbXjxXiOf1uy6jC0rD2pE2zx/Q8RBeIxc4kxvapre9850 rqTg== 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; bh=w3yTUkLspKBqDQJHWh+JoXDFo37Kmr6nOcS2+ZHLdto=; b=POUYxjWZ75Al8w4GJZjD0hk2XIs9BMmreoq1IT+kKiBvugMaksi9eGk6Fwjsizfa1A dUDwBY9kir0USq7Hmj7RpA2JcgYmSyToQSjT0CZAhjM5MbYa/WvY+9rZTgeKPej2o/LA NHVa3mVPc/ZxOJcAtkZOVOitMMJJJGF3evM+Bdnz+PsVnpuzGEkInuVYE1UYnYOQeeAW pKz5VdAft72CYmYRrN3eVXlQxvP2lSWPHWtxDqToJi5boxRjnY/oLXHcxnnF6P11Vgza BwOT8F0OVO9TfN7gQ2Mtv2SaiiiW1pOEglsigEZRTSR2xG3Nxycy9OV4lhzh6IeMtg3r 0w8w== X-Gm-Message-State: AHPjjUj3WHvH1qCQiyzzE7cZS+KZouY7ulpOs4dS2xeXo35St3Kkbghw mxDX7cHv8JVB0g== X-Google-Smtp-Source: AOwi7QABFn0fwJ2Nevezgz5R9aDl6aCQlF9R8XQFzPSPlcFVR1FF5hv4Z3Gk4+0snHsqw16uW0Pfxg== X-Received: by 10.55.144.69 with SMTP id s66mr4416667qkd.111.1505418302854; Thu, 14 Sep 2017 12:45:02 -0700 (PDT) Received: from localhost ([144.121.20.162]) by smtp.gmail.com with ESMTPSA id q49sm12159658qta.80.2017.09.14.12.45.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Sep 2017 12:45:01 -0700 (PDT) From: Rob Clark To: iommu@lists.linux-foundation.org Subject: [RFC] iommu: arm-smmu: stall support Date: Thu, 14 Sep 2017 15:44:33 -0400 Message-Id: <20170914194444.32551-1-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170914_124525_229487_52ADAAC3 X-CRM114-Status: GOOD ( 25.43 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arm-msm@vger.kernel.org, Joerg Roedel , Will Deacon , Rob Clark , linux-kernel@vger.kernel.org, Jordan Crouse , Robin Murphy , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Adds a new domain property for iommu clients to opt-in to stalling with asynchronous resume, and for the client to determine if the iommu supports this. Current motivation is that: a) On 8x96/a530, if we don't enable CFCFG (or HUPCF) then non- faulting translations which are happening concurrently with one that faults, fail (or return garbage), which triggers all sorts of fun GPU crashes, which generally have no relation to the root fault. (The CP can be far ahead in the cmdstream from the other parts of the GPU...) b) I am working on a debugfs feature to dump submits/batches that cause GPU hangs, and I would like to also use this for faults. But it needs to run in non-atomic context, so I need to toss things off to a workqueue, and then resume the iommu after it finishes. c) (and ofc at some point in the future for SVM we'd like to be able to pin unpinned pages and things like that, in response to faults.) TODO - For RFC I thought it would be easier to review the idea as a single patch, but it should be split into separate core and arm-smmu parts - I vaguely remember someone (Will?) mentioning that there could be cases with multiple masters sharing a single context bank, and somehow stalling might not work in that case? (How does that even happen, arm-smmu assignes the context banks? Maybe I'm mis-remembering the details.) I think that this probably shouldn't effect the API parts of this RFC, the iommu driver should already know about all the devices that might attach because of ->attach_dev() so it could fail in _set_attr()? Signed-off-by: Rob Clark --- drivers/iommu/arm-smmu.c | 36 ++++++++++++++++++++++++++++++++---- drivers/iommu/iommu.c | 21 +++++++++++++++++++++ include/linux/iommu.h | 14 ++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fe8e7fd61282..50131985a1e7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -239,6 +239,7 @@ struct arm_smmu_domain { struct io_pgtable_ops *pgtbl_ops; struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; + bool stall; struct mutex init_mutex; /* Protects smmu pointer */ spinlock_t cb_lock; /* Serialises ATS1* ops */ struct iommu_domain domain; @@ -544,6 +545,24 @@ static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v1 = { .tlb_sync = arm_smmu_tlb_sync_vmid, }; +static void arm_smmu_domain_resume(struct iommu_domain *domain, bool terminate) +{ + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_cfg *cfg = &smmu_domain->cfg; + struct arm_smmu_device *smmu = smmu_domain->smmu; + void __iomem *cb_base; + unsigned val; + + cb_base = ARM_SMMU_CB(smmu, cfg->cbndx); + + if (terminate) + val = RESUME_TERMINATE; + else + val = RESUME_RETRY; + + writel_relaxed(val, cb_base + ARM_SMMU_CB_RESUME); +} + static irqreturn_t arm_smmu_context_fault(int irq, void *dev) { u32 fsr, fsynr; @@ -563,11 +582,14 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR); - dev_err_ratelimited(smmu->dev, - "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cb=%d\n", - fsr, iova, fsynr, cfg->cbndx); - writel(fsr, cb_base + ARM_SMMU_CB_FSR); + + if (!report_iommu_fault(domain, smmu->dev, iova, 0)) { + dev_err_ratelimited(smmu->dev, + "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, cb=%d\n", + fsr, iova, fsynr, cfg->cbndx); + } + return IRQ_HANDLED; } @@ -698,6 +720,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, /* SCTLR */ reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M; + if (smmu_domain->stall) + reg |= SCTLR_CFCFG; /* stall on fault */ if (stage1) reg |= SCTLR_S1_ASIDPNE; #ifdef __BIG_ENDIAN @@ -1524,6 +1548,9 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, smmu_domain->stage = ARM_SMMU_DOMAIN_S1; break; + case DOMAIN_ATTR_STALL: + smmu_domain->stall = *(bool *)data; + break; default: ret = -ENODEV; } @@ -1587,6 +1614,7 @@ static struct iommu_ops arm_smmu_ops = { .device_group = arm_smmu_device_group, .domain_get_attr = arm_smmu_domain_get_attr, .domain_set_attr = arm_smmu_domain_set_attr, + .domain_resume = arm_smmu_domain_resume, .of_xlate = arm_smmu_of_xlate, .get_resv_regions = arm_smmu_get_resv_regions, .put_resv_regions = arm_smmu_put_resv_regions, diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3f6ea160afed..49eecfb7abd7 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1788,6 +1788,27 @@ int iommu_domain_set_attr(struct iommu_domain *domain, } EXPORT_SYMBOL_GPL(iommu_domain_set_attr); +/** + * iommu_domain_resume - Resume translations for a domain after a fault. + * + * This can be called at some point after the fault handler is called, + * allowing the user of the IOMMU to (for example) handle the fault + * from a task context. It is illegal to call this if + * iommu_domain_set_attr(STALL) failed. + * + * @domain: the domain to resume + * @terminate: if true, the translation that triggered the fault should + * be terminated, else it should be retried. + */ +void iommu_domain_resume(struct iommu_domain *domain, bool terminate) +{ + /* invalid to call if iommu_domain_set_attr(STALL) failed: */ + if (WARN_ON(!domain->ops->domain_resume)) + return; + domain->ops->domain_resume(domain, terminate); +} +EXPORT_SYMBOL_GPL(iommu_domain_resume); + void iommu_get_resv_regions(struct device *dev, struct list_head *list) { const struct iommu_ops *ops = dev->bus->iommu_ops; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 2cb54adc4a33..2154fe2591a0 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -124,6 +124,17 @@ enum iommu_attr { DOMAIN_ATTR_FSL_PAMU_ENABLE, DOMAIN_ATTR_FSL_PAMUV1, DOMAIN_ATTR_NESTING, /* two stages of translation */ + /* + * Domain stalls faulting translations, if DOMAIN_ATTR_STALL is + * enabled, user of domain calls iommu_domain_resume() at some + * point (either from fault handler or asynchronously after + * the fault handler is called (for example, from a workqueue) + * to resume translations. + * + * The attribute value is a bool, and should be set before + * attaching the domain. + */ + DOMAIN_ATTR_STALL, DOMAIN_ATTR_MAX, }; @@ -208,6 +219,8 @@ struct iommu_ops { int (*domain_set_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); + void (*domain_resume)(struct iommu_domain *domain, bool terminate); + /* Request/Free a list of reserved regions for a device */ void (*get_resv_regions)(struct device *dev, struct list_head *list); void (*put_resv_regions)(struct device *dev, struct list_head *list); @@ -333,6 +346,7 @@ extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, void *data); extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, void *data); +extern void iommu_domain_resume(struct iommu_domain *domain, bool terminate); /* Window handling function prototypes */ extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,