From patchwork Fri May 11 19:06:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 10394831 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 1627360348 for ; Fri, 11 May 2018 19:07:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F251128D17 for ; Fri, 11 May 2018 19:07:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E673828F91; Fri, 11 May 2018 19:07:40 +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=-2.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2716728D17 for ; Fri, 11 May 2018 19:07:40 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 1D87E6B0680; Fri, 11 May 2018 15:07:39 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 165BB6B0681; Fri, 11 May 2018 15:07:39 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 02A7D6B0682; Fri, 11 May 2018 15:07:38 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-oi0-f71.google.com (mail-oi0-f71.google.com [209.85.218.71]) by kanga.kvack.org (Postfix) with ESMTP id CD5966B0680 for ; Fri, 11 May 2018 15:07:38 -0400 (EDT) Received: by mail-oi0-f71.google.com with SMTP id 8-v6so3422855oip.22 for ; Fri, 11 May 2018 12:07:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=atSg0CeOK0gomHtQ3DmWsUe5bYnm1QlR7Wpz1RP6XDM=; b=aj8WvKX+dpr/1Nh0BCBwjauJNWfMqQvbI12dXyXpufkCSWuwJzIY+lvsSLVxugqTZ7 vKETmYoizPO8Y4e7cgSLjifHYUHuF1hCn7++/Yrvf5iAgB22FZ3YBD9D7iI2zScA+Hp5 IH8qrulbP9G1ER+XcxOR11QvqpX8V0JYvp5+H2nTZRvob2PTH/AK4TkVXhZjl9qYiAgH gHVQzf3pbITwZTUEErtQbeoNHXqM7fVMealGwoETO2Y0goI9sC2K6pjd8ncWrbXtt2Cg Zlq6Cxrwi/Mf+KvDlMKPBU5o4lDy7YDW9e+Io8gNFKXxB62CpaTwSsyz3Z5Ws+NfaCni l3Aw== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of jean-philippe.brucker@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=jean-philippe.brucker@arm.com X-Gm-Message-State: ALKqPwdJ6jOF9qw5gB7f9KOBKeAanwmBKGcH0kQPw+zdeFCzHgBvNOgX /VBjW5tKUDwDKk65DMZ6rrF8l05YXDThwnmUcPdZRAwgphuWGSUZ4PbF6g2SGSY7/sbEHeHmA8r yqmmW9BiTEuFTYWR4xdnU/HI8Dt2HnugObnq40V7aaViPRRRpqE+6APkD4cvyMCO/JQ== X-Received: by 2002:a9d:2416:: with SMTP id p22-v6mr4444151ota.99.1526065658533; Fri, 11 May 2018 12:07:38 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrBu52l+3C+O8MrRYsXRMP185gaBkaY/jNZmOdnlARoogccMQRATgX5Sp9mv6FoxmdBO1B3 X-Received: by 2002:a9d:2416:: with SMTP id p22-v6mr4444104ota.99.1526065657598; Fri, 11 May 2018 12:07:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526065657; cv=none; d=google.com; s=arc-20160816; b=CzzsSuOD8g/reCmdA4k2XaplVyRcmPEwcnNBH/usLvRPAno62ADktmWw1prdn+zBEU wMnArprHjSIYkhJctbGS+x+oJmEtCNGtXaw86Ft2MvAc119PaGiiLeL5V1muCVSYUtn5 wOs4ypcHhrB1RjjwXAqasWPCJcHKwVzyzKQleLsM70ahlHkrHSwu/MlVF06aDtpTokJr qNfpFjFN5rAyrYM5ZB6b8EVXA1/FA8tavpfThU0T4PpkynjHDMpxU9MRFOZ66DWPAwgU bsLe7K39acSjb4aKw3DLRf5eLw/d/8hwnkXrS/vJhSySXgfbKJBQEhioiVeB1hhHk0gp YQqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=atSg0CeOK0gomHtQ3DmWsUe5bYnm1QlR7Wpz1RP6XDM=; b=lO0MW4nNIqEGc4DCxlGLVqfZQwtve8y8g+kjKyGOPZvI4NVmh7SAfvq3Xhu1aCfJRJ jnBjFimTFDtLTQDCWIpeY4JbPl6xz8ywCBUKut3Lgki4HsHvAExxKA1s8aoe5LiH/Pb/ n2OU3juE55Lu/LfDVm2w9YX96sDOfLoYszAgBlpOyAvnR7UjjGIyQjmaKOzsTUmmkrS6 FR+H7w2IK6BFgvlidZ7livug2DR6N8UOsrJloFCicENxXPCtI1GQ/0S+u9V1EPbZWVON Rcbsun/LG3CXt+WIB1OvK/XKdAhq36EHgkADH6itQ1NTGeec8fIgBi0NIyTGp71eQzPb QFLQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of jean-philippe.brucker@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=jean-philippe.brucker@arm.com Received: from foss.arm.com (foss.arm.com. [217.140.101.70]) by mx.google.com with ESMTP id l43-v6si1403917ota.212.2018.05.11.12.07.37 for ; Fri, 11 May 2018 12:07:37 -0700 (PDT) Received-SPF: pass (google.com: domain of jean-philippe.brucker@arm.com designates 217.140.101.70 as permitted sender) client-ip=217.140.101.70; Authentication-Results: mx.google.com; spf=pass (google.com: domain of jean-philippe.brucker@arm.com designates 217.140.101.70 as permitted sender) smtp.mailfrom=jean-philippe.brucker@arm.com 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 364A21991; Fri, 11 May 2018 12:07:37 -0700 (PDT) Received: from ostrya.cambridge.arm.com (ostrya.cambridge.arm.com [10.1.210.33]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EC91F3F23C; Fri, 11 May 2018 12:07:31 -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, kvm@vger.kernel.org, linux-mm@kvack.org Cc: joro@8bytes.org, will.deacon@arm.com, robin.murphy@arm.com, alex.williamson@redhat.com, tn@semihalf.com, liubo95@huawei.com, thunder.leizhen@huawei.com, xieyisheng1@huawei.com, xuzaibo@huawei.com, ilias.apalodimas@linaro.org, jonathan.cameron@huawei.com, liudongdong3@huawei.com, shunyong.yang@hxt-semitech.com, nwatters@codeaurora.org, okaya@codeaurora.org, jcrouse@codeaurora.org, rfranz@cavium.com, dwmw2@infradead.org, jacob.jun.pan@linux.intel.com, yi.l.liu@intel.com, ashok.raj@intel.com, kevin.tian@intel.com, baolu.lu@linux.intel.com, robdclark@gmail.com, christian.koenig@amd.com, bharatku@xilinx.com, rgummal@xilinx.com Subject: [PATCH v2 01/40] iommu: Introduce Shared Virtual Addressing API Date: Fri, 11 May 2018 20:06:02 +0100 Message-Id: <20180511190641.23008-2-jean-philippe.brucker@arm.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180511190641.23008-1-jean-philippe.brucker@arm.com> References: <20180511190641.23008-1-jean-philippe.brucker@arm.com> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Shared Virtual Addressing (SVA) provides a way for device drivers to bind process address spaces to devices. This requires the IOMMU to support page table format and features compatible with the CPUs, and usually requires the system to support I/O Page Faults (IOPF) and Process Address Space ID (PASID). When all of these are available, DMA can access virtual addresses of a process. A PASID is allocated for each process, and the device driver programs it into the device in an implementation-specific way. Add a new API for sharing process page tables with devices. Introduce two IOMMU operations, sva_device_init() and sva_device_shutdown(), that prepare the IOMMU driver for SVA. For example allocate PASID tables and fault queues. Subsequent patches will implement the bind() and unbind() operations. Support for I/O Page Faults will be added in a later patch using a new feature bit (IOMMU_SVA_FEAT_IOPF). With the current API users must pin down all shared mappings. Other feature bits that may be added in the future are IOMMU_SVA_FEAT_PRIVATE, to support private PASID address spaces, and IOMMU_SVA_FEAT_NO_PASID, to bind the whole device address space to a process. Signed-off-by: Jean-Philippe Brucker --- v1->v2: * Add sva_param structure to iommu_param * CONFIG option is only selectable by IOMMU drivers --- drivers/iommu/Kconfig | 4 ++ drivers/iommu/Makefile | 1 + drivers/iommu/iommu-sva.c | 110 ++++++++++++++++++++++++++++++++++++++ include/linux/iommu.h | 32 +++++++++++ 4 files changed, 147 insertions(+) create mode 100644 drivers/iommu/iommu-sva.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 7564237f788d..cca8e06903c7 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -74,6 +74,10 @@ config IOMMU_DMA select IOMMU_IOVA select NEED_SG_DMA_LENGTH +config IOMMU_SVA + bool + select IOMMU_API + config FSL_PAMU bool "Freescale IOMMU support" depends on PCI diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 1fb695854809..1dbcc89ebe4c 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_IOMMU_API) += iommu.o obj-$(CONFIG_IOMMU_API) += iommu-traces.o obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o +obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c new file mode 100644 index 000000000000..8b4afb7c63ae --- /dev/null +++ b/drivers/iommu/iommu-sva.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Manage PASIDs and bind process address spaces to devices. + * + * Copyright (C) 2018 ARM Ltd. + */ + +#include +#include + +/** + * iommu_sva_device_init() - Initialize Shared Virtual Addressing for a device + * @dev: the device + * @features: bitmask of features that need to be initialized + * @max_pasid: max PASID value supported by the device + * + * Users of the bind()/unbind() API must call this function to initialize all + * features required for SVA. + * + * The device must support multiple address spaces (e.g. PCI PASID). By default + * the PASID allocated during bind() is limited by the IOMMU capacity, and by + * the device PASID width defined in the PCI capability or in the firmware + * description. Setting @max_pasid to a non-zero value smaller than this limit + * overrides it. + * + * The device should not be performing any DMA while this function is running, + * otherwise the behavior is undefined. + * + * Return 0 if initialization succeeded, or an error. + */ +int iommu_sva_device_init(struct device *dev, unsigned long features, + unsigned int max_pasid) +{ + int ret; + struct iommu_sva_param *param; + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + + if (!domain || !domain->ops->sva_device_init) + return -ENODEV; + + if (features) + return -EINVAL; + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + return -ENOMEM; + + param->features = features; + param->max_pasid = max_pasid; + + /* + * IOMMU driver updates the limits depending on the IOMMU and device + * capabilities. + */ + ret = domain->ops->sva_device_init(dev, param); + if (ret) + goto err_free_param; + + mutex_lock(&dev->iommu_param->lock); + if (dev->iommu_param->sva_param) + ret = -EEXIST; + else + dev->iommu_param->sva_param = param; + mutex_unlock(&dev->iommu_param->lock); + if (ret) + goto err_device_shutdown; + + return 0; + +err_device_shutdown: + if (domain->ops->sva_device_shutdown) + domain->ops->sva_device_shutdown(dev, param); + +err_free_param: + kfree(param); + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_sva_device_init); + +/** + * iommu_sva_device_shutdown() - Shutdown Shared Virtual Addressing for a device + * @dev: the device + * + * Disable SVA. Device driver should ensure that the device isn't performing any + * DMA while this function is running. + */ +int iommu_sva_device_shutdown(struct device *dev) +{ + struct iommu_sva_param *param; + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + + if (!domain) + return -ENODEV; + + mutex_lock(&dev->iommu_param->lock); + param = dev->iommu_param->sva_param; + dev->iommu_param->sva_param = NULL; + mutex_unlock(&dev->iommu_param->lock); + if (!param) + return -ENODEV; + + if (domain->ops->sva_device_shutdown) + domain->ops->sva_device_shutdown(dev, param); + + kfree(param); + + return 0; +} +EXPORT_SYMBOL_GPL(iommu_sva_device_shutdown); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0933f726d2e6..2efe7738bedb 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -212,6 +212,12 @@ struct page_response_msg { u64 private_data; }; +struct iommu_sva_param { + unsigned long features; + unsigned int min_pasid; + unsigned int max_pasid; +}; + /** * struct iommu_ops - iommu ops and capabilities * @capable: check capability @@ -219,6 +225,8 @@ struct page_response_msg { * @domain_free: free iommu domain * @attach_dev: attach device to an iommu domain * @detach_dev: detach device from an iommu domain + * @sva_device_init: initialize Shared Virtual Adressing for a device + * @sva_device_shutdown: shutdown Shared Virtual Adressing for a device * @map: map a physically contiguous memory region to an iommu domain * @unmap: unmap a physically contiguous memory region from an iommu domain * @map_sg: map a scatter-gather list of physically contiguous memory chunks @@ -256,6 +264,10 @@ struct iommu_ops { int (*attach_dev)(struct iommu_domain *domain, struct device *dev); void (*detach_dev)(struct iommu_domain *domain, struct device *dev); + int (*sva_device_init)(struct device *dev, + struct iommu_sva_param *param); + void (*sva_device_shutdown)(struct device *dev, + struct iommu_sva_param *param); int (*map)(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, @@ -413,6 +425,7 @@ struct iommu_fault_param { * struct iommu_param - collection of per-device IOMMU data * * @fault_param: IOMMU detected device fault reporting data + * @sva_param: SVA parameters * * TODO: migrate other per device data pointers under iommu_dev_data, e.g. * struct iommu_group *iommu_group; @@ -421,6 +434,7 @@ struct iommu_fault_param { struct iommu_param { struct mutex lock; struct iommu_fault_param *fault_param; + struct iommu_sva_param *sva_param; }; int iommu_device_register(struct iommu_device *iommu); @@ -920,4 +934,22 @@ static inline int iommu_sva_invalidate(struct iommu_domain *domain, #endif /* CONFIG_IOMMU_API */ +#ifdef CONFIG_IOMMU_SVA +extern int iommu_sva_device_init(struct device *dev, unsigned long features, + unsigned int max_pasid); +extern int iommu_sva_device_shutdown(struct device *dev); +#else /* CONFIG_IOMMU_SVA */ +static inline int iommu_sva_device_init(struct device *dev, + unsigned long features, + unsigned int max_pasid) +{ + return -ENODEV; +} + +static inline int iommu_sva_device_shutdown(struct device *dev) +{ + return -ENODEV; +} +#endif /* CONFIG_IOMMU_SVA */ + #endif /* __LINUX_IOMMU_H */