From patchwork Fri Oct 6 13:31:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 9989365 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 531606029B for ; Fri, 6 Oct 2017 13:29:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4D3AB28BCF for ; Fri, 6 Oct 2017 13:29:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4154728C53; Fri, 6 Oct 2017 13:29:30 +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_SIGNED, DKIM_VALID,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 CB11E28BCF for ; Fri, 6 Oct 2017 13:29:29 +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: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=j2R2iaTiLnk/60+MN0bazzP5jMTE67b1O34UVx/8Gkc=; b=NsNTWOxpdQDcFQyUtjV4ZqP5P9 57cDZz12kzpK46NGeM5ORwEI6fPFDXzF3iMwVB40ncKyJTI0N5m0CSfpDMxOPKOQEXwReF4srM2El v1aSknkKbsl26XEM+2m+t0kraGTaXsO9ln2gFbGofrst5g8IsTtEiB33+R2h3QCf6DKzXCtvvv1L3 g/byvmZvEJucqhXa8Rfdu1qbjjh3qHISwJ2A3ApFoc6CNEYqn3BrvWdLfs3ffHMLz4iATdFWkfEAV dYEOlp6ZaQpko+sA60hCHJ4sqAgTA5X+dcZvwQ26MOJUqwDmj1iDy588Enmrgm1upZl0YaRO1AmXC oLmJaqGQ==; 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 1e0Sgz-00034E-2l; Fri, 06 Oct 2017 13:29:29 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e0SgF-00025f-0J for linux-arm-kernel@lists.infradead.org; Fri, 06 Oct 2017 13:29:25 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 307B81435; Fri, 6 Oct 2017 06:28:23 -0700 (PDT) Received: from e106794-lin.cambridge.arm.com (e106794-lin.cambridge.arm.com [10.1.211.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 55CD53F578; Fri, 6 Oct 2017 06:28:18 -0700 (PDT) From: Jean-Philippe Brucker To: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, devicetree@vger.kernel.org, iommu@lists.linux-foundation.org Subject: [RFCv2 PATCH 06/36] iommu: Extend fault reporting Date: Fri, 6 Oct 2017 14:31:33 +0100 Message-Id: <20171006133203.22803-7-jean-philippe.brucker@arm.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20171006133203.22803-1-jean-philippe.brucker@arm.com> References: <20171006133203.22803-1-jean-philippe.brucker@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171006_062844_142672_4445FA1D X-CRM114-Status: GOOD ( 17.40 ) 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: mark.rutland@arm.com, xieyisheng1@huawei.com, gabriele.paoloni@huawei.com, catalin.marinas@arm.com, will.deacon@arm.com, okaya@codeaurora.org, yi.l.liu@intel.com, lorenzo.pieralisi@arm.com, ashok.raj@intel.com, tn@semihalf.com, joro@8bytes.org, rfranz@cavium.com, lenb@kernel.org, jacob.jun.pan@linux.intel.com, alex.williamson@redhat.com, robh+dt@kernel.org, thunder.leizhen@huawei.com, bhelgaas@google.com, dwmw2@infradead.org, liubo95@huawei.com, rjw@rjwysocki.net, robdclark@gmail.com, hanjun.guo@linaro.org, sudeep.holla@arm.com, robin.murphy@arm.com, nwatters@codeaurora.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 A number of new users will need additional information in the IOMMU fault report, such as PASID and/or PRI group. Pass a new iommu_fault structure to the driver callbacks. For the moment add the new API in parallel, with an "ext" prefix, to let users move to the new API at their pace. I think it would be nice to use a single API though. There are only 4 device drivers using it, and receiving an iommu_fault instead of iova/flags wouldn't hurt them much. For the same reason as the process_exit handler, set_fault_handler is done on a device rather than a domain (although for the moment stored in the domain). Even when multiple heterogenous devices are in the same IOMMU group, each of their driver might want to register a fault handler. At the moment they'll race to set the handler, and the winning driver will receive fault reports from other devices. The new registering function also takes flags as arguments, giving future users a way to specify at which point of the fault process they want to be called. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/iommu.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/linux/iommu.h | 18 ++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index f9cb89dd28f5..ee956b5fc301 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1234,6 +1234,8 @@ EXPORT_SYMBOL_GPL(iommu_capable); * This function should be used by IOMMU users which want to be notified * whenever an IOMMU fault happens. * + * Note that new users should use iommu_set_ext_fault_handler instead. + * * The fault handler itself should return 0 on success, and an appropriate * error code otherwise. */ @@ -1243,11 +1245,44 @@ void iommu_set_fault_handler(struct iommu_domain *domain, { BUG_ON(!domain); + if (WARN_ON(domain->ext_handler)) + return; + domain->handler = handler; domain->handler_token = token; } EXPORT_SYMBOL_GPL(iommu_set_fault_handler); +/** + * iommu_set_ext_fault_handler() - set a fault handler for a device + * @dev: the device + * @handler: fault handler + * @token: user data, will be passed back to the fault handler + * @flags: IOMMU_FAULT_HANDLER_* parameters. + * + * This function should be used by IOMMU users which want to be notified + * whenever an IOMMU fault happens. + * + * The fault handler itself should return 0 on success, and an appropriate + * error code otherwise. + */ +void iommu_set_ext_fault_handler(struct device *dev, + iommu_ext_fault_handler_t handler, + void *token, int flags) +{ + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + + if (WARN_ON(!domain)) + return; + + if (WARN_ON(domain->handler || domain->ext_handler)) + return; + + domain->ext_handler = handler; + domain->handler_token = token; +} +EXPORT_SYMBOL_GPL(iommu_set_ext_fault_handler); + static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, unsigned type) { @@ -1787,6 +1822,10 @@ int report_iommu_fault(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags) { int ret = -ENOSYS; + struct iommu_fault fault = { + .address = iova, + .flags = flags, + }; /* * if upper layers showed interest and installed a fault handler, @@ -1795,6 +1834,9 @@ int report_iommu_fault(struct iommu_domain *domain, struct device *dev, if (domain->handler) ret = domain->handler(domain, dev, iova, flags, domain->handler_token); + else if (domain->ext_handler) + ret = domain->ext_handler(domain, dev, &fault, + domain->handler_token); trace_io_page_fault(dev, iova, flags); return ret; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index e64c2711ea8d..ea4eaf585eb4 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -57,6 +57,14 @@ struct notifier_block; typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); +struct iommu_fault { + unsigned long address; + unsigned int flags; +}; + +typedef int (*iommu_ext_fault_handler_t)(struct iommu_domain *, struct device *, + struct iommu_fault *, void *); + /* All process are being detached from this device */ #define IOMMU_PROCESS_EXIT_ALL (-1) typedef int (*iommu_process_exit_handler_t)(struct iommu_domain *, struct device *dev, @@ -97,6 +105,7 @@ struct iommu_domain { const struct iommu_ops *ops; unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */ iommu_fault_handler_t handler; + iommu_ext_fault_handler_t ext_handler; void *handler_token; iommu_process_exit_handler_t process_exit; void *process_exit_token; @@ -352,6 +361,9 @@ extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long io extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); +extern void iommu_set_ext_fault_handler(struct device *dev, + iommu_ext_fault_handler_t handler, + void *token, int flags); extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); @@ -566,6 +578,12 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain, { } +static inline void iommu_set_ext_fault_handler(struct device *dev, + iommu_ext_fault_handler_t handler, void *token, + int flags) +{ +} + static inline void iommu_get_resv_regions(struct device *dev, struct list_head *list) {