From patchwork Thu Jul 23 14:57:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681161 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 89FFA722 for ; Thu, 23 Jul 2020 15:07:50 +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 5F6C220771 for ; Thu, 23 Jul 2020 15:07:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="S069Ktjb"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="A3x9ZNUi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F6C220771 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=gu0kGPyhmnD3RHkOo7nsdY0vaPYgH3iHjM2NHxnbKJI=; b=S069Ktjb3QisfXqZYTPk6fE8u 3gSS4qby8M5iuFal6aJreooGcXG0mLqOFIBHFgDw5EIKygRCqL6jBHhSPI7lENyBEhGdt9ugIbi+M PWA2aOxiafh4hgB3/xvb1lA5NnVaQ2L51vlRWOy6ERvS3mUkT1NzA5b467GEkaOkFoI51uy7bjL2y QbPPb+IpX9QmCGriGorem0bHtsM6J8lb/BDo4pY1uFKn2Muhk207hbocAUFwLlPdfjxIvuBqSW5r8 fHyX06uEidKCmyl/08Z4+0JhuSO6RjR4kVfqNYdou62JHgNFT3xMyQmTS9itGKw7bFWXM/N/JIl83 hg3ga4JHQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnB-0002Mn-MK; Thu, 23 Jul 2020 15:05:53 +0000 Received: from mail-ed1-x541.google.com ([2a00:1450:4864:20::541]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycn7-0002KA-M8 for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:05:51 +0000 Received: by mail-ed1-x541.google.com with SMTP id d16so4732182edz.12 for ; Thu, 23 Jul 2020 08:05:48 -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=+GSsqAmRYo5YOIIF67wsMh/QH5K3e+p6piN1dBGQeZo=; b=A3x9ZNUiNkchSCqN/Y2+rVNEG3cooy0NdE4kKd7eF/yJvy+eswwswqhDneZrH+0MDs RmA4Nif/EZz90XMTqfeItoWYJlHqiEICJJlaLRij1mMMCTpUfr8fwGBx4nFVx3Re+RPU Ed0DGk0hVY2QLyVaVA0DLQAd5VrmmzU22wZmOI6SKxiPhLuKV5F/uYLOv6zzj0qwcdYh S8AkkV9WpcC+Ub1/+qQ6N1mNOGESjUBC9EWMGEQ+RiM2yNBzSjOvlcd0YL1WTXmuRPQ8 Ykf5ZbhAWgb40CDYdk0/Nlsp7h1U+4XL64SViJMsNsXbz+VSM19XhhPngaq0PvEVtL2q ULlw== 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=+GSsqAmRYo5YOIIF67wsMh/QH5K3e+p6piN1dBGQeZo=; b=imbgKTOjxvkcmmjrRwdKW8VFmMiXfRnSAxNdpZT71AZPUc/yGuXYtkwCvCxhz8pN1A IRehYqEZpQpkgccYJYiEi9yykE/AngWFSh/rQ2al6Z/2UcWcjCLQtV+mEisSmjsJ7Dap Xmlq+pSfYO4oDBgdoGzGST3AIP+jJg2B9TmVHIiH0/LeHtw2u2B86RPxPzgjltpRnHlh /58BrrPoL3LE901kTL2ReieFK+mVHUg3+Niozn3d9VvM/E/6vuxYa35Xrl9s3yyP1BpX 7tdFWPxv5tdIhW67BpNKsi0u3GadiDs0ISMht0Nt6Epe/CdRvqBjBdlcbdbMlcMyuyjo WDPw== X-Gm-Message-State: AOAM531XzCan1moOq2muighGVqivXGSdDE7dIMDBQkdJhaukyNJFygpu SrjWKnJBxr8IzftpNutH6t8W2Q== X-Google-Smtp-Source: ABdhPJyXttub8o+VyJgO+UKD+ccLd3hT5h2Uwz/upuFRlXsrp3TZZ1ZjH8cTHC96Joh6797HCzPm2A== X-Received: by 2002:a50:ee87:: with SMTP id f7mr4628941edr.355.1595516747245; Thu, 23 Jul 2020 08:05:47 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:46 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 01/13] mm: Define pasid in mm Date: Thu, 23 Jul 2020 16:57:13 +0200 Message-Id: <20200723145724.3014766-2-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110550_464094_F1602600 X-CRM114-Status: GOOD ( 11.53 ) 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 [2a00:1450:4864:20:0:0:0:541 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Tony Luck , Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Fenghua Yu PASID is shared by all threads in a process. So the logical place to keep track of it is in the "mm". Both ARM and X86 need to use the PASID in the "mm". Suggested-by: Christoph Hellwig Signed-off-by: Fenghua Yu Reviewed-by: Tony Luck --- https://lore.kernel.org/linux-iommu/1594684087-61184-8-git-send-email-fenghua.yu@intel.com/ --- --- include/linux/mm_types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 64ede5f150dc..d61285cfe027 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -538,6 +538,10 @@ struct mm_struct { atomic_long_t hugetlb_usage; #endif struct work_struct async_put_work; + +#ifdef CONFIG_IOMMU_SUPPORT + u32 pasid; +#endif } __randomize_layout; /* From patchwork Thu Jul 23 14:57:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681165 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 3CE45138A for ; Thu, 23 Jul 2020 15:08:07 +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 133CD207BB for ; Thu, 23 Jul 2020 15:08:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="DO841mD8"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="lk0/XPlr" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 133CD207BB 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=TcqNhaJic4SNKz9Bv1+aa/a/RgzFlNQw8/gVxNX4e04=; b=DO841mD8+qSFO/b4XTBq05sRB UoYb/IVCktH/Mw/rRYxynN4Oj84PDByYqNgKGR+dSjekwZMCs2oIPQdTtZJh0zyjOXhXPN24Z44Oe Cz9Qk9yOMC05FEmXvwExdpaFLB8OQl215JuEXXNED40KaBDP51XxmurWq4uAW1Jr9oNJ147ojKvxg qx2lMO/d7oua3Qv6ZpYqGUTWwacAhcOgJ46ppe6U2wHaVJLaR0ylsM4KHgMYRe0IXMUvDlDAvnTCT ngv9Hj7C+upI1P/+KjFpNa4mBAL83CZZLEd1I4VwPhLDOqkK3rerz/N9pf2UADXSQmIul8jHOtDjn GNdXFu/rw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnY-0002Vk-H8; Thu, 23 Jul 2020 15:06:16 +0000 Received: from mail-ej1-x643.google.com ([2a00:1450:4864:20::643]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycn7-0002KC-ML for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:05:57 +0000 Received: by mail-ej1-x643.google.com with SMTP id ga4so6720907ejb.11 for ; Thu, 23 Jul 2020 08:05:49 -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=BfF5mSAeuK6GNmSG6ImiNv8aoTdn7LDUcDTf16UYC0A=; b=lk0/XPlr3PKH7Nk45lh8t2O9OdaaB5Zyoq21/6dI6m+zIRUsrXGTfwSmWGrpB6jORX RINvO4lyWUN/KGKSRedd4/iFaUMCWxDTfer4DjbZKZolSoCyJT44faUl0fs/g4/GTdua ODfq0kthEqQAheIDweOUZeH1LvVNn1yxtGE58sXbMequIAS0w2S5noRx2rlct5jT+Qbo M+i1YKkSFHs+Xg0O/4AEkwIGZemKhN7MOw2J/xvrc+k5tgyCdZn4mi339uUUVfOvvUmd hnA0dbm23sVasKVoiGgwVI+4cnEo3pIjTWILskSYxzyxQXxvhWUY5XGWGI0OvtTgsbtT n8VA== 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=BfF5mSAeuK6GNmSG6ImiNv8aoTdn7LDUcDTf16UYC0A=; b=YJlLBzaUF4SKMbJQH7g66BBvxhdDzH6LM3OULfEeT/QJu8Mn23tdSYYkIiiyRHRI8Y GK95wQWH29uDzzHi8yp/tI9zwT/2OOC9QU1pfCZs2jqe2E4HaaKI94eqYxLc5FJfpj/R 2/Ksc12CcTvJd6D5L8fuMXniF0pjaaL/MNtKN3accirsB0HX/OmisOAupTuICc11vyV5 YTEH4r1OPzhO4XL/Nag11izPWkG/OfEEcSwj0NqWqTDDgrHiBNj+w5EwCPmnqtwRA0Xi W/59LYFUnACMlZeg/b0/yG7QGbeNhcdvam7/Tdnm/nAys4Ay0kfDxo8ItF18dPNVdAGj yQdw== X-Gm-Message-State: AOAM532FWQl8BmUw516ulJ5MPk3FkUVNX9GXQOqhEtBVpACeGwR7GPGK sDZKLXh9PYnW5yzC/BbxTNq4yQ== X-Google-Smtp-Source: ABdhPJztenR5csLNhM439x8AXYy3fLBVtK93JFVn5FR0Q2kR3j3ecwgQY1A1tchoy6d2cKjeBZZUsQ== X-Received: by 2002:a17:906:2616:: with SMTP id h22mr4748563ejc.154.1595516748393; Thu, 23 Jul 2020 08:05:48 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:47 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 02/13] iommu/ioasid: Add ioasid references Date: Thu, 23 Jul 2020 16:57:14 +0200 Message-Id: <20200723145724.3014766-3-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110550_541193_445C3693 X-CRM114-Status: GOOD ( 19.20 ) 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 [2a00:1450:4864:20:0:0:0:643 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Let IOASID users take references to existing ioasids with ioasid_get(). ioasid_put() drops a reference and only frees the ioasid when its reference number is zero. It returns true if the ioasid was freed. For drivers that don't call ioasid_get(), ioasid_put() is the same as ioasid_free(). Reviewed-by: Lu Baolu Signed-off-by: Jean-Philippe Brucker --- include/linux/ioasid.h | 10 ++++++++-- drivers/iommu/intel/iommu.c | 4 ++-- drivers/iommu/intel/svm.c | 6 +++--- drivers/iommu/ioasid.c | 38 +++++++++++++++++++++++++++++++++---- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h index 6f000d7a0ddc..e9dacd4b9f6b 100644 --- a/include/linux/ioasid.h +++ b/include/linux/ioasid.h @@ -34,7 +34,8 @@ struct ioasid_allocator_ops { #if IS_ENABLED(CONFIG_IOASID) ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, void *private); -void ioasid_free(ioasid_t ioasid); +void ioasid_get(ioasid_t ioasid); +bool ioasid_put(ioasid_t ioasid); void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, bool (*getter)(void *)); int ioasid_register_allocator(struct ioasid_allocator_ops *allocator); @@ -48,10 +49,15 @@ static inline ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, return INVALID_IOASID; } -static inline void ioasid_free(ioasid_t ioasid) +static inline void ioasid_get(ioasid_t ioasid) { } +static inline bool ioasid_put(ioasid_t ioasid) +{ + return false; +} + static inline void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, bool (*getter)(void *)) { diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index d759e7234e98..fd7a65d4f091 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -5139,7 +5139,7 @@ static void auxiliary_unlink_device(struct dmar_domain *domain, domain->auxd_refcnt--; if (!domain->auxd_refcnt && domain->default_pasid > 0) - ioasid_free(domain->default_pasid); + ioasid_put(domain->default_pasid); } static int aux_domain_add_dev(struct dmar_domain *domain, @@ -5201,7 +5201,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain, spin_unlock(&iommu->lock); spin_unlock_irqrestore(&device_domain_lock, flags); if (!domain->auxd_refcnt && domain->default_pasid > 0) - ioasid_free(domain->default_pasid); + ioasid_put(domain->default_pasid); return ret; } diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index 6c87c807a0ab..b078a697c42e 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -546,7 +546,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct svm_dev_ops *ops, if (mm) { ret = mmu_notifier_register(&svm->notifier, mm); if (ret) { - ioasid_free(svm->pasid); + ioasid_put(svm->pasid); kfree(svm); kfree(sdev); goto out; @@ -564,7 +564,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct svm_dev_ops *ops, if (ret) { if (mm) mmu_notifier_unregister(&svm->notifier, mm); - ioasid_free(svm->pasid); + ioasid_put(svm->pasid); kfree(svm); kfree(sdev); goto out; @@ -639,7 +639,7 @@ static int intel_svm_unbind_mm(struct device *dev, int pasid) kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { - ioasid_free(svm->pasid); + ioasid_put(svm->pasid); if (svm->mm) mmu_notifier_unregister(&svm->notifier, svm->mm); list_del(&svm->list); diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c index 0f8dd377aada..50ee27bbd04e 100644 --- a/drivers/iommu/ioasid.c +++ b/drivers/iommu/ioasid.c @@ -2,7 +2,7 @@ /* * I/O Address Space ID allocator. There is one global IOASID space, split into * subsets. Users create a subset with DECLARE_IOASID_SET, then allocate and - * free IOASIDs with ioasid_alloc and ioasid_free. + * free IOASIDs with ioasid_alloc and ioasid_put. */ #include #include @@ -15,6 +15,7 @@ struct ioasid_data { struct ioasid_set *set; void *private; struct rcu_head rcu; + refcount_t refs; }; /* @@ -314,6 +315,7 @@ ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, data->set = set; data->private = private; + refcount_set(&data->refs, 1); /* * Custom allocator needs allocator data to perform platform specific @@ -346,11 +348,34 @@ ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, EXPORT_SYMBOL_GPL(ioasid_alloc); /** - * ioasid_free - Free an IOASID + * ioasid_get - obtain a reference to the IOASID + */ +void ioasid_get(ioasid_t ioasid) +{ + struct ioasid_data *ioasid_data; + + spin_lock(&ioasid_allocator_lock); + ioasid_data = xa_load(&active_allocator->xa, ioasid); + if (ioasid_data) + refcount_inc(&ioasid_data->refs); + else + WARN_ON(1); + spin_unlock(&ioasid_allocator_lock); +} +EXPORT_SYMBOL_GPL(ioasid_get); + +/** + * ioasid_put - Release a reference to an ioasid * @ioasid: the ID to remove + * + * Put a reference to the IOASID, free it when the number of references drops to + * zero. + * + * Return: %true if the IOASID was freed, %false otherwise. */ -void ioasid_free(ioasid_t ioasid) +bool ioasid_put(ioasid_t ioasid) { + bool free = false; struct ioasid_data *ioasid_data; spin_lock(&ioasid_allocator_lock); @@ -360,6 +385,10 @@ void ioasid_free(ioasid_t ioasid) goto exit_unlock; } + free = refcount_dec_and_test(&ioasid_data->refs); + if (!free) + goto exit_unlock; + active_allocator->ops->free(ioasid, active_allocator->ops->pdata); /* Custom allocator needs additional steps to free the xa element */ if (active_allocator->flags & IOASID_ALLOCATOR_CUSTOM) { @@ -369,8 +398,9 @@ void ioasid_free(ioasid_t ioasid) exit_unlock: spin_unlock(&ioasid_allocator_lock); + return free; } -EXPORT_SYMBOL_GPL(ioasid_free); +EXPORT_SYMBOL_GPL(ioasid_put); /** * ioasid_find - Find IOASID data From patchwork Thu Jul 23 14:57:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681167 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 2BBE6722 for ; Thu, 23 Jul 2020 15:08:22 +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 0502C207BB for ; Thu, 23 Jul 2020 15:08:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="CYxNCvov"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="ZweWZh0Q" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0502C207BB 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=8dLrHwWQc8DSK3b63rDtFoQZmBZmljZSNfuPRNzSHs4=; b=CYxNCvovFYv2lMRFyatr3aDSn cl1PpIaF/GjlSPaJUptMZIF7C+E+AnQ6YC9BNPtuzyqkVIYtL96tJDS7bWpKCFvTGHMkELLvubtuT oYDvX8u9mMx3/wnDIsygmfyX2aCC0UKgx9jAudBA6Vh3/2ULsXFXT8jpVNC8dE+cjn2MOh/cJd+E4 eaq+rZrQXZ9Vg73OfpBPNw61g3gQ3Ao9X7gt4gJKQrF46GeFGc0pQkLn3z9/wCB3jG6+zEkBjJVAo 9HpHd/r+KBQWCrdw1e6T0GgM7LKulKUZ9kaky463bC7raK3Jys2jkWn5EDcLsFNsNVVY/5acTewdh lCe7ZUcLQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnO-0002U0-OY; Thu, 23 Jul 2020 15:06:06 +0000 Received: from mail-ed1-x543.google.com ([2a00:1450:4864:20::543]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycn8-0002KH-TA for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:05:56 +0000 Received: by mail-ed1-x543.google.com with SMTP id a1so4731816edt.10 for ; Thu, 23 Jul 2020 08:05:50 -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=QSjnF2ORoRKzIxf85Zu/xkv4tbAQK9/wWrANBTFZ96U=; b=ZweWZh0Q/Fi1xL5hY3ZhgY2f5mGSHwIt0qKTrncr7BidMJ6iqwczf44naj8YGN75Ka gotcFJjp4JDspsOWZP8/ZpZujkUsJkFX5YGvT8ghbpHpyWRiK7WO0MTQwoczOwQ6cKl4 MjHHDImP+T/iMFt3RxzICpfnYrVI2RnAUqWAnUuwpmNjq0v0i9J3HHhxMcRxUVMjQnXg L4lx0lC+QwrBhp+6Ev8lfwCSpBak96BwbcoE+5oKlg9bXK8nVPXV6V0+dtCKu3f8O0em ooJcMDN2HeIdTW68S4//Z4degLFBizHTwQ+dw4t4K7YLqvwzQC2MITEIGC3dcx712y0L /onQ== 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=QSjnF2ORoRKzIxf85Zu/xkv4tbAQK9/wWrANBTFZ96U=; b=OgqO7cRWzp9WwbhdvHZqfhD3NwyGbhkdGknT/xH3ZkirAZpix7SUa3VM09IrxSwF9W r/isuKc0vhrDjYnHwvMH3G8iIleZeIQP9fbwuFQqRn1x6HzzBMcg1utMIUq04WpWrBK7 4RdP2NtrrApM8Z5NhUzrdVK9vKeAItVF8wxD/GPfv9jpbDOKaCLf4R6ejeo1K1Tty2qL L6Oni+lQcVCMYTZcHbgxvJuBSNzUN5po/3miOWMhPVmYhBkDS8L64vRSR+sswyGUrLFh TuV2o20j74Cioj5SKhLycn1GRQ9WjU31o1cBAzgzLKNnb+3Dskf50F4YDRTyOliEokrA /Zsg== X-Gm-Message-State: AOAM531vdsrAgrfxEImhbQHxgbrQYYRhcXJLmkuZHVD0fuirDcIPH269 7y9Pg0Xi0eZ4HzvfrwgjxCb7q6PP6Ro= X-Google-Smtp-Source: ABdhPJw1XDc31MtzxIte5n+3QxgvO/tkwT9UKSEC+CRNXlP+BwUMek0S7VbhzC2PJXcGnpv3j4pGmA== X-Received: by 2002:a05:6402:1c07:: with SMTP id ck7mr4608743edb.297.1595516749545; Thu, 23 Jul 2020 08:05:49 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:48 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 03/13] iommu/sva: Add PASID helpers Date: Thu, 23 Jul 2020 16:57:15 +0200 Message-Id: <20200723145724.3014766-4-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110551_002751_E7F41EB0 X-CRM114-Status: GOOD ( 21.11 ) 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 [2a00:1450:4864:20:0:0:0:543 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Let IOMMU drivers allocate a single PASID per mm. Store the mm in the IOASID set to allow refcounting and searching mm by PASID, when handling an I/O page fault. Reviewed-by: Lu Baolu Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/Kconfig | 5 +++ drivers/iommu/Makefile | 1 + drivers/iommu/iommu-sva-lib.h | 15 +++++++ drivers/iommu/iommu-sva-lib.c | 85 +++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 drivers/iommu/iommu-sva-lib.h create mode 100644 drivers/iommu/iommu-sva-lib.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 6dc49ed8377a..490c86e3615a 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -102,6 +102,11 @@ config IOMMU_DMA select IRQ_MSI_IOMMU select NEED_SG_DMA_LENGTH +# Shared Virtual Addressing library +config IOMMU_SVA_LIB + bool + select IOASID + config FSL_PAMU bool "Freescale IOMMU support" depends on PCI diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 342190196dfb..0fe5a7f9bc69 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -38,3 +38,4 @@ obj-$(CONFIG_S390_IOMMU) += s390-iommu.o obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o +obj-$(CONFIG_IOMMU_SVA_LIB) += iommu-sva-lib.o diff --git a/drivers/iommu/iommu-sva-lib.h b/drivers/iommu/iommu-sva-lib.h new file mode 100644 index 000000000000..b40990aef3fd --- /dev/null +++ b/drivers/iommu/iommu-sva-lib.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SVA library for IOMMU drivers + */ +#ifndef _IOMMU_SVA_LIB_H +#define _IOMMU_SVA_LIB_H + +#include +#include + +int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max); +void iommu_sva_free_pasid(struct mm_struct *mm); +struct mm_struct *iommu_sva_find(ioasid_t pasid); + +#endif /* _IOMMU_SVA_LIB_H */ diff --git a/drivers/iommu/iommu-sva-lib.c b/drivers/iommu/iommu-sva-lib.c new file mode 100644 index 000000000000..db7e6c104d6b --- /dev/null +++ b/drivers/iommu/iommu-sva-lib.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helpers for IOMMU drivers implementing SVA + */ +#include +#include + +#include "iommu-sva-lib.h" + +static DEFINE_MUTEX(iommu_sva_lock); +static DECLARE_IOASID_SET(iommu_sva_pasid); + +/** + * iommu_sva_alloc_pasid - Allocate a PASID for the mm + * @mm: the mm + * @min: minimum PASID value (inclusive) + * @max: maximum PASID value (inclusive) + * + * Try to allocate a PASID for this mm, or take a reference to the existing one + * provided it fits within the [min, max] range. On success the PASID is + * available in mm->pasid, and must be released with iommu_sva_free_pasid(). + * + * Returns 0 on success and < 0 on error. + */ +int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) +{ + int ret = 0; + ioasid_t pasid; + + if (min == INVALID_IOASID || max == INVALID_IOASID || + min == 0 || max < min) + return -EINVAL; + + mutex_lock(&iommu_sva_lock); + if (mm->pasid) { + if (mm->pasid >= min && mm->pasid <= max) + ioasid_get(mm->pasid); + else + ret = -EOVERFLOW; + } else { + pasid = ioasid_alloc(&iommu_sva_pasid, min, max, mm); + if (pasid == INVALID_IOASID) + ret = -ENOMEM; + else + mm->pasid = pasid; + } + mutex_unlock(&iommu_sva_lock); + return ret; +} +EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid); + +/** + * iommu_sva_free_pasid - Release the mm's PASID + * @mm: the mm. + * + * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() + */ +void iommu_sva_free_pasid(struct mm_struct *mm) +{ + mutex_lock(&iommu_sva_lock); + if (ioasid_put(mm->pasid)) + mm->pasid = 0; + mutex_unlock(&iommu_sva_lock); +} +EXPORT_SYMBOL_GPL(iommu_sva_free_pasid); + +/* ioasid wants a void * argument */ +static bool __mmget_not_zero(void *mm) +{ + return mmget_not_zero(mm); +} + +/** + * iommu_sva_find() - Find mm associated to the given PASID + * @pasid: Process Address Space ID assigned to the mm + * + * On success a reference to the mm is taken, and must be released with mmput(). + * + * Returns the mm corresponding to this PASID, or an error if not found. + */ +struct mm_struct *iommu_sva_find(ioasid_t pasid) +{ + return ioasid_find(&iommu_sva_pasid, pasid, __mmget_not_zero); +} +EXPORT_SYMBOL_GPL(iommu_sva_find); From patchwork Thu Jul 23 14:57:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681169 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 1844D138A for ; Thu, 23 Jul 2020 15:08:38 +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 D3E9420771 for ; Thu, 23 Jul 2020 15:08:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="rlJy+12K"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="TIgqDcGP" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D3E9420771 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=qXR+EErixUNuf5We0mMsxl2bXqzkDo/8kqK7i+KmDg4=; b=rlJy+12KbMV9PUwjWWrcIfvEv amvRT79MAWLmYBw2D3694pZt8Zns1mb1Zh5dpBVqaIDA1qTWfkKa4/U6W2SbkGygqN/0WAFHc9EEp 5ruZGVXg3RLBM2ktZ13BOwd0mdzHa5IUWdCZ1R9vMQb9eD9XuzmgN8AJkj0zQpr9jlcyObANbfPrQ G+VGSwEnaD0pWpQy3syaa5lrIi8QkHkqzRZeIyQ4lb2aZFcTHbpMKXYABKuQZTiB7JZ+jHAr4gENK LGj1K0XwlMB4DzJBK8jEOmz+5SE/S/bLIatO3jwIKBOB3xkQlAipERt0THeyHaLi3Tat1B/HpDdo4 Lw4+czBsg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnp-0002cR-DA; Thu, 23 Jul 2020 15:06:33 +0000 Received: from mail-ej1-x641.google.com ([2a00:1450:4864:20::641]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnA-0002M0-6j for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:00 +0000 Received: by mail-ej1-x641.google.com with SMTP id n22so6752009ejy.3 for ; Thu, 23 Jul 2020 08:05:51 -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=kyLB1szUBQsUyuDZEpVs6lUMCzD0UrnQim8ogBM1DBc=; b=TIgqDcGPETOax2H76d+vZEBy1zdv63MybiopLlR5rP602xAa2N/xycNbrwcqXVpEnJ EWI44u9SK/S9yc+5y/zUAphoZCqGYVb3LQ3Jhd9IXv/3PlTQmNTdvczY9ldDPgWW/kVH SDPjqEhzW5Zzc+5SF+gjxjdVjcDuXaQi4W13y3wz55uBHZUxGOe1SnUE52hW8Q9eFxtR CImx+fPZ7oyZqudrfJcVdq6sQqPUySrFS7kP9OQHALQ2Cn4xFA7aVPgMe/2woBP/8iMO wzWKfxJblq4inkYojADj7cwnFD55gA6OP7Fz9VWUTrwCjMUyfJaifkazmKFBuHM0cazd XY4A== 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=kyLB1szUBQsUyuDZEpVs6lUMCzD0UrnQim8ogBM1DBc=; b=bLsUHh3u0LVY9mU4PCpU3iiEUfvHy8fHdfb2vuK8P8lq/506TK+Nvu4gUzJ9U8pqvQ Rrn3S81XncvippRGjJjfFSBWAWMV21GTlWPs8ia+EbE4Bh348OzP06QEzl8bHfa1XHeh QlJSjC0b306N0WN3+/75bctegk5C6CGvJZGKdkepyfixJNwJRDRCQ2eKJDom2PMEgdY2 JlzViLyDm2q851Yksiz7iSPc9+Ore/5CHJakGJ2janoGHoC8h/oS5E1/WbTFh9V7iOrH uQozp+m2eTFF60jv3Fdw5NgSU7MoL9ywNi/arwB6BBJq9P0uY3rkL/GUlGHJbGtOiH14 fj7g== X-Gm-Message-State: AOAM533xqymsvYZeJLU2Ru3xKaNwM/jwsaRJreIlgRl5ECbDcbMrBcu/ fMSOgIilm09rj9wbyLR/8hZNjg== X-Google-Smtp-Source: ABdhPJxT81WzrRL69fRaYXLwYWkurDucRWTnYTaHFYjHmtV2KeNSCodT01sypTXX787HWuZiSk9GWQ== X-Received: by 2002:a17:906:8601:: with SMTP id o1mr4957765ejx.326.1595516750851; Thu, 23 Jul 2020 08:05:50 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:50 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 04/13] arm64: mm: Pin down ASIDs for sharing mm with devices Date: Thu, 23 Jul 2020 16:57:16 +0200 Message-Id: <20200723145724.3014766-5-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110552_362950_5F5363B5 X-CRM114-Status: GOOD ( 30.62 ) 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 [2a00:1450:4864:20:0:0:0:641 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org To enable address space sharing with the IOMMU, introduce arm64_mm_context_get() and arm64_mm_context_put(), that pin down a context and ensure that it will keep its ASID after a rollover. Export the symbols to let the modular SMMUv3 driver use them. Pinning is necessary because a device constantly needs a valid ASID, unlike tasks that only require one when running. Without pinning, we would need to notify the IOMMU when we're about to use a new ASID for a task, and it would get complicated when a new task is assigned a shared ASID. Consider the following scenario with no ASID pinned: 1. Task t1 is running on CPUx with shared ASID (gen=1, asid=1) 2. Task t2 is scheduled on CPUx, gets ASID (1, 2) 3. Task tn is scheduled on CPUy, a rollover occurs, tn gets ASID (2, 1) We would now have to immediately generate a new ASID for t1, notify the IOMMU, and finally enable task tn. We are holding the lock during all that time, since we can't afford having another CPU trigger a rollover. The IOMMU issues invalidation commands that can take tens of milliseconds. It gets needlessly complicated. All we wanted to do was schedule task tn, that has no business with the IOMMU. By letting the IOMMU pin tasks when needed, we avoid stalling the slow path, and let the pinning fail when we're out of shareable ASIDs. After a rollover, the allocator expects at least one ASID to be available in addition to the reserved ones (one per CPU). So (NR_ASIDS - NR_CPUS - 1) is the maximum number of ASIDs that can be shared with the IOMMU. Signed-off-by: Jean-Philippe Brucker --- v9: * Make mm->context.pinned a refcount_t. * Prepend exported symbols with arm64_. * Initialize pinned_asid_map with kernel ASID bits if necessary. * Allow pinned_asid_map to be NULL. It could also depend on CONFIG_ARM_SMMU_V3_SVA since it adds an overhead on rollover (memcpy() asid_map instead of memset()), but that can be changed later. * Only set the USER_ASID_BIT if kpti is enabled (previously it was set if CONFIG_UNMAP_KERNEL_AT_EL0). --- arch/arm64/include/asm/mmu.h | 3 + arch/arm64/include/asm/mmu_context.h | 11 ++- arch/arm64/mm/context.c | 105 +++++++++++++++++++++++++-- 3 files changed, 112 insertions(+), 7 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 8444df000181..77b3bd6ddcfa 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -17,11 +17,14 @@ #ifndef __ASSEMBLY__ +#include + typedef struct { atomic64_t id; #ifdef CONFIG_COMPAT void *sigpage; #endif + refcount_t pinned; void *vdso; unsigned long flags; } mm_context_t; diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index b0bd9b55594c..0a10a3412c93 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -177,7 +177,13 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp) #define destroy_context(mm) do { } while(0) void check_and_switch_context(struct mm_struct *mm, unsigned int cpu); -#define init_new_context(tsk,mm) ({ atomic64_set(&(mm)->context.id, 0); 0; }) +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + atomic64_set(&mm->context.id, 0); + refcount_set(&mm->context.pinned, 0); + return 0; +} #ifdef CONFIG_ARM64_SW_TTBR0_PAN static inline void update_saved_ttbr0(struct task_struct *tsk, @@ -250,6 +256,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, void verify_cpu_asid_bits(void); void post_ttbr_update_workaround(void); +unsigned long arm64_mm_context_get(struct mm_struct *mm); +void arm64_mm_context_put(struct mm_struct *mm); + #endif /* !__ASSEMBLY__ */ #endif /* !__ASM_MMU_CONTEXT_H */ diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index d702d60e64da..5c06973b15db 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -27,6 +27,10 @@ static DEFINE_PER_CPU(atomic64_t, active_asids); static DEFINE_PER_CPU(u64, reserved_asids); static cpumask_t tlb_flush_pending; +static unsigned long max_pinned_asids; +static unsigned long nr_pinned_asids; +static unsigned long *pinned_asid_map; + #define ASID_MASK (~GENMASK(asid_bits - 1, 0)) #define ASID_FIRST_VERSION (1UL << asid_bits) @@ -72,7 +76,7 @@ void verify_cpu_asid_bits(void) } } -static void set_kpti_asid_bits(void) +static void set_kpti_asid_bits(unsigned long *map) { unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); /* @@ -81,13 +85,15 @@ static void set_kpti_asid_bits(void) * is set, then the ASID will map only userspace. Thus * mark even as reserved for kernel. */ - memset(asid_map, 0xaa, len); + memset(map, 0xaa, len); } static void set_reserved_asid_bits(void) { - if (arm64_kernel_unmapped_at_el0()) - set_kpti_asid_bits(); + if (pinned_asid_map) + bitmap_copy(asid_map, pinned_asid_map, NUM_USER_ASIDS); + else if (arm64_kernel_unmapped_at_el0()) + set_kpti_asid_bits(asid_map); else bitmap_clear(asid_map, 0, NUM_USER_ASIDS); } @@ -165,6 +171,14 @@ static u64 new_context(struct mm_struct *mm) if (check_update_reserved_asid(asid, newasid)) return newasid; + /* + * If it is pinned, we can keep using it. Note that reserved + * takes priority, because even if it is also pinned, we need to + * update the generation into the reserved_asids. + */ + if (refcount_read(&mm->context.pinned)) + return newasid; + /* * We had a valid ASID in a previous life, so try to re-use * it if possible. @@ -254,6 +268,71 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) cpu_switch_mm(mm->pgd, mm); } +unsigned long arm64_mm_context_get(struct mm_struct *mm) +{ + unsigned long flags; + u64 asid; + + if (!pinned_asid_map) + return 0; + + raw_spin_lock_irqsave(&cpu_asid_lock, flags); + + asid = atomic64_read(&mm->context.id); + + if (refcount_inc_not_zero(&mm->context.pinned)) + goto out_unlock; + + if (nr_pinned_asids >= max_pinned_asids) { + asid = 0; + goto out_unlock; + } + + if (!asid_gen_match(asid)) { + /* + * We went through one or more rollover since that ASID was + * used. Ensure that it is still valid, or generate a new one. + */ + asid = new_context(mm); + atomic64_set(&mm->context.id, asid); + } + + nr_pinned_asids++; + __set_bit(asid2idx(asid), pinned_asid_map); + refcount_set(&mm->context.pinned, 1); + +out_unlock: + raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); + + asid &= ~ASID_MASK; + + /* Set the equivalent of USER_ASID_BIT */ + if (asid && arm64_kernel_unmapped_at_el0()) + asid |= 1; + + return asid; +} +EXPORT_SYMBOL_GPL(arm64_mm_context_get); + +void arm64_mm_context_put(struct mm_struct *mm) +{ + unsigned long flags; + u64 asid = atomic64_read(&mm->context.id); + + if (!pinned_asid_map) + return; + + raw_spin_lock_irqsave(&cpu_asid_lock, flags); + + if (refcount_dec_and_test(&mm->context.pinned)) { + __clear_bit(asid2idx(asid), pinned_asid_map); + nr_pinned_asids--; + } + + raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); +} +EXPORT_SYMBOL_GPL(arm64_mm_context_put); + /* Errata workaround post TTBRx_EL1 update. */ asmlinkage void post_ttbr_update_workaround(void) { @@ -294,8 +373,11 @@ static int asids_update_limit(void) { unsigned long num_available_asids = NUM_USER_ASIDS; - if (arm64_kernel_unmapped_at_el0()) + if (arm64_kernel_unmapped_at_el0()) { num_available_asids /= 2; + if (pinned_asid_map) + set_kpti_asid_bits(pinned_asid_map); + } /* * Expect allocation after rollover to fail if we don't have at least * one more ASID than CPUs. ASID #0 is reserved for init_mm. @@ -303,6 +385,13 @@ static int asids_update_limit(void) WARN_ON(num_available_asids - 1 <= num_possible_cpus()); pr_info("ASID allocator initialised with %lu entries\n", num_available_asids); + + /* + * There must always be an ASID available after rollover. Ensure that, + * even if all CPUs have a reserved ASID and the maximum number of ASIDs + * are pinned, there still is at least one empty slot in the ASID map. + */ + max_pinned_asids = num_available_asids - num_possible_cpus() - 2; return 0; } arch_initcall(asids_update_limit); @@ -317,13 +406,17 @@ static int asids_init(void) panic("Failed to allocate bitmap for %lu ASIDs\n", NUM_USER_ASIDS); + pinned_asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), + sizeof(*pinned_asid_map), GFP_KERNEL); + nr_pinned_asids = 0; + /* * We cannot call set_reserved_asid_bits() here because CPU * caps are not finalized yet, so it is safer to assume KPTI * and reserve kernel ASID's from beginning. */ if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) - set_kpti_asid_bits(); + set_kpti_asid_bits(asid_map); return 0; } early_initcall(asids_init); From patchwork Thu Jul 23 14:57:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681175 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 0AA32138A for ; Thu, 23 Jul 2020 15:09:00 +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 D80BD20771 for ; Thu, 23 Jul 2020 15:08:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="jTot04ix"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="yyjWSRkG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D80BD20771 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=cwoWDN/quucEPzupBnuviKc+nX2d3254lMHInaYbQHw=; b=jTot04ixJjClGh+HaVicmkHO1 0CKbGYYT8O9zbOcXlH429zi9+MBhh52s+grR8asdR11P3H5vqXlglFUngBRX/SDIBHugLJCMNCybI VYtoySsLRARLm5cfxZzsBucVhtq8gIwFLv2bqlyHrJazP8Kg4/BPmY6OZEBueuYt6fgSgm181RxV1 s1v7hUHDHKopN9CD+UwIYv2PyBUC4IR4XqyPyiS4bsGGGN8hlvapChWhTvWturX9fjHOHfa9TCXmj f+6u8cCSk4wzq5AtTmSvcPx6IkECwYYeVKR6pydeXW89bXPJ9ETHEf+Rw8dDg7vUxl5ZNgL6CTKSb 2hVAQK1YQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jyco2-0002fH-94; Thu, 23 Jul 2020 15:06:46 +0000 Received: from mail-ej1-x644.google.com ([2a00:1450:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnB-0002MV-AL for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:01 +0000 Received: by mail-ej1-x644.google.com with SMTP id ga4so6721105ejb.11 for ; Thu, 23 Jul 2020 08:05:52 -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=3oBLBYue5lopM0lAyJB4XMe1LW3YwZEKf+LdekkzBVc=; b=yyjWSRkGKZjbIxLg6mPU5JRg8+zjWo39oxWARO0rFAf7xvEsGx9sDOz4ws1yIjhvN9 laaBD16npKzzbqWOxgQ1jQ5DP1lbbyGo0uydaAIn98Dfa9VG7iibjH4kPNleUWt7xBAY 6QYfA9i4NO/jpmIJkDxtikKePJvycS7XKU2VHPBampdtIG8t6lfZbQn/3G8v50HIw1Xi qWwC2Cj/HY1PevPioAPtVdXXSohRCUMGnS3x2pKhiI615oj8TQFwbKWrqGV7BHur40O3 G832PObyuUgUSbiYqwyAFq9V2+fh+CSPmAGPHiSCEKastn+bUtZSmIKsz7rlrmmvjs5F rmgw== 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=3oBLBYue5lopM0lAyJB4XMe1LW3YwZEKf+LdekkzBVc=; b=V8s37xlJs14a3dcg6Kj0lq0wl+mvDDOUoqCMANVbv3q82BxYHVD8kfZqa5tG/C+Knf rF6VlueUIC84YXD7tii6W3d75EtzC9OPxQpDxLhC/M0oGCY1OiZmvIlpodIaG0qICz1G C4TRLD2sLEl1srcitTgENkQLlZDhupY18CJtNJ4Zk/e8k0gkSXEeqgk3gkeJOWK99bJd 8XUI69Mc3nQML5wiqX+g12zuQ9S/fVIKm+aCN9fR+mGe1NL/Wzt7ntpRSQL/JHpmAhyE fJenvX6ywvQoiqAWVr1gY3PBqwqPgZnsXX+rp1be64DG6jLP/ivvxg6K5pV+VM8xeMKH 0iyQ== X-Gm-Message-State: AOAM531E0qmkMGKE8T5R9hysDwOhK6RE8TDfCgllm7WEugYIBO44XsQV BBGrYSOd8aw86u8Ujh8mhezDKA== X-Google-Smtp-Source: ABdhPJy1E+sscpX7vNRhb33bnirUO+kvVoULyQIuO1logsaTl2zszzpwcTJEk+tphoPbPSBvFTQnXw== X-Received: by 2002:a17:906:c187:: with SMTP id g7mr5071763ejz.108.1595516751982; Thu, 23 Jul 2020 08:05:51 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:51 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 05/13] iommu/io-pgtable-arm: Move some definitions to a header Date: Thu, 23 Jul 2020 16:57:17 +0200 Message-Id: <20200723145724.3014766-6-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110553_480586_0BE5BC8A X-CRM114-Status: GOOD ( 15.07 ) 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 [2a00:1450:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Extract some of the most generic TCR defines, so they can be reused by the page table sharing code. Acked-by: Will Deacon Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/io-pgtable-arm.h | 30 ++++++++++++++++++++++++++++++ drivers/iommu/io-pgtable-arm.c | 27 ++------------------------- MAINTAINERS | 3 +-- 3 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 drivers/iommu/io-pgtable-arm.h diff --git a/drivers/iommu/io-pgtable-arm.h b/drivers/iommu/io-pgtable-arm.h new file mode 100644 index 000000000000..ba7cfdf7afa0 --- /dev/null +++ b/drivers/iommu/io-pgtable-arm.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef IO_PGTABLE_ARM_H_ +#define IO_PGTABLE_ARM_H_ + +#define ARM_LPAE_TCR_TG0_4K 0 +#define ARM_LPAE_TCR_TG0_64K 1 +#define ARM_LPAE_TCR_TG0_16K 2 + +#define ARM_LPAE_TCR_TG1_16K 1 +#define ARM_LPAE_TCR_TG1_4K 2 +#define ARM_LPAE_TCR_TG1_64K 3 + +#define ARM_LPAE_TCR_SH_NS 0 +#define ARM_LPAE_TCR_SH_OS 2 +#define ARM_LPAE_TCR_SH_IS 3 + +#define ARM_LPAE_TCR_RGN_NC 0 +#define ARM_LPAE_TCR_RGN_WBWA 1 +#define ARM_LPAE_TCR_RGN_WT 2 +#define ARM_LPAE_TCR_RGN_WB 3 + +#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL +#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL +#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL +#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL +#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL +#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL +#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL + +#endif /* IO_PGTABLE_ARM_H_ */ diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 04fbd4bf0ff9..f71a2eade04a 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -20,6 +20,8 @@ #include +#include "io-pgtable-arm.h" + #define ARM_LPAE_MAX_ADDR_BITS 52 #define ARM_LPAE_S2_MAX_CONCAT_PAGES 16 #define ARM_LPAE_MAX_LEVELS 4 @@ -100,23 +102,6 @@ #define ARM_LPAE_PTE_MEMATTR_DEV (((arm_lpae_iopte)0x1) << 2) /* Register bits */ -#define ARM_LPAE_TCR_TG0_4K 0 -#define ARM_LPAE_TCR_TG0_64K 1 -#define ARM_LPAE_TCR_TG0_16K 2 - -#define ARM_LPAE_TCR_TG1_16K 1 -#define ARM_LPAE_TCR_TG1_4K 2 -#define ARM_LPAE_TCR_TG1_64K 3 - -#define ARM_LPAE_TCR_SH_NS 0 -#define ARM_LPAE_TCR_SH_OS 2 -#define ARM_LPAE_TCR_SH_IS 3 - -#define ARM_LPAE_TCR_RGN_NC 0 -#define ARM_LPAE_TCR_RGN_WBWA 1 -#define ARM_LPAE_TCR_RGN_WT 2 -#define ARM_LPAE_TCR_RGN_WB 3 - #define ARM_LPAE_VTCR_SL0_MASK 0x3 #define ARM_LPAE_TCR_T0SZ_SHIFT 0 @@ -124,14 +109,6 @@ #define ARM_LPAE_VTCR_PS_SHIFT 16 #define ARM_LPAE_VTCR_PS_MASK 0x7 -#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL -#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL -#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL -#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL -#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL -#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL -#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL - #define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3) #define ARM_LPAE_MAIR_ATTR_MASK 0xff #define ARM_LPAE_MAIR_ATTR_DEVICE 0x04 diff --git a/MAINTAINERS b/MAINTAINERS index b4a43a9e7fbc..b8f00e641c08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1499,8 +1499,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/iommu/arm,smmu* F: drivers/iommu/arm-smmu* -F: drivers/iommu/io-pgtable-arm-v7s.c -F: drivers/iommu/io-pgtable-arm.c +F: drivers/iommu/io-pgtable-arm* ARM SUB-ARCHITECTURES L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) From patchwork Thu Jul 23 14:57:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681171 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 441A6138A for ; Thu, 23 Jul 2020 15:08:43 +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 1AFA720771 for ; Thu, 23 Jul 2020 15:08:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="I2i2d1by"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="QGvAr7eI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1AFA720771 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=CO6yaUUjnzFGmeMF253kmVECURijeyXVv2dKIUO0eco=; b=I2i2d1bySaNGqmV+nt0SaGhJe TERYXsEJ0BOME0W+MyajBOqID9bpAzj2O1vuEOzy0HcFEcwq8s72yJ5A6HqVVtua3ilzSm5omIB8i nKENaw6IfnpGTbLvkNLZLrFGPS+x8rjDBqobE003Vkxx3usySwvq9QVjDlCdNWJ434LjNQHwTTPyk aeUTgEt0/bP0qxucDpcMvbHfUIMDWqvPbpAfaUGABnDjGOkMMg7rF1NnoBOnluB1XgjUHU4WqXE1H P9WxU7KSZPD7WJD8ONyShQxuW7yEuFADAm7p7ywkII1SPaFl3VE++iaodS8f2R4xW2fs9aH4X5DjN 2/Rz20CFg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycoF-0002kf-5m; Thu, 23 Jul 2020 15:06:59 +0000 Received: from mail-ed1-x543.google.com ([2a00:1450:4864:20::543]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnC-0002NX-2T for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:01 +0000 Received: by mail-ed1-x543.google.com with SMTP id h28so4774183edz.0 for ; Thu, 23 Jul 2020 08:05:53 -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=wEZcqIGYqwEOQrL51rqxhyVNs0I0pb8HH3i02KmnnVs=; b=QGvAr7eIz2NPXC6cBdK7i4d4trJ+B8qTxmoUzieiiSlZrXgai9Ns3CqIvbPgVyRyeM cdLleZcpIONx3HPqg0jUbMKhXfQdSBwn8QSKhagvJZsvNY7wfm6r4d94OB9b+9K1Vg34 eEvZ7ZLE6F4CN+ytXxD3DQWTWpHOiAnYxm39JZejeV5BAYdQH3qdHCVjQX/Nj/jqlz6H DKyI7A8FX2caXOt6PFMVADhmCi+R0icDhxTHcpYS1/gzmbYQpVGksNwVpgMNChxuvxyV qq5D+42WF4kKJMxwqarulYrhQGNnMJgJbDpQ9MegJpCG2QU9IPfH5eXs+l55aQGq36gt dkNw== 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=wEZcqIGYqwEOQrL51rqxhyVNs0I0pb8HH3i02KmnnVs=; b=X8joprq0OqVh6vY1Y8WwgCw2g7V1IcmRmn3JvmjWhBYXx3qUFOINAgcWFTtnts7TPx W88mmuFXz4OSV1UeKNSSUpQfOjPRHAYGxJ/S6QFMS2Ls3tKeyK8cavc3lh+jlJUq83+a 9LIXRU1zXHM+JRvrVr5GEAALPRnbengY4LreC2W7iwUQS70j35tmaaVjLbR9Gug68s9A NcetnmhU8DgTfKzHnbb2cMfpZXZuPE4RSS1sA8i7xrooqO05ZqeRaXeoZN9x8/rwZM69 ee1QXFTYvUxCmI5ZOdhzlESLPzqhaC6xNzgL/PfqBxTpm6EWcV+hpnS2S/hkKk5vq6by 4Mtg== X-Gm-Message-State: AOAM5314UQ5nJxyU7l1rJYEfvPKbBJFsdLtFzQ2brel1JbU9AtAfSjZ4 mAJsEYaj6G71SaI/QRE5pUl6oQ== X-Google-Smtp-Source: ABdhPJx4fNwTfUFLzi/fYdsIJQfH1+RwBv+2YVOyYHLcBTwcTU9qUrY0wiaVlC4MG3drv028RhX/oA== X-Received: by 2002:a05:6402:158d:: with SMTP id c13mr4553675edv.103.1595516753225; Thu, 23 Jul 2020 08:05:53 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:52 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 06/13] arm64: cpufeature: Export symbol read_sanitised_ftr_reg() Date: Thu, 23 Jul 2020 16:57:18 +0200 Message-Id: <20200723145724.3014766-7-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110554_254889_2B068CAC X-CRM114-Status: GOOD ( 10.70 ) 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 [2a00:1450:4864:20:0:0:0:543 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, Suzuki K Poulose , robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The SMMUv3 driver would like to read the MMFR0 PARANGE field in order to share CPU page tables with devices. Allow the driver to be built as module by exporting the read_sanitized_ftr_reg() cpufeature symbol. Acked-by: Suzuki K Poulose Signed-off-by: Jean-Philippe Brucker --- arch/arm64/kernel/cpufeature.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9fae0efc80c1..ac2ed25c43d3 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1068,6 +1068,7 @@ u64 read_sanitised_ftr_reg(u32 id) return 0; return regp->sys_val; } +EXPORT_SYMBOL_GPL(read_sanitised_ftr_reg); #define read_sysreg_case(r) \ case r: return read_sysreg_s(r) From patchwork Thu Jul 23 14:57:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681219 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 CEC41138C for ; Thu, 23 Jul 2020 15:27:14 +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 81D4C2086A for ; Thu, 23 Jul 2020 15:27:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="RfraJcM0"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="ZT5BcjZd"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="bJhitXqn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 81D4C2086A 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=uu9mxIA8boB0GQcgPZ3zRTV50FkiY/w+wpVY9jMqOTQ=; b=RfraJcM0GCXxosnZG8V+d5tLS HVJhBItfDCS5vIBTpRYdIbRfzQ2erRfyAIcaFkoftVwpbwu5MTyFme/4fyqUEHTkjDqDNmpoULjQr zisYj9LRMHNZ/UrOpKP+1kRLoxqIRTGQ9Xs0XB8/BK69mWTTpJ18D8DLMYReTiqBlSeCPMlEPM7yQ 0soaONRRL8SVMdZzsU5bowFoN+Or7X4ymaTuBRX3FnObfvMVUHdLIGR0zc16B84OYXxAXFgxgozDc cvohHJ3Ljigw5G1Wf880EayTNxDL1s4LBm+IAaJn6qQzj6vQRX9i1gxpBIJdRPDKCF8CYsOy2WDHF B7c6c11OA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jyd6E-0006sM-KM; Thu, 23 Jul 2020 15:25:34 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jyd65-0006ln-E8 for linux-arm-kernel@merlin.infradead.org; Thu, 23 Jul 2020 15:25:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=WIf5gPtG6PCGrbyPd+nLy+qiINwOX0mX6fkVLor5Fqc=; b=ZT5BcjZdiET5sr735OhrpCV9Bf 0YywH4Q9hrdPoEjrT493iKK2aR9rXYkLQYNbwhrh3MrYu751pfsPZSZTe44TxfdUC2+/qtpwq8yfB EMp0tvg19DkQMMdz3dtb2prUmx668SkqrIKCMOW29uToY7mE8idFhTbEzfi3WI7naxZY4k4cXhKya XmGOA1Mxxcf8TOw6974LatM6cP8WRH5CksItG5Z3bAKApuk3RIW7LAe8P82/6Q+5r6zBt1xs6rktM IdsFjZeve0NqNQsdb4J0nkBn+eT8tkzDdDVbX1JSV/MJSRL8zF0w6HPZDIY3uP/BuXxkq3MWuZNPm M2jc9JEA==; Received: from mail-ed1-x543.google.com ([2a00:1450:4864:20::543]) by casper.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnK-0000gR-BT for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:10 +0000 Received: by mail-ed1-x543.google.com with SMTP id q4so1530919edv.13 for ; Thu, 23 Jul 2020 08:05:55 -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=WIf5gPtG6PCGrbyPd+nLy+qiINwOX0mX6fkVLor5Fqc=; b=bJhitXqnhrXgo8lLgKS6YdzidPHXQSUYXc+UuTsEgmSEigcxNP3/RNNvuqQuuj33d2 S3pUDrUh5CZecRG2lsULF68LWslA0MtMLfaQPn/7bwN4Ek/HuYyvSGQ0RSlxAtKQHJON HIB2iaVtUfga0QNGVgwq7TnqGZjQiCXGdrSgxb16p/ViDWvLvLosVU3riZkgKI/KZ4k0 guROlh1kvICUpIAqwIaU+tzCDlSgwZec3/9/CK/abCXsgmjuJA0Aff8pBHcs+TPrFe/F 1bY63iT/qLGmjWXLuFEwFiCdfnGzKHtxkuAfefWiPAbB4M784v68MX/UryI6YkRRyl7w 3bjQ== 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=WIf5gPtG6PCGrbyPd+nLy+qiINwOX0mX6fkVLor5Fqc=; b=LHYAtqrXiGOI25vWqO9XKqnaaUzJxB4/epzN3Dwh+0ptAh0f3FJxn9U+XX7Ytn9/KZ dD5cLjgmlT3MQN1L+FyBTMIp/YB5jPsuKCX8OeEQuU1SDLwelziLRHgq83kbC8zo+rg4 gRbRcrE01Tb45t8JetqV7k/9ayd2eB4Yjjw7w2tRop3/Ut76O6LLb0AuKQB2OFgbTjIA ItiyavCM4sb3AsIKeZ/Bhb539BQ42PL4sTituc6zMQKuJ5e7UNiQTEu+OI97fKAUyxDa 22rUFhaaBbnaPy77Ujws6BCj3VvU2LvY+O1HPZaOyAEBNQzsDQQXXn1WeQqMk4jvsbBD whNw== X-Gm-Message-State: AOAM531jqg04jO1nKGZQfJ3oNb5tdBI3RmKUkPczC8A7I1dKpjcb0I2f uD2XFMpbL/U4Hx8TtVswudt5Nw== X-Google-Smtp-Source: ABdhPJzeBvXvO3zoDWKc6XUZ/psDTOn7xiNZRLaq7BrSX0f7If1Byi4Ur+4K4NMcjc15VFs5NxjBNw== X-Received: by 2002:a05:6402:16c2:: with SMTP id r2mr4512989edx.127.1595516754393; Thu, 23 Jul 2020 08:05:54 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:53 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 07/13] iommu/arm-smmu-v3: Move definitions to a header Date: Thu, 23 Jul 2020 16:57:19 +0200 Message-Id: <20200723145724.3014766-8-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_160602_917133_48283C25 X-CRM114-Status: GOOD ( 16.89 ) X-Spam-Score: -2.1 (--) X-Spam-Report: SpamAssassin version 3.4.4 on casper.infradead.org summary: Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:543 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Allow sharing structure definitions with the upcoming SVA support for Arm SMMUv3, by moving them to a separate header. We could surgically extract only what is needed but keeping all definitions in one place looks nicer. Signed-off-by: Jean-Philippe Brucker --- v9: new --- drivers/iommu/arm-smmu-v3.h | 675 ++++++++++++++++++++++++++++++++++++ drivers/iommu/arm-smmu-v3.c | 660 +---------------------------------- 2 files changed, 676 insertions(+), 659 deletions(-) create mode 100644 drivers/iommu/arm-smmu-v3.h diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h new file mode 100644 index 000000000000..51a9ce07b2d6 --- /dev/null +++ b/drivers/iommu/arm-smmu-v3.h @@ -0,0 +1,675 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * IOMMU API for ARM architected SMMUv3 implementations. + * + * Copyright (C) 2015 ARM Limited + */ + +#ifndef _ARM_SMMU_V3_H +#define _ARM_SMMU_V3_H + +#include +#include +#include +#include +#include + +/* MMIO registers */ +#define ARM_SMMU_IDR0 0x0 +#define IDR0_ST_LVL GENMASK(28, 27) +#define IDR0_ST_LVL_2LVL 1 +#define IDR0_STALL_MODEL GENMASK(25, 24) +#define IDR0_STALL_MODEL_STALL 0 +#define IDR0_STALL_MODEL_FORCE 2 +#define IDR0_TTENDIAN GENMASK(22, 21) +#define IDR0_TTENDIAN_MIXED 0 +#define IDR0_TTENDIAN_LE 2 +#define IDR0_TTENDIAN_BE 3 +#define IDR0_CD2L (1 << 19) +#define IDR0_VMID16 (1 << 18) +#define IDR0_PRI (1 << 16) +#define IDR0_SEV (1 << 14) +#define IDR0_MSI (1 << 13) +#define IDR0_ASID16 (1 << 12) +#define IDR0_ATS (1 << 10) +#define IDR0_HYP (1 << 9) +#define IDR0_COHACC (1 << 4) +#define IDR0_TTF GENMASK(3, 2) +#define IDR0_TTF_AARCH64 2 +#define IDR0_TTF_AARCH32_64 3 +#define IDR0_S1P (1 << 1) +#define IDR0_S2P (1 << 0) + +#define ARM_SMMU_IDR1 0x4 +#define IDR1_TABLES_PRESET (1 << 30) +#define IDR1_QUEUES_PRESET (1 << 29) +#define IDR1_REL (1 << 28) +#define IDR1_CMDQS GENMASK(25, 21) +#define IDR1_EVTQS GENMASK(20, 16) +#define IDR1_PRIQS GENMASK(15, 11) +#define IDR1_SSIDSIZE GENMASK(10, 6) +#define IDR1_SIDSIZE GENMASK(5, 0) + +#define ARM_SMMU_IDR3 0xc +#define IDR3_RIL (1 << 10) + +#define ARM_SMMU_IDR5 0x14 +#define IDR5_STALL_MAX GENMASK(31, 16) +#define IDR5_GRAN64K (1 << 6) +#define IDR5_GRAN16K (1 << 5) +#define IDR5_GRAN4K (1 << 4) +#define IDR5_OAS GENMASK(2, 0) +#define IDR5_OAS_32_BIT 0 +#define IDR5_OAS_36_BIT 1 +#define IDR5_OAS_40_BIT 2 +#define IDR5_OAS_42_BIT 3 +#define IDR5_OAS_44_BIT 4 +#define IDR5_OAS_48_BIT 5 +#define IDR5_OAS_52_BIT 6 +#define IDR5_VAX GENMASK(11, 10) +#define IDR5_VAX_52_BIT 1 + +#define ARM_SMMU_CR0 0x20 +#define CR0_ATSCHK (1 << 4) +#define CR0_CMDQEN (1 << 3) +#define CR0_EVTQEN (1 << 2) +#define CR0_PRIQEN (1 << 1) +#define CR0_SMMUEN (1 << 0) + +#define ARM_SMMU_CR0ACK 0x24 + +#define ARM_SMMU_CR1 0x28 +#define CR1_TABLE_SH GENMASK(11, 10) +#define CR1_TABLE_OC GENMASK(9, 8) +#define CR1_TABLE_IC GENMASK(7, 6) +#define CR1_QUEUE_SH GENMASK(5, 4) +#define CR1_QUEUE_OC GENMASK(3, 2) +#define CR1_QUEUE_IC GENMASK(1, 0) +/* CR1 cacheability fields don't quite follow the usual TCR-style encoding */ +#define CR1_CACHE_NC 0 +#define CR1_CACHE_WB 1 +#define CR1_CACHE_WT 2 + +#define ARM_SMMU_CR2 0x2c +#define CR2_PTM (1 << 2) +#define CR2_RECINVSID (1 << 1) +#define CR2_E2H (1 << 0) + +#define ARM_SMMU_GBPA 0x44 +#define GBPA_UPDATE (1 << 31) +#define GBPA_ABORT (1 << 20) + +#define ARM_SMMU_IRQ_CTRL 0x50 +#define IRQ_CTRL_EVTQ_IRQEN (1 << 2) +#define IRQ_CTRL_PRIQ_IRQEN (1 << 1) +#define IRQ_CTRL_GERROR_IRQEN (1 << 0) + +#define ARM_SMMU_IRQ_CTRLACK 0x54 + +#define ARM_SMMU_GERROR 0x60 +#define GERROR_SFM_ERR (1 << 8) +#define GERROR_MSI_GERROR_ABT_ERR (1 << 7) +#define GERROR_MSI_PRIQ_ABT_ERR (1 << 6) +#define GERROR_MSI_EVTQ_ABT_ERR (1 << 5) +#define GERROR_MSI_CMDQ_ABT_ERR (1 << 4) +#define GERROR_PRIQ_ABT_ERR (1 << 3) +#define GERROR_EVTQ_ABT_ERR (1 << 2) +#define GERROR_CMDQ_ERR (1 << 0) +#define GERROR_ERR_MASK 0xfd + +#define ARM_SMMU_GERRORN 0x64 + +#define ARM_SMMU_GERROR_IRQ_CFG0 0x68 +#define ARM_SMMU_GERROR_IRQ_CFG1 0x70 +#define ARM_SMMU_GERROR_IRQ_CFG2 0x74 + +#define ARM_SMMU_STRTAB_BASE 0x80 +#define STRTAB_BASE_RA (1UL << 62) +#define STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6) + +#define ARM_SMMU_STRTAB_BASE_CFG 0x88 +#define STRTAB_BASE_CFG_FMT GENMASK(17, 16) +#define STRTAB_BASE_CFG_FMT_LINEAR 0 +#define STRTAB_BASE_CFG_FMT_2LVL 1 +#define STRTAB_BASE_CFG_SPLIT GENMASK(10, 6) +#define STRTAB_BASE_CFG_LOG2SIZE GENMASK(5, 0) + +#define ARM_SMMU_CMDQ_BASE 0x90 +#define ARM_SMMU_CMDQ_PROD 0x98 +#define ARM_SMMU_CMDQ_CONS 0x9c + +#define ARM_SMMU_EVTQ_BASE 0xa0 +#define ARM_SMMU_EVTQ_PROD 0x100a8 +#define ARM_SMMU_EVTQ_CONS 0x100ac +#define ARM_SMMU_EVTQ_IRQ_CFG0 0xb0 +#define ARM_SMMU_EVTQ_IRQ_CFG1 0xb8 +#define ARM_SMMU_EVTQ_IRQ_CFG2 0xbc + +#define ARM_SMMU_PRIQ_BASE 0xc0 +#define ARM_SMMU_PRIQ_PROD 0x100c8 +#define ARM_SMMU_PRIQ_CONS 0x100cc +#define ARM_SMMU_PRIQ_IRQ_CFG0 0xd0 +#define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8 +#define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc + +#define ARM_SMMU_REG_SZ 0xe00 + +/* Common MSI config fields */ +#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) +#define MSI_CFG2_SH GENMASK(5, 4) +#define MSI_CFG2_MEMATTR GENMASK(3, 0) + +/* Common memory attribute values */ +#define ARM_SMMU_SH_NSH 0 +#define ARM_SMMU_SH_OSH 2 +#define ARM_SMMU_SH_ISH 3 +#define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1 +#define ARM_SMMU_MEMATTR_OIWB 0xf + +#define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1)) +#define Q_WRP(llq, p) ((p) & (1 << (llq)->max_n_shift)) +#define Q_OVERFLOW_FLAG (1U << 31) +#define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) +#define Q_ENT(q, p) ((q)->base + \ + Q_IDX(&((q)->llq), p) * \ + (q)->ent_dwords) + +#define Q_BASE_RWA (1UL << 62) +#define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) +#define Q_BASE_LOG2SIZE GENMASK(4, 0) + +/* Ensure DMA allocations are naturally aligned */ +#ifdef CONFIG_CMA_ALIGNMENT +#define Q_MAX_SZ_SHIFT (PAGE_SHIFT + CONFIG_CMA_ALIGNMENT) +#else +#define Q_MAX_SZ_SHIFT (PAGE_SHIFT + MAX_ORDER - 1) +#endif + +/* + * Stream table. + * + * Linear: Enough to cover 1 << IDR1.SIDSIZE entries + * 2lvl: 128k L1 entries, + * 256 lazy entries per table (each table covers a PCI bus) + */ +#define STRTAB_L1_SZ_SHIFT 20 +#define STRTAB_SPLIT 8 + +#define STRTAB_L1_DESC_DWORDS 1 +#define STRTAB_L1_DESC_SPAN GENMASK_ULL(4, 0) +#define STRTAB_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 6) + +#define STRTAB_STE_DWORDS 8 +#define STRTAB_STE_0_V (1UL << 0) +#define STRTAB_STE_0_CFG GENMASK_ULL(3, 1) +#define STRTAB_STE_0_CFG_ABORT 0 +#define STRTAB_STE_0_CFG_BYPASS 4 +#define STRTAB_STE_0_CFG_S1_TRANS 5 +#define STRTAB_STE_0_CFG_S2_TRANS 6 + +#define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) +#define STRTAB_STE_0_S1FMT_LINEAR 0 +#define STRTAB_STE_0_S1FMT_64K_L2 2 +#define STRTAB_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6) +#define STRTAB_STE_0_S1CDMAX GENMASK_ULL(63, 59) + +#define STRTAB_STE_1_S1DSS GENMASK_ULL(1, 0) +#define STRTAB_STE_1_S1DSS_TERMINATE 0x0 +#define STRTAB_STE_1_S1DSS_BYPASS 0x1 +#define STRTAB_STE_1_S1DSS_SSID0 0x2 + +#define STRTAB_STE_1_S1C_CACHE_NC 0UL +#define STRTAB_STE_1_S1C_CACHE_WBRA 1UL +#define STRTAB_STE_1_S1C_CACHE_WT 2UL +#define STRTAB_STE_1_S1C_CACHE_WB 3UL +#define STRTAB_STE_1_S1CIR GENMASK_ULL(3, 2) +#define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4) +#define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6) + +#define STRTAB_STE_1_S1STALLD (1UL << 27) + +#define STRTAB_STE_1_EATS GENMASK_ULL(29, 28) +#define STRTAB_STE_1_EATS_ABT 0UL +#define STRTAB_STE_1_EATS_TRANS 1UL +#define STRTAB_STE_1_EATS_S1CHK 2UL + +#define STRTAB_STE_1_STRW GENMASK_ULL(31, 30) +#define STRTAB_STE_1_STRW_NSEL1 0UL +#define STRTAB_STE_1_STRW_EL2 2UL + +#define STRTAB_STE_1_SHCFG GENMASK_ULL(45, 44) +#define STRTAB_STE_1_SHCFG_INCOMING 1UL + +#define STRTAB_STE_2_S2VMID GENMASK_ULL(15, 0) +#define STRTAB_STE_2_VTCR GENMASK_ULL(50, 32) +#define STRTAB_STE_2_VTCR_S2T0SZ GENMASK_ULL(5, 0) +#define STRTAB_STE_2_VTCR_S2SL0 GENMASK_ULL(7, 6) +#define STRTAB_STE_2_VTCR_S2IR0 GENMASK_ULL(9, 8) +#define STRTAB_STE_2_VTCR_S2OR0 GENMASK_ULL(11, 10) +#define STRTAB_STE_2_VTCR_S2SH0 GENMASK_ULL(13, 12) +#define STRTAB_STE_2_VTCR_S2TG GENMASK_ULL(15, 14) +#define STRTAB_STE_2_VTCR_S2PS GENMASK_ULL(18, 16) +#define STRTAB_STE_2_S2AA64 (1UL << 51) +#define STRTAB_STE_2_S2ENDI (1UL << 52) +#define STRTAB_STE_2_S2PTW (1UL << 54) +#define STRTAB_STE_2_S2R (1UL << 58) + +#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4) + +/* + * Context descriptors. + * + * Linear: when less than 1024 SSIDs are supported + * 2lvl: at most 1024 L1 entries, + * 1024 lazy entries per table. + */ +#define CTXDESC_SPLIT 10 +#define CTXDESC_L2_ENTRIES (1 << CTXDESC_SPLIT) + +#define CTXDESC_L1_DESC_DWORDS 1 +#define CTXDESC_L1_DESC_V (1UL << 0) +#define CTXDESC_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 12) + +#define CTXDESC_CD_DWORDS 8 +#define CTXDESC_CD_0_TCR_T0SZ GENMASK_ULL(5, 0) +#define CTXDESC_CD_0_TCR_TG0 GENMASK_ULL(7, 6) +#define CTXDESC_CD_0_TCR_IRGN0 GENMASK_ULL(9, 8) +#define CTXDESC_CD_0_TCR_ORGN0 GENMASK_ULL(11, 10) +#define CTXDESC_CD_0_TCR_SH0 GENMASK_ULL(13, 12) +#define CTXDESC_CD_0_TCR_EPD0 (1ULL << 14) +#define CTXDESC_CD_0_TCR_EPD1 (1ULL << 30) + +#define CTXDESC_CD_0_ENDI (1UL << 15) +#define CTXDESC_CD_0_V (1UL << 31) + +#define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32) +#define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38) + +#define CTXDESC_CD_0_AA64 (1UL << 41) +#define CTXDESC_CD_0_S (1UL << 44) +#define CTXDESC_CD_0_R (1UL << 45) +#define CTXDESC_CD_0_A (1UL << 46) +#define CTXDESC_CD_0_ASET (1UL << 47) +#define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48) + +#define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4) + +/* + * When the SMMU only supports linear context descriptor tables, pick a + * reasonable size limit (64kB). + */ +#define CTXDESC_LINEAR_CDMAX ilog2(SZ_64K / (CTXDESC_CD_DWORDS << 3)) + +/* Command queue */ +#define CMDQ_ENT_SZ_SHIFT 4 +#define CMDQ_ENT_DWORDS ((1 << CMDQ_ENT_SZ_SHIFT) >> 3) +#define CMDQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - CMDQ_ENT_SZ_SHIFT) + +#define CMDQ_CONS_ERR GENMASK(30, 24) +#define CMDQ_ERR_CERROR_NONE_IDX 0 +#define CMDQ_ERR_CERROR_ILL_IDX 1 +#define CMDQ_ERR_CERROR_ABT_IDX 2 +#define CMDQ_ERR_CERROR_ATC_INV_IDX 3 + +#define CMDQ_PROD_OWNED_FLAG Q_OVERFLOW_FLAG + +/* + * This is used to size the command queue and therefore must be at least + * BITS_PER_LONG so that the valid_map works correctly (it relies on the + * total number of queue entries being a multiple of BITS_PER_LONG). + */ +#define CMDQ_BATCH_ENTRIES BITS_PER_LONG + +#define CMDQ_0_OP GENMASK_ULL(7, 0) +#define CMDQ_0_SSV (1UL << 11) + +#define CMDQ_PREFETCH_0_SID GENMASK_ULL(63, 32) +#define CMDQ_PREFETCH_1_SIZE GENMASK_ULL(4, 0) +#define CMDQ_PREFETCH_1_ADDR_MASK GENMASK_ULL(63, 12) + +#define CMDQ_CFGI_0_SSID GENMASK_ULL(31, 12) +#define CMDQ_CFGI_0_SID GENMASK_ULL(63, 32) +#define CMDQ_CFGI_1_LEAF (1UL << 0) +#define CMDQ_CFGI_1_RANGE GENMASK_ULL(4, 0) + +#define CMDQ_TLBI_0_NUM GENMASK_ULL(16, 12) +#define CMDQ_TLBI_RANGE_NUM_MAX 31 +#define CMDQ_TLBI_0_SCALE GENMASK_ULL(24, 20) +#define CMDQ_TLBI_0_VMID GENMASK_ULL(47, 32) +#define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48) +#define CMDQ_TLBI_1_LEAF (1UL << 0) +#define CMDQ_TLBI_1_TTL GENMASK_ULL(9, 8) +#define CMDQ_TLBI_1_TG GENMASK_ULL(11, 10) +#define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) +#define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12) + +#define CMDQ_ATC_0_SSID GENMASK_ULL(31, 12) +#define CMDQ_ATC_0_SID GENMASK_ULL(63, 32) +#define CMDQ_ATC_0_GLOBAL (1UL << 9) +#define CMDQ_ATC_1_SIZE GENMASK_ULL(5, 0) +#define CMDQ_ATC_1_ADDR_MASK GENMASK_ULL(63, 12) + +#define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) +#define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) +#define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0) +#define CMDQ_PRI_1_RESP GENMASK_ULL(13, 12) + +#define CMDQ_SYNC_0_CS GENMASK_ULL(13, 12) +#define CMDQ_SYNC_0_CS_NONE 0 +#define CMDQ_SYNC_0_CS_IRQ 1 +#define CMDQ_SYNC_0_CS_SEV 2 +#define CMDQ_SYNC_0_MSH GENMASK_ULL(23, 22) +#define CMDQ_SYNC_0_MSIATTR GENMASK_ULL(27, 24) +#define CMDQ_SYNC_0_MSIDATA GENMASK_ULL(63, 32) +#define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2) + +/* Event queue */ +#define EVTQ_ENT_SZ_SHIFT 5 +#define EVTQ_ENT_DWORDS ((1 << EVTQ_ENT_SZ_SHIFT) >> 3) +#define EVTQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - EVTQ_ENT_SZ_SHIFT) + +#define EVTQ_0_ID GENMASK_ULL(7, 0) + +/* PRI queue */ +#define PRIQ_ENT_SZ_SHIFT 4 +#define PRIQ_ENT_DWORDS ((1 << PRIQ_ENT_SZ_SHIFT) >> 3) +#define PRIQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - PRIQ_ENT_SZ_SHIFT) + +#define PRIQ_0_SID GENMASK_ULL(31, 0) +#define PRIQ_0_SSID GENMASK_ULL(51, 32) +#define PRIQ_0_PERM_PRIV (1UL << 58) +#define PRIQ_0_PERM_EXEC (1UL << 59) +#define PRIQ_0_PERM_READ (1UL << 60) +#define PRIQ_0_PERM_WRITE (1UL << 61) +#define PRIQ_0_PRG_LAST (1UL << 62) +#define PRIQ_0_SSID_V (1UL << 63) + +#define PRIQ_1_PRG_IDX GENMASK_ULL(8, 0) +#define PRIQ_1_ADDR_MASK GENMASK_ULL(63, 12) + +/* High-level queue structures */ +#define ARM_SMMU_POLL_TIMEOUT_US 1000000 /* 1s! */ +#define ARM_SMMU_POLL_SPIN_COUNT 10 + +#define MSI_IOVA_BASE 0x8000000 +#define MSI_IOVA_LENGTH 0x100000 + +enum pri_resp { + PRI_RESP_DENY = 0, + PRI_RESP_FAIL = 1, + PRI_RESP_SUCC = 2, +}; + +struct arm_smmu_cmdq_ent { + /* Common fields */ + u8 opcode; + bool substream_valid; + + /* Command-specific fields */ + union { + #define CMDQ_OP_PREFETCH_CFG 0x1 + struct { + u32 sid; + u8 size; + u64 addr; + } prefetch; + + #define CMDQ_OP_CFGI_STE 0x3 + #define CMDQ_OP_CFGI_ALL 0x4 + #define CMDQ_OP_CFGI_CD 0x5 + #define CMDQ_OP_CFGI_CD_ALL 0x6 + struct { + u32 sid; + u32 ssid; + union { + bool leaf; + u8 span; + }; + } cfgi; + + #define CMDQ_OP_TLBI_NH_ASID 0x11 + #define CMDQ_OP_TLBI_NH_VA 0x12 + #define CMDQ_OP_TLBI_EL2_ALL 0x20 + #define CMDQ_OP_TLBI_S12_VMALL 0x28 + #define CMDQ_OP_TLBI_S2_IPA 0x2a + #define CMDQ_OP_TLBI_NSNH_ALL 0x30 + struct { + u8 num; + u8 scale; + u16 asid; + u16 vmid; + bool leaf; + u8 ttl; + u8 tg; + u64 addr; + } tlbi; + + #define CMDQ_OP_ATC_INV 0x40 + #define ATC_INV_SIZE_ALL 52 + struct { + u32 sid; + u32 ssid; + u64 addr; + u8 size; + bool global; + } atc; + + #define CMDQ_OP_PRI_RESP 0x41 + struct { + u32 sid; + u32 ssid; + u16 grpid; + enum pri_resp resp; + } pri; + + #define CMDQ_OP_CMD_SYNC 0x46 + struct { + u64 msiaddr; + } sync; + }; +}; + +struct arm_smmu_ll_queue { + union { + u64 val; + struct { + u32 prod; + u32 cons; + }; + struct { + atomic_t prod; + atomic_t cons; + } atomic; + u8 __pad[SMP_CACHE_BYTES]; + } ____cacheline_aligned_in_smp; + u32 max_n_shift; +}; + +struct arm_smmu_queue { + struct arm_smmu_ll_queue llq; + int irq; /* Wired interrupt */ + + __le64 *base; + dma_addr_t base_dma; + u64 q_base; + + size_t ent_dwords; + + u32 __iomem *prod_reg; + u32 __iomem *cons_reg; +}; + +struct arm_smmu_queue_poll { + ktime_t timeout; + unsigned int delay; + unsigned int spin_cnt; + bool wfe; +}; + +struct arm_smmu_cmdq { + struct arm_smmu_queue q; + atomic_long_t *valid_map; + atomic_t owner_prod; + atomic_t lock; +}; + +struct arm_smmu_cmdq_batch { + u64 cmds[CMDQ_BATCH_ENTRIES * CMDQ_ENT_DWORDS]; + int num; +}; + +struct arm_smmu_evtq { + struct arm_smmu_queue q; + u32 max_stalls; +}; + +struct arm_smmu_priq { + struct arm_smmu_queue q; +}; + +/* High-level stream table and context descriptor structures */ +struct arm_smmu_strtab_l1_desc { + u8 span; + + __le64 *l2ptr; + dma_addr_t l2ptr_dma; +}; + +struct arm_smmu_ctx_desc { + u16 asid; + u64 ttbr; + u64 tcr; + u64 mair; +}; + +struct arm_smmu_l1_ctx_desc { + __le64 *l2ptr; + dma_addr_t l2ptr_dma; +}; + +struct arm_smmu_ctx_desc_cfg { + __le64 *cdtab; + dma_addr_t cdtab_dma; + struct arm_smmu_l1_ctx_desc *l1_desc; + unsigned int num_l1_ents; +}; + +struct arm_smmu_s1_cfg { + struct arm_smmu_ctx_desc_cfg cdcfg; + struct arm_smmu_ctx_desc cd; + u8 s1fmt; + u8 s1cdmax; +}; + +struct arm_smmu_s2_cfg { + u16 vmid; + u64 vttbr; + u64 vtcr; +}; + +struct arm_smmu_strtab_cfg { + __le64 *strtab; + dma_addr_t strtab_dma; + struct arm_smmu_strtab_l1_desc *l1_desc; + unsigned int num_l1_ents; + + u64 strtab_base; + u32 strtab_base_cfg; +}; + +/* An SMMUv3 instance */ +struct arm_smmu_device { + struct device *dev; + void __iomem *base; + void __iomem *page1; + +#define ARM_SMMU_FEAT_2_LVL_STRTAB (1 << 0) +#define ARM_SMMU_FEAT_2_LVL_CDTAB (1 << 1) +#define ARM_SMMU_FEAT_TT_LE (1 << 2) +#define ARM_SMMU_FEAT_TT_BE (1 << 3) +#define ARM_SMMU_FEAT_PRI (1 << 4) +#define ARM_SMMU_FEAT_ATS (1 << 5) +#define ARM_SMMU_FEAT_SEV (1 << 6) +#define ARM_SMMU_FEAT_MSI (1 << 7) +#define ARM_SMMU_FEAT_COHERENCY (1 << 8) +#define ARM_SMMU_FEAT_TRANS_S1 (1 << 9) +#define ARM_SMMU_FEAT_TRANS_S2 (1 << 10) +#define ARM_SMMU_FEAT_STALLS (1 << 11) +#define ARM_SMMU_FEAT_HYP (1 << 12) +#define ARM_SMMU_FEAT_STALL_FORCE (1 << 13) +#define ARM_SMMU_FEAT_VAX (1 << 14) +#define ARM_SMMU_FEAT_RANGE_INV (1 << 15) + u32 features; + +#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) +#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) + u32 options; + + struct arm_smmu_cmdq cmdq; + struct arm_smmu_evtq evtq; + struct arm_smmu_priq priq; + + int gerr_irq; + int combined_irq; + + unsigned long ias; /* IPA */ + unsigned long oas; /* PA */ + unsigned long pgsize_bitmap; + +#define ARM_SMMU_MAX_ASIDS (1 << 16) + unsigned int asid_bits; + +#define ARM_SMMU_MAX_VMIDS (1 << 16) + unsigned int vmid_bits; + DECLARE_BITMAP(vmid_map, ARM_SMMU_MAX_VMIDS); + + unsigned int ssid_bits; + unsigned int sid_bits; + + struct arm_smmu_strtab_cfg strtab_cfg; + + /* IOMMU core code handle */ + struct iommu_device iommu; +}; + +/* SMMU private data for each master */ +struct arm_smmu_master { + struct arm_smmu_device *smmu; + struct device *dev; + struct arm_smmu_domain *domain; + struct list_head domain_head; + u32 *sids; + unsigned int num_sids; + bool ats_enabled; + unsigned int ssid_bits; +}; + +/* SMMU private data for an IOMMU domain */ +enum arm_smmu_domain_stage { + ARM_SMMU_DOMAIN_S1 = 0, + ARM_SMMU_DOMAIN_S2, + ARM_SMMU_DOMAIN_NESTED, + ARM_SMMU_DOMAIN_BYPASS, +}; + +struct arm_smmu_domain { + struct arm_smmu_device *smmu; + struct mutex init_mutex; /* Protects smmu pointer */ + + struct io_pgtable_ops *pgtbl_ops; + bool non_strict; + atomic_t nr_ats_masters; + + enum arm_smmu_domain_stage stage; + union { + struct arm_smmu_s1_cfg s1_cfg; + struct arm_smmu_s2_cfg s2_cfg; + }; + + struct iommu_domain domain; + + struct list_head devices; + spinlock_t devices_lock; +}; + +#endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 937aa1af428d..827334ed312b 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -19,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -33,397 +31,13 @@ #include -/* MMIO registers */ -#define ARM_SMMU_IDR0 0x0 -#define IDR0_ST_LVL GENMASK(28, 27) -#define IDR0_ST_LVL_2LVL 1 -#define IDR0_STALL_MODEL GENMASK(25, 24) -#define IDR0_STALL_MODEL_STALL 0 -#define IDR0_STALL_MODEL_FORCE 2 -#define IDR0_TTENDIAN GENMASK(22, 21) -#define IDR0_TTENDIAN_MIXED 0 -#define IDR0_TTENDIAN_LE 2 -#define IDR0_TTENDIAN_BE 3 -#define IDR0_CD2L (1 << 19) -#define IDR0_VMID16 (1 << 18) -#define IDR0_PRI (1 << 16) -#define IDR0_SEV (1 << 14) -#define IDR0_MSI (1 << 13) -#define IDR0_ASID16 (1 << 12) -#define IDR0_ATS (1 << 10) -#define IDR0_HYP (1 << 9) -#define IDR0_COHACC (1 << 4) -#define IDR0_TTF GENMASK(3, 2) -#define IDR0_TTF_AARCH64 2 -#define IDR0_TTF_AARCH32_64 3 -#define IDR0_S1P (1 << 1) -#define IDR0_S2P (1 << 0) - -#define ARM_SMMU_IDR1 0x4 -#define IDR1_TABLES_PRESET (1 << 30) -#define IDR1_QUEUES_PRESET (1 << 29) -#define IDR1_REL (1 << 28) -#define IDR1_CMDQS GENMASK(25, 21) -#define IDR1_EVTQS GENMASK(20, 16) -#define IDR1_PRIQS GENMASK(15, 11) -#define IDR1_SSIDSIZE GENMASK(10, 6) -#define IDR1_SIDSIZE GENMASK(5, 0) - -#define ARM_SMMU_IDR3 0xc -#define IDR3_RIL (1 << 10) - -#define ARM_SMMU_IDR5 0x14 -#define IDR5_STALL_MAX GENMASK(31, 16) -#define IDR5_GRAN64K (1 << 6) -#define IDR5_GRAN16K (1 << 5) -#define IDR5_GRAN4K (1 << 4) -#define IDR5_OAS GENMASK(2, 0) -#define IDR5_OAS_32_BIT 0 -#define IDR5_OAS_36_BIT 1 -#define IDR5_OAS_40_BIT 2 -#define IDR5_OAS_42_BIT 3 -#define IDR5_OAS_44_BIT 4 -#define IDR5_OAS_48_BIT 5 -#define IDR5_OAS_52_BIT 6 -#define IDR5_VAX GENMASK(11, 10) -#define IDR5_VAX_52_BIT 1 - -#define ARM_SMMU_CR0 0x20 -#define CR0_ATSCHK (1 << 4) -#define CR0_CMDQEN (1 << 3) -#define CR0_EVTQEN (1 << 2) -#define CR0_PRIQEN (1 << 1) -#define CR0_SMMUEN (1 << 0) - -#define ARM_SMMU_CR0ACK 0x24 - -#define ARM_SMMU_CR1 0x28 -#define CR1_TABLE_SH GENMASK(11, 10) -#define CR1_TABLE_OC GENMASK(9, 8) -#define CR1_TABLE_IC GENMASK(7, 6) -#define CR1_QUEUE_SH GENMASK(5, 4) -#define CR1_QUEUE_OC GENMASK(3, 2) -#define CR1_QUEUE_IC GENMASK(1, 0) -/* CR1 cacheability fields don't quite follow the usual TCR-style encoding */ -#define CR1_CACHE_NC 0 -#define CR1_CACHE_WB 1 -#define CR1_CACHE_WT 2 - -#define ARM_SMMU_CR2 0x2c -#define CR2_PTM (1 << 2) -#define CR2_RECINVSID (1 << 1) -#define CR2_E2H (1 << 0) - -#define ARM_SMMU_GBPA 0x44 -#define GBPA_UPDATE (1 << 31) -#define GBPA_ABORT (1 << 20) - -#define ARM_SMMU_IRQ_CTRL 0x50 -#define IRQ_CTRL_EVTQ_IRQEN (1 << 2) -#define IRQ_CTRL_PRIQ_IRQEN (1 << 1) -#define IRQ_CTRL_GERROR_IRQEN (1 << 0) - -#define ARM_SMMU_IRQ_CTRLACK 0x54 - -#define ARM_SMMU_GERROR 0x60 -#define GERROR_SFM_ERR (1 << 8) -#define GERROR_MSI_GERROR_ABT_ERR (1 << 7) -#define GERROR_MSI_PRIQ_ABT_ERR (1 << 6) -#define GERROR_MSI_EVTQ_ABT_ERR (1 << 5) -#define GERROR_MSI_CMDQ_ABT_ERR (1 << 4) -#define GERROR_PRIQ_ABT_ERR (1 << 3) -#define GERROR_EVTQ_ABT_ERR (1 << 2) -#define GERROR_CMDQ_ERR (1 << 0) -#define GERROR_ERR_MASK 0xfd - -#define ARM_SMMU_GERRORN 0x64 - -#define ARM_SMMU_GERROR_IRQ_CFG0 0x68 -#define ARM_SMMU_GERROR_IRQ_CFG1 0x70 -#define ARM_SMMU_GERROR_IRQ_CFG2 0x74 - -#define ARM_SMMU_STRTAB_BASE 0x80 -#define STRTAB_BASE_RA (1UL << 62) -#define STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6) - -#define ARM_SMMU_STRTAB_BASE_CFG 0x88 -#define STRTAB_BASE_CFG_FMT GENMASK(17, 16) -#define STRTAB_BASE_CFG_FMT_LINEAR 0 -#define STRTAB_BASE_CFG_FMT_2LVL 1 -#define STRTAB_BASE_CFG_SPLIT GENMASK(10, 6) -#define STRTAB_BASE_CFG_LOG2SIZE GENMASK(5, 0) - -#define ARM_SMMU_CMDQ_BASE 0x90 -#define ARM_SMMU_CMDQ_PROD 0x98 -#define ARM_SMMU_CMDQ_CONS 0x9c - -#define ARM_SMMU_EVTQ_BASE 0xa0 -#define ARM_SMMU_EVTQ_PROD 0x100a8 -#define ARM_SMMU_EVTQ_CONS 0x100ac -#define ARM_SMMU_EVTQ_IRQ_CFG0 0xb0 -#define ARM_SMMU_EVTQ_IRQ_CFG1 0xb8 -#define ARM_SMMU_EVTQ_IRQ_CFG2 0xbc - -#define ARM_SMMU_PRIQ_BASE 0xc0 -#define ARM_SMMU_PRIQ_PROD 0x100c8 -#define ARM_SMMU_PRIQ_CONS 0x100cc -#define ARM_SMMU_PRIQ_IRQ_CFG0 0xd0 -#define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8 -#define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc - -#define ARM_SMMU_REG_SZ 0xe00 - -/* Common MSI config fields */ -#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) -#define MSI_CFG2_SH GENMASK(5, 4) -#define MSI_CFG2_MEMATTR GENMASK(3, 0) - -/* Common memory attribute values */ -#define ARM_SMMU_SH_NSH 0 -#define ARM_SMMU_SH_OSH 2 -#define ARM_SMMU_SH_ISH 3 -#define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1 -#define ARM_SMMU_MEMATTR_OIWB 0xf - -#define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1)) -#define Q_WRP(llq, p) ((p) & (1 << (llq)->max_n_shift)) -#define Q_OVERFLOW_FLAG (1U << 31) -#define Q_OVF(p) ((p) & Q_OVERFLOW_FLAG) -#define Q_ENT(q, p) ((q)->base + \ - Q_IDX(&((q)->llq), p) * \ - (q)->ent_dwords) - -#define Q_BASE_RWA (1UL << 62) -#define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) -#define Q_BASE_LOG2SIZE GENMASK(4, 0) - -/* Ensure DMA allocations are naturally aligned */ -#ifdef CONFIG_CMA_ALIGNMENT -#define Q_MAX_SZ_SHIFT (PAGE_SHIFT + CONFIG_CMA_ALIGNMENT) -#else -#define Q_MAX_SZ_SHIFT (PAGE_SHIFT + MAX_ORDER - 1) -#endif - -/* - * Stream table. - * - * Linear: Enough to cover 1 << IDR1.SIDSIZE entries - * 2lvl: 128k L1 entries, - * 256 lazy entries per table (each table covers a PCI bus) - */ -#define STRTAB_L1_SZ_SHIFT 20 -#define STRTAB_SPLIT 8 - -#define STRTAB_L1_DESC_DWORDS 1 -#define STRTAB_L1_DESC_SPAN GENMASK_ULL(4, 0) -#define STRTAB_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 6) - -#define STRTAB_STE_DWORDS 8 -#define STRTAB_STE_0_V (1UL << 0) -#define STRTAB_STE_0_CFG GENMASK_ULL(3, 1) -#define STRTAB_STE_0_CFG_ABORT 0 -#define STRTAB_STE_0_CFG_BYPASS 4 -#define STRTAB_STE_0_CFG_S1_TRANS 5 -#define STRTAB_STE_0_CFG_S2_TRANS 6 - -#define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) -#define STRTAB_STE_0_S1FMT_LINEAR 0 -#define STRTAB_STE_0_S1FMT_64K_L2 2 -#define STRTAB_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6) -#define STRTAB_STE_0_S1CDMAX GENMASK_ULL(63, 59) - -#define STRTAB_STE_1_S1DSS GENMASK_ULL(1, 0) -#define STRTAB_STE_1_S1DSS_TERMINATE 0x0 -#define STRTAB_STE_1_S1DSS_BYPASS 0x1 -#define STRTAB_STE_1_S1DSS_SSID0 0x2 - -#define STRTAB_STE_1_S1C_CACHE_NC 0UL -#define STRTAB_STE_1_S1C_CACHE_WBRA 1UL -#define STRTAB_STE_1_S1C_CACHE_WT 2UL -#define STRTAB_STE_1_S1C_CACHE_WB 3UL -#define STRTAB_STE_1_S1CIR GENMASK_ULL(3, 2) -#define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4) -#define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6) - -#define STRTAB_STE_1_S1STALLD (1UL << 27) - -#define STRTAB_STE_1_EATS GENMASK_ULL(29, 28) -#define STRTAB_STE_1_EATS_ABT 0UL -#define STRTAB_STE_1_EATS_TRANS 1UL -#define STRTAB_STE_1_EATS_S1CHK 2UL - -#define STRTAB_STE_1_STRW GENMASK_ULL(31, 30) -#define STRTAB_STE_1_STRW_NSEL1 0UL -#define STRTAB_STE_1_STRW_EL2 2UL - -#define STRTAB_STE_1_SHCFG GENMASK_ULL(45, 44) -#define STRTAB_STE_1_SHCFG_INCOMING 1UL - -#define STRTAB_STE_2_S2VMID GENMASK_ULL(15, 0) -#define STRTAB_STE_2_VTCR GENMASK_ULL(50, 32) -#define STRTAB_STE_2_VTCR_S2T0SZ GENMASK_ULL(5, 0) -#define STRTAB_STE_2_VTCR_S2SL0 GENMASK_ULL(7, 6) -#define STRTAB_STE_2_VTCR_S2IR0 GENMASK_ULL(9, 8) -#define STRTAB_STE_2_VTCR_S2OR0 GENMASK_ULL(11, 10) -#define STRTAB_STE_2_VTCR_S2SH0 GENMASK_ULL(13, 12) -#define STRTAB_STE_2_VTCR_S2TG GENMASK_ULL(15, 14) -#define STRTAB_STE_2_VTCR_S2PS GENMASK_ULL(18, 16) -#define STRTAB_STE_2_S2AA64 (1UL << 51) -#define STRTAB_STE_2_S2ENDI (1UL << 52) -#define STRTAB_STE_2_S2PTW (1UL << 54) -#define STRTAB_STE_2_S2R (1UL << 58) - -#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4) - -/* - * Context descriptors. - * - * Linear: when less than 1024 SSIDs are supported - * 2lvl: at most 1024 L1 entries, - * 1024 lazy entries per table. - */ -#define CTXDESC_SPLIT 10 -#define CTXDESC_L2_ENTRIES (1 << CTXDESC_SPLIT) - -#define CTXDESC_L1_DESC_DWORDS 1 -#define CTXDESC_L1_DESC_V (1UL << 0) -#define CTXDESC_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 12) - -#define CTXDESC_CD_DWORDS 8 -#define CTXDESC_CD_0_TCR_T0SZ GENMASK_ULL(5, 0) -#define CTXDESC_CD_0_TCR_TG0 GENMASK_ULL(7, 6) -#define CTXDESC_CD_0_TCR_IRGN0 GENMASK_ULL(9, 8) -#define CTXDESC_CD_0_TCR_ORGN0 GENMASK_ULL(11, 10) -#define CTXDESC_CD_0_TCR_SH0 GENMASK_ULL(13, 12) -#define CTXDESC_CD_0_TCR_EPD0 (1ULL << 14) -#define CTXDESC_CD_0_TCR_EPD1 (1ULL << 30) - -#define CTXDESC_CD_0_ENDI (1UL << 15) -#define CTXDESC_CD_0_V (1UL << 31) - -#define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32) -#define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38) - -#define CTXDESC_CD_0_AA64 (1UL << 41) -#define CTXDESC_CD_0_S (1UL << 44) -#define CTXDESC_CD_0_R (1UL << 45) -#define CTXDESC_CD_0_A (1UL << 46) -#define CTXDESC_CD_0_ASET (1UL << 47) -#define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48) - -#define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4) - -/* - * When the SMMU only supports linear context descriptor tables, pick a - * reasonable size limit (64kB). - */ -#define CTXDESC_LINEAR_CDMAX ilog2(SZ_64K / (CTXDESC_CD_DWORDS << 3)) - -/* Command queue */ -#define CMDQ_ENT_SZ_SHIFT 4 -#define CMDQ_ENT_DWORDS ((1 << CMDQ_ENT_SZ_SHIFT) >> 3) -#define CMDQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - CMDQ_ENT_SZ_SHIFT) - -#define CMDQ_CONS_ERR GENMASK(30, 24) -#define CMDQ_ERR_CERROR_NONE_IDX 0 -#define CMDQ_ERR_CERROR_ILL_IDX 1 -#define CMDQ_ERR_CERROR_ABT_IDX 2 -#define CMDQ_ERR_CERROR_ATC_INV_IDX 3 - -#define CMDQ_PROD_OWNED_FLAG Q_OVERFLOW_FLAG - -/* - * This is used to size the command queue and therefore must be at least - * BITS_PER_LONG so that the valid_map works correctly (it relies on the - * total number of queue entries being a multiple of BITS_PER_LONG). - */ -#define CMDQ_BATCH_ENTRIES BITS_PER_LONG - -#define CMDQ_0_OP GENMASK_ULL(7, 0) -#define CMDQ_0_SSV (1UL << 11) - -#define CMDQ_PREFETCH_0_SID GENMASK_ULL(63, 32) -#define CMDQ_PREFETCH_1_SIZE GENMASK_ULL(4, 0) -#define CMDQ_PREFETCH_1_ADDR_MASK GENMASK_ULL(63, 12) - -#define CMDQ_CFGI_0_SSID GENMASK_ULL(31, 12) -#define CMDQ_CFGI_0_SID GENMASK_ULL(63, 32) -#define CMDQ_CFGI_1_LEAF (1UL << 0) -#define CMDQ_CFGI_1_RANGE GENMASK_ULL(4, 0) - -#define CMDQ_TLBI_0_NUM GENMASK_ULL(16, 12) -#define CMDQ_TLBI_RANGE_NUM_MAX 31 -#define CMDQ_TLBI_0_SCALE GENMASK_ULL(24, 20) -#define CMDQ_TLBI_0_VMID GENMASK_ULL(47, 32) -#define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48) -#define CMDQ_TLBI_1_LEAF (1UL << 0) -#define CMDQ_TLBI_1_TTL GENMASK_ULL(9, 8) -#define CMDQ_TLBI_1_TG GENMASK_ULL(11, 10) -#define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) -#define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12) - -#define CMDQ_ATC_0_SSID GENMASK_ULL(31, 12) -#define CMDQ_ATC_0_SID GENMASK_ULL(63, 32) -#define CMDQ_ATC_0_GLOBAL (1UL << 9) -#define CMDQ_ATC_1_SIZE GENMASK_ULL(5, 0) -#define CMDQ_ATC_1_ADDR_MASK GENMASK_ULL(63, 12) - -#define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) -#define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) -#define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0) -#define CMDQ_PRI_1_RESP GENMASK_ULL(13, 12) - -#define CMDQ_SYNC_0_CS GENMASK_ULL(13, 12) -#define CMDQ_SYNC_0_CS_NONE 0 -#define CMDQ_SYNC_0_CS_IRQ 1 -#define CMDQ_SYNC_0_CS_SEV 2 -#define CMDQ_SYNC_0_MSH GENMASK_ULL(23, 22) -#define CMDQ_SYNC_0_MSIATTR GENMASK_ULL(27, 24) -#define CMDQ_SYNC_0_MSIDATA GENMASK_ULL(63, 32) -#define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2) - -/* Event queue */ -#define EVTQ_ENT_SZ_SHIFT 5 -#define EVTQ_ENT_DWORDS ((1 << EVTQ_ENT_SZ_SHIFT) >> 3) -#define EVTQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - EVTQ_ENT_SZ_SHIFT) - -#define EVTQ_0_ID GENMASK_ULL(7, 0) - -/* PRI queue */ -#define PRIQ_ENT_SZ_SHIFT 4 -#define PRIQ_ENT_DWORDS ((1 << PRIQ_ENT_SZ_SHIFT) >> 3) -#define PRIQ_MAX_SZ_SHIFT (Q_MAX_SZ_SHIFT - PRIQ_ENT_SZ_SHIFT) - -#define PRIQ_0_SID GENMASK_ULL(31, 0) -#define PRIQ_0_SSID GENMASK_ULL(51, 32) -#define PRIQ_0_PERM_PRIV (1UL << 58) -#define PRIQ_0_PERM_EXEC (1UL << 59) -#define PRIQ_0_PERM_READ (1UL << 60) -#define PRIQ_0_PERM_WRITE (1UL << 61) -#define PRIQ_0_PRG_LAST (1UL << 62) -#define PRIQ_0_SSID_V (1UL << 63) - -#define PRIQ_1_PRG_IDX GENMASK_ULL(8, 0) -#define PRIQ_1_ADDR_MASK GENMASK_ULL(63, 12) - -/* High-level queue structures */ -#define ARM_SMMU_POLL_TIMEOUT_US 1000000 /* 1s! */ -#define ARM_SMMU_POLL_SPIN_COUNT 10 - -#define MSI_IOVA_BASE 0x8000000 -#define MSI_IOVA_LENGTH 0x100000 +#include "arm-smmu-v3.h" static bool disable_bypass = 1; module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO); MODULE_PARM_DESC(disable_bypass, "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); -enum pri_resp { - PRI_RESP_DENY = 0, - PRI_RESP_FAIL = 1, - PRI_RESP_SUCC = 2, -}; - enum arm_smmu_msi_index { EVTQ_MSI_INDEX, GERROR_MSI_INDEX, @@ -449,278 +63,6 @@ static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = { }, }; -struct arm_smmu_cmdq_ent { - /* Common fields */ - u8 opcode; - bool substream_valid; - - /* Command-specific fields */ - union { - #define CMDQ_OP_PREFETCH_CFG 0x1 - struct { - u32 sid; - u8 size; - u64 addr; - } prefetch; - - #define CMDQ_OP_CFGI_STE 0x3 - #define CMDQ_OP_CFGI_ALL 0x4 - #define CMDQ_OP_CFGI_CD 0x5 - #define CMDQ_OP_CFGI_CD_ALL 0x6 - struct { - u32 sid; - u32 ssid; - union { - bool leaf; - u8 span; - }; - } cfgi; - - #define CMDQ_OP_TLBI_NH_ASID 0x11 - #define CMDQ_OP_TLBI_NH_VA 0x12 - #define CMDQ_OP_TLBI_EL2_ALL 0x20 - #define CMDQ_OP_TLBI_S12_VMALL 0x28 - #define CMDQ_OP_TLBI_S2_IPA 0x2a - #define CMDQ_OP_TLBI_NSNH_ALL 0x30 - struct { - u8 num; - u8 scale; - u16 asid; - u16 vmid; - bool leaf; - u8 ttl; - u8 tg; - u64 addr; - } tlbi; - - #define CMDQ_OP_ATC_INV 0x40 - #define ATC_INV_SIZE_ALL 52 - struct { - u32 sid; - u32 ssid; - u64 addr; - u8 size; - bool global; - } atc; - - #define CMDQ_OP_PRI_RESP 0x41 - struct { - u32 sid; - u32 ssid; - u16 grpid; - enum pri_resp resp; - } pri; - - #define CMDQ_OP_CMD_SYNC 0x46 - struct { - u64 msiaddr; - } sync; - }; -}; - -struct arm_smmu_ll_queue { - union { - u64 val; - struct { - u32 prod; - u32 cons; - }; - struct { - atomic_t prod; - atomic_t cons; - } atomic; - u8 __pad[SMP_CACHE_BYTES]; - } ____cacheline_aligned_in_smp; - u32 max_n_shift; -}; - -struct arm_smmu_queue { - struct arm_smmu_ll_queue llq; - int irq; /* Wired interrupt */ - - __le64 *base; - dma_addr_t base_dma; - u64 q_base; - - size_t ent_dwords; - - u32 __iomem *prod_reg; - u32 __iomem *cons_reg; -}; - -struct arm_smmu_queue_poll { - ktime_t timeout; - unsigned int delay; - unsigned int spin_cnt; - bool wfe; -}; - -struct arm_smmu_cmdq { - struct arm_smmu_queue q; - atomic_long_t *valid_map; - atomic_t owner_prod; - atomic_t lock; -}; - -struct arm_smmu_cmdq_batch { - u64 cmds[CMDQ_BATCH_ENTRIES * CMDQ_ENT_DWORDS]; - int num; -}; - -struct arm_smmu_evtq { - struct arm_smmu_queue q; - u32 max_stalls; -}; - -struct arm_smmu_priq { - struct arm_smmu_queue q; -}; - -/* High-level stream table and context descriptor structures */ -struct arm_smmu_strtab_l1_desc { - u8 span; - - __le64 *l2ptr; - dma_addr_t l2ptr_dma; -}; - -struct arm_smmu_ctx_desc { - u16 asid; - u64 ttbr; - u64 tcr; - u64 mair; -}; - -struct arm_smmu_l1_ctx_desc { - __le64 *l2ptr; - dma_addr_t l2ptr_dma; -}; - -struct arm_smmu_ctx_desc_cfg { - __le64 *cdtab; - dma_addr_t cdtab_dma; - struct arm_smmu_l1_ctx_desc *l1_desc; - unsigned int num_l1_ents; -}; - -struct arm_smmu_s1_cfg { - struct arm_smmu_ctx_desc_cfg cdcfg; - struct arm_smmu_ctx_desc cd; - u8 s1fmt; - u8 s1cdmax; -}; - -struct arm_smmu_s2_cfg { - u16 vmid; - u64 vttbr; - u64 vtcr; -}; - -struct arm_smmu_strtab_cfg { - __le64 *strtab; - dma_addr_t strtab_dma; - struct arm_smmu_strtab_l1_desc *l1_desc; - unsigned int num_l1_ents; - - u64 strtab_base; - u32 strtab_base_cfg; -}; - -/* An SMMUv3 instance */ -struct arm_smmu_device { - struct device *dev; - void __iomem *base; - void __iomem *page1; - -#define ARM_SMMU_FEAT_2_LVL_STRTAB (1 << 0) -#define ARM_SMMU_FEAT_2_LVL_CDTAB (1 << 1) -#define ARM_SMMU_FEAT_TT_LE (1 << 2) -#define ARM_SMMU_FEAT_TT_BE (1 << 3) -#define ARM_SMMU_FEAT_PRI (1 << 4) -#define ARM_SMMU_FEAT_ATS (1 << 5) -#define ARM_SMMU_FEAT_SEV (1 << 6) -#define ARM_SMMU_FEAT_MSI (1 << 7) -#define ARM_SMMU_FEAT_COHERENCY (1 << 8) -#define ARM_SMMU_FEAT_TRANS_S1 (1 << 9) -#define ARM_SMMU_FEAT_TRANS_S2 (1 << 10) -#define ARM_SMMU_FEAT_STALLS (1 << 11) -#define ARM_SMMU_FEAT_HYP (1 << 12) -#define ARM_SMMU_FEAT_STALL_FORCE (1 << 13) -#define ARM_SMMU_FEAT_VAX (1 << 14) -#define ARM_SMMU_FEAT_RANGE_INV (1 << 15) - u32 features; - -#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) -#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) - u32 options; - - struct arm_smmu_cmdq cmdq; - struct arm_smmu_evtq evtq; - struct arm_smmu_priq priq; - - int gerr_irq; - int combined_irq; - - unsigned long ias; /* IPA */ - unsigned long oas; /* PA */ - unsigned long pgsize_bitmap; - -#define ARM_SMMU_MAX_ASIDS (1 << 16) - unsigned int asid_bits; - -#define ARM_SMMU_MAX_VMIDS (1 << 16) - unsigned int vmid_bits; - DECLARE_BITMAP(vmid_map, ARM_SMMU_MAX_VMIDS); - - unsigned int ssid_bits; - unsigned int sid_bits; - - struct arm_smmu_strtab_cfg strtab_cfg; - - /* IOMMU core code handle */ - struct iommu_device iommu; -}; - -/* SMMU private data for each master */ -struct arm_smmu_master { - struct arm_smmu_device *smmu; - struct device *dev; - struct arm_smmu_domain *domain; - struct list_head domain_head; - u32 *sids; - unsigned int num_sids; - bool ats_enabled; - unsigned int ssid_bits; -}; - -/* SMMU private data for an IOMMU domain */ -enum arm_smmu_domain_stage { - ARM_SMMU_DOMAIN_S1 = 0, - ARM_SMMU_DOMAIN_S2, - ARM_SMMU_DOMAIN_NESTED, - ARM_SMMU_DOMAIN_BYPASS, -}; - -struct arm_smmu_domain { - struct arm_smmu_device *smmu; - struct mutex init_mutex; /* Protects smmu pointer */ - - struct io_pgtable_ops *pgtbl_ops; - bool non_strict; - atomic_t nr_ats_masters; - - enum arm_smmu_domain_stage stage; - union { - struct arm_smmu_s1_cfg s1_cfg; - struct arm_smmu_s2_cfg s2_cfg; - }; - - struct iommu_domain domain; - - struct list_head devices; - spinlock_t devices_lock; -}; - struct arm_smmu_option_prop { u32 opt; const char *prop; From patchwork Thu Jul 23 14:57:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681173 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 2FD3813A4 for ; Thu, 23 Jul 2020 15:08:58 +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 EF96120771 for ; Thu, 23 Jul 2020 15:08:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ockqNHWa"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="zCsk0FDm" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EF96120771 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=AUhfRh06MAGhhQ6Qo/Qb3qxjrMFWFyt50IBfBBkWUCo=; b=ockqNHWauO3buJR18xBTFPbX2 mzLF4SFjviUV1q/oRsIbGuMtKXFx/n+3qCrCIYoZ5O2I3KpvDELNLumhU4dS9PuOdw3ucnCSh7yWI 2pIewkv/P6VwJPy1rTI9me+iJdYrWbAX6trtJ8LxB3um1t3yzVLS+IAQ3jJpmN6imJaUJrzimdHxf 0sB6WHD/u7nViUUSTm9c13ArKw9WD/dlkFJZHcZ9zM6ZQecGIF5CTtZS/RBvcQ8Y74rca1KuHbYg9 kC99qkcE6as4+nHHSFSB0bKJxZB3qbycdm0nhf56ztrap98rFuUC5g44jPRxFCWT9cMclxQd9XOA8 UpdCwO1RQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycoU-0002os-NE; Thu, 23 Jul 2020 15:07:14 +0000 Received: from mail-ej1-x642.google.com ([2a00:1450:4864:20::642]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnE-0002Op-FV for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:08 +0000 Received: by mail-ej1-x642.google.com with SMTP id l4so6704341ejd.13 for ; Thu, 23 Jul 2020 08:05:56 -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=yWZ8FjwXK+dksOqK3nLYWBRxXcByntJO5CNNaeLNHxY=; b=zCsk0FDm4L+791n8G8Whn/IMan8qkhGJpd3itkoU2fE4osc7hietit0/wFo1MMYCKu YLh4ONxoCZqgiKb+XNT+lMP18iTusa796HBhYJrr5tU2ULz1O4FRtnBHbffYUzkXfTay U2N2iJLFAWrq4ssTfz+EYfwXdEtRdmw4xUqyNvL8TOvB/Xl5frW7qhDd7PmG53A+849b 2F3zMOhjDVPKjHCSorennkhS7NA9x26f8xfQYpuud3Sz6YXKCb4f3r/GUwMW17iFcJhH FBm3FAb2l2kcUOpcoW9wxg5I2AOLZKNQw1ZaRwxmYriNdw8jTws/j/LEr0o48ZwuyLdw 1qkQ== 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=yWZ8FjwXK+dksOqK3nLYWBRxXcByntJO5CNNaeLNHxY=; b=AHnNfWFOzGLEq3IjWcKV46dWVm8ZEjjSfP/TyAwUjhqvUY6Ni/8aVwuonwlqf85LqI ECd9+VV0zZ5pGawbfOPNpU05WUz/WFY9INTtFUy+rENi35LJXrqDNlTtiMjenrRjsKlA bZjDDxYMtbJ8K0+Ux7tQC1c2M1DzVjvrTzq+WaywH7RpXh1dEQ1eA9wXvQcFl/1nXvIi aXQAqLLrrzY91PdpGrV72CixzWyNsplptWqOFJMmAWdl6LbYu+SgPq7kpbEDMcyoxAXK 99HQqLMwQ+9hMHGJiyjhldYH2U3TMZILyud7wS6JfvLnvUhToswU257fql0rBWBG7cUf ZZUg== X-Gm-Message-State: AOAM5321F58GrkgnpBGkHyHIE0POr02ZcNeT/s8ijDBL+kUn48zagiHj eEMSQ51l1zUdxbDAEHo5gEB2aA== X-Google-Smtp-Source: ABdhPJylrtOaxrTLvFdaGtqIle2qLiXnjnEywz0sCPFX1x5omIQ/yFKbHKVthU0n2KaXfMbOZkXhOQ== X-Received: by 2002:a17:907:20b4:: with SMTP id pw20mr4955394ejb.225.1595516755496; Thu, 23 Jul 2020 08:05:55 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:54 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 08/13] iommu/arm-smmu-v3: Share process page tables Date: Thu, 23 Jul 2020 16:57:20 +0200 Message-Id: <20200723145724.3014766-9-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110556_664002_09795F23 X-CRM114-Status: GOOD ( 29.52 ) 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 [2a00:1450:4864:20:0:0:0:642 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org With Shared Virtual Addressing (SVA), we need to mirror CPU TTBR, TCR, MAIR and ASIDs in SMMU contexts. Each SMMU has a single ASID space split into two sets, shared and private. Shared ASIDs correspond to those obtained from the arch ASID allocator, and private ASIDs are used for "classic" map/unmap DMA. A possible conflict happens when trying to use a shared ASID that has already been allocated for private use by the SMMU driver. This will be addressed in a later patch by replacing the private ASID. At the moment we return -EBUSY. Each mm_struct shared with the SMMU will have a single context descriptor. Add a refcount to keep track of this. It will be protected by the global SVA lock. Introduce a new arm-smmu-v3-sva.c file and the CONFIG_ARM_SMMU_V3_SVA option to let users opt in SVA support. Signed-off-by: Jean-Philippe Brucker --- v9: Move to arm-smmu-v3-sva.c --- drivers/iommu/Kconfig | 10 +++ drivers/iommu/Makefile | 5 +- drivers/iommu/arm-smmu-v3.h | 8 +++ drivers/iommu/arm-smmu-v3-sva.c | 123 ++++++++++++++++++++++++++++++++ drivers/iommu/arm-smmu-v3.c | 34 +++++++-- 5 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 drivers/iommu/arm-smmu-v3-sva.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 490c86e3615a..afe355c02a50 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -446,6 +446,16 @@ config ARM_SMMU_V3 Say Y here if your system includes an IOMMU device implementing the ARM SMMUv3 architecture. +config ARM_SMMU_V3_SVA + bool "Shared Virtual Addressing support for the ARM SMMUv3" + depends on ARM_SMMU_V3 + help + Support for sharing process address spaces with devices using the + SMMUv3. + + Say Y here if your system supports SVA extensions such as PCIe PASID + and PRI. + config S390_IOMMU def_bool y if S390 && PCI depends on S390 && PCI diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 0fe5a7f9bc69..929a752e4723 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -16,7 +16,10 @@ obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd/debugfs.o obj-$(CONFIG_AMD_IOMMU_V2) += amd/iommu_v2.o obj-$(CONFIG_ARM_SMMU) += arm_smmu.o arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o -obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o +arm_smmu_v3-objs-y += arm-smmu-v3.o +arm_smmu_v3-objs-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o +arm_smmu_v3-objs := $(arm_smmu_v3-objs-y) +obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o obj-$(CONFIG_DMAR_TABLE) += intel/dmar.o obj-$(CONFIG_INTEL_IOMMU) += intel/iommu.o intel/pasid.o obj-$(CONFIG_INTEL_IOMMU) += intel/trace.o diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index 51a9ce07b2d6..6b06a6f19604 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -540,6 +540,9 @@ struct arm_smmu_ctx_desc { u64 ttbr; u64 tcr; u64 mair; + + refcount_t refs; + struct mm_struct *mm; }; struct arm_smmu_l1_ctx_desc { @@ -672,4 +675,9 @@ struct arm_smmu_domain { spinlock_t devices_lock; }; +extern struct xarray arm_smmu_asid_xa; +extern struct mutex arm_smmu_asid_lock; + +bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); + #endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c new file mode 100644 index 000000000000..7c1541864688 --- /dev/null +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implementation of the IOMMU SVA API for the ARM SMMUv3 + */ + +#include +#include +#include + +#include "arm-smmu-v3.h" +#include "io-pgtable-arm.h" + +static struct arm_smmu_ctx_desc * +arm_smmu_share_asid(struct mm_struct *mm, u16 asid) +{ + struct arm_smmu_ctx_desc *cd; + + cd = xa_load(&arm_smmu_asid_xa, asid); + if (!cd) + return NULL; + + if (cd->mm) { + if (WARN_ON(cd->mm != mm)) + return ERR_PTR(-EINVAL); + /* All devices bound to this mm use the same cd struct. */ + refcount_inc(&cd->refs); + return cd; + } + + /* Ouch, ASID is already in use for a private cd. */ + return ERR_PTR(-EBUSY); +} + +__maybe_unused +static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm) +{ + u16 asid; + int err = 0; + u64 tcr, par, reg; + struct arm_smmu_ctx_desc *cd; + struct arm_smmu_ctx_desc *ret = NULL; + + asid = arm64_mm_context_get(mm); + if (!asid) + return ERR_PTR(-ESRCH); + + cd = kzalloc(sizeof(*cd), GFP_KERNEL); + if (!cd) { + err = -ENOMEM; + goto out_put_context; + } + + refcount_set(&cd->refs, 1); + + mutex_lock(&arm_smmu_asid_lock); + ret = arm_smmu_share_asid(mm, asid); + if (ret) { + mutex_unlock(&arm_smmu_asid_lock); + goto out_free_cd; + } + + err = xa_insert(&arm_smmu_asid_xa, asid, cd, GFP_KERNEL); + mutex_unlock(&arm_smmu_asid_lock); + + if (err) + goto out_free_asid; + + tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, 64ULL - VA_BITS) | + FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, ARM_LPAE_TCR_RGN_WBWA) | + FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, ARM_LPAE_TCR_RGN_WBWA) | + FIELD_PREP(CTXDESC_CD_0_TCR_SH0, ARM_LPAE_TCR_SH_IS) | + CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64; + + switch (PAGE_SIZE) { + case SZ_4K: + tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_4K); + break; + case SZ_16K: + tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_16K); + break; + case SZ_64K: + tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_TG0, ARM_LPAE_TCR_TG0_64K); + break; + default: + WARN_ON(1); + err = -EINVAL; + goto out_free_asid; + } + + reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1); + par = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_PARANGE_SHIFT); + tcr |= FIELD_PREP(CTXDESC_CD_0_TCR_IPS, par); + + cd->ttbr = virt_to_phys(mm->pgd); + cd->tcr = tcr; + /* + * MAIR value is pretty much constant and global, so we can just get it + * from the current CPU register + */ + cd->mair = read_sysreg(mair_el1); + cd->asid = asid; + cd->mm = mm; + + return cd; + +out_free_asid: + arm_smmu_free_asid(cd); +out_free_cd: + kfree(cd); +out_put_context: + arm64_mm_context_put(mm); + return err < 0 ? ERR_PTR(err) : ret; +} + +__maybe_unused +static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) +{ + if (arm_smmu_free_asid(cd)) { + /* Unpin ASID */ + arm64_mm_context_put(cd->mm); + kfree(cd); + } +} diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 827334ed312b..06f148a9ed82 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -68,7 +68,8 @@ struct arm_smmu_option_prop { const char *prop; }; -static DEFINE_XARRAY_ALLOC1(asid_xa); +DEFINE_XARRAY_ALLOC1(arm_smmu_asid_xa); +DEFINE_MUTEX(arm_smmu_asid_lock); static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, @@ -1004,7 +1005,8 @@ static int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, #ifdef __BIG_ENDIAN CTXDESC_CD_0_ENDI | #endif - CTXDESC_CD_0_R | CTXDESC_CD_0_A | CTXDESC_CD_0_ASET | + CTXDESC_CD_0_R | CTXDESC_CD_0_A | + (cd->mm ? 0 : CTXDESC_CD_0_ASET) | CTXDESC_CD_0_AA64 | FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) | CTXDESC_CD_0_V; @@ -1108,12 +1110,20 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain) cdcfg->cdtab = NULL; } -static void arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd) +bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd) { + bool free; + struct arm_smmu_ctx_desc *old_cd; + if (!cd->asid) - return; + return false; - xa_erase(&asid_xa, cd->asid); + free = refcount_dec_and_test(&cd->refs); + if (free) { + old_cd = xa_erase(&arm_smmu_asid_xa, cd->asid); + WARN_ON(old_cd != cd); + } + return free; } /* Stream table manipulation functions */ @@ -1801,9 +1811,12 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; + /* Prevent SVA from touching the CD while we're freeing it */ + mutex_lock(&arm_smmu_asid_lock); if (cfg->cdcfg.cdtab) arm_smmu_free_cd_tables(smmu_domain); arm_smmu_free_asid(&cfg->cd); + mutex_unlock(&arm_smmu_asid_lock); } else { struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; if (cfg->vmid) @@ -1823,10 +1836,14 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr; - ret = xa_alloc(&asid_xa, &asid, &cfg->cd, + refcount_set(&cfg->cd.refs, 1); + + /* Prevent SVA from modifying the ASID until it is written to the CD */ + mutex_lock(&arm_smmu_asid_lock); + ret = xa_alloc(&arm_smmu_asid_xa, &asid, &cfg->cd, XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL); if (ret) - return ret; + goto out_unlock; cfg->s1cdmax = master->ssid_bits; @@ -1854,12 +1871,15 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, if (ret) goto out_free_cd_tables; + mutex_unlock(&arm_smmu_asid_lock); return 0; out_free_cd_tables: arm_smmu_free_cd_tables(smmu_domain); out_free_asid: arm_smmu_free_asid(&cfg->cd); +out_unlock: + mutex_unlock(&arm_smmu_asid_lock); return ret; } From patchwork Thu Jul 23 14:57:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681179 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 5C18E138A for ; Thu, 23 Jul 2020 15:09:12 +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 2EFCC20771 for ; Thu, 23 Jul 2020 15:09:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kbLKt005"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="aCMH28yf" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2EFCC20771 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=H8fqcH90WCz8hie8vRgv8EgxIY7hrvjOY7csvrN8k/Q=; b=kbLKt0059r7p8j5cliGIaYbul fOUdVzbar7t13HIIgeMFl3Q3kbMeP32uMSFpDob053OAhjqjsKF4WMUcSXqvqCXEaDyDDqv7wVigq ulx1uF+iSjcv/OKpL7h3oq0HF0jJEuNS+9Y4phOOvrCQdZiw7l/nAkNB21azfUmKaIfnhcbm4rj6O CAwVCOGztpd0ybLJp48jY4Rn+XbvOZx/6v5P9XefLHw4mSN8HvztH775QNwdibv3zFpKapPZeNLX4 bau87nGt41kJoqxD5/l80pfezjQwgn2S54drlK9FREeWC5UFogHdkoIjH9dgyKGFNMYlwzb457qyt OTLr2BC1g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycoh-0002vX-0w; Thu, 23 Jul 2020 15:07:27 +0000 Received: from mail-ej1-x641.google.com ([2a00:1450:4864:20::641]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnF-0002PV-FP for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:09 +0000 Received: by mail-ej1-x641.google.com with SMTP id w9so6730991ejc.8 for ; Thu, 23 Jul 2020 08:05:57 -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=wskuJloDXQffCZslMedcsZLhDNM/RTcftR4W5M+lmWM=; b=aCMH28yfVT0dvw1jNUUZbraQg0/4QDSbSz+ipcvfIDhdbz2vRFp3gQyyZcGEeOpIOf Rk6ZnzcSzfP5U5s7YRqSVsQpUjLMeafohbmXpBJ7W3cP6eonBGltklz41+NaxrRh6KXR 8nNwD3m8wK5KJI5I9RTCs8hDN+qtGUb0sL89irJmOnt7TQswOSqjyvx+Wz0jNW/5DKde fBEmAZK5nmCq5IqFkb7+f6r0CSP5mi6nGaFF2fC/yjVrGHFemFsd/NxvuU7UB/IEY2QF 6M6jVyc3K+eUpLxJwuaNq2xpP+hdAOSlWiiFig33xtIJIKR1oyfLwAn2X87VVQSoEQqK xLlA== 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=wskuJloDXQffCZslMedcsZLhDNM/RTcftR4W5M+lmWM=; b=h99eNUuu2/idTrUcet1r4u/K1MqUNVDS+XufxbZ8HqQqlRxfAvnTUkPSy5aidWJPNH hOhX+jNa5BN4f2jm/R7AXs0+5tTvF+8d/Cxb4CYEIxzMU6GTnGlgBeLlCOk8xq5SkIYk ac+7vX4mIIfAGDrRxl+Trrrr3HHx+/002r0pL5IGACuNJf6eJB02JFBwzoXnTp5xakwK 3q1K4/VJLhHCye0tVhGVND2CijtXGGACWB8C7nIe+8wWXF3AVeJbJeIXT2RxIR0PUkdQ 6N5AMmYadDkOc+gqwFtFu1QJptmMAZecAxcWJIP27BXpwvz0F7sfaNNNGGyHcP1ZzLRU sytA== X-Gm-Message-State: AOAM533YmerJknl3gUKuAYNTGRs6zKJYA9r1YXFOsWyNNC9wBvcYfqgr 7DQX3tcxS7lD7BiXIys+RQpmVA== X-Google-Smtp-Source: ABdhPJyB1Vkh5KERl8YmjBS8VfddZR0PFejHbSzUL2vYjqtEO7CwYUzdDRG0iR2rh/YcuHmXTAF++A== X-Received: by 2002:a17:906:1747:: with SMTP id d7mr4752761eje.39.1595516756567; Thu, 23 Jul 2020 08:05:56 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:56 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 09/13] iommu/arm-smmu-v3: Seize private ASID Date: Thu, 23 Jul 2020 16:57:21 +0200 Message-Id: <20200723145724.3014766-10-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110557_606291_7B2F8F31 X-CRM114-Status: GOOD ( 23.23 ) 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 [2a00:1450:4864:20:0:0:0:641 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The SMMU has a single ASID space, the union of shared and private ASID sets. This means that the SMMU driver competes with the arch allocator for ASIDs. Shared ASIDs are those of Linux processes, allocated by the arch, and contribute in broadcast TLB maintenance. Private ASIDs are allocated by the SMMU driver and used for "classic" map/unmap DMA. They require command-queue TLB invalidations. When we pin down an mm_context and get an ASID that is already in use by the SMMU, it belongs to a private context. We used to simply abort the bind, but this is unfair to users that would be unable to bind a few seemingly random processes. Try to allocate a new private ASID for the context, and make the old ASID shared. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm-smmu-v3.h | 3 +++ drivers/iommu/arm-smmu-v3-sva.c | 36 +++++++++++++++++++++++++++++++-- drivers/iommu/arm-smmu-v3.c | 34 +++++++++++++++++++------------ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index 6b06a6f19604..90c08f156b43 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -678,6 +678,9 @@ struct arm_smmu_domain { extern struct xarray arm_smmu_asid_xa; extern struct mutex arm_smmu_asid_lock; +int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, + struct arm_smmu_ctx_desc *cd); +void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid); bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); #endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c index 7c1541864688..d590c864bdf3 100644 --- a/drivers/iommu/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -10,10 +10,19 @@ #include "arm-smmu-v3.h" #include "io-pgtable-arm.h" +/* + * Try to reserve this ASID in the SMMU. If it is in use, try to steal it from + * the private entry. Careful here, we may be modifying the context tables of + * another SMMU! + */ static struct arm_smmu_ctx_desc * arm_smmu_share_asid(struct mm_struct *mm, u16 asid) { + int ret; + u32 new_asid; struct arm_smmu_ctx_desc *cd; + struct arm_smmu_device *smmu; + struct arm_smmu_domain *smmu_domain; cd = xa_load(&arm_smmu_asid_xa, asid); if (!cd) @@ -27,8 +36,31 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid) return cd; } - /* Ouch, ASID is already in use for a private cd. */ - return ERR_PTR(-EBUSY); + smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd); + smmu = smmu_domain->smmu; + + ret = xa_alloc(&arm_smmu_asid_xa, &new_asid, cd, + XA_LIMIT(1, 1 << smmu->asid_bits), GFP_KERNEL); + if (ret) + return ERR_PTR(-ENOSPC); + /* + * Race with unmap: TLB invalidations will start targeting the new ASID, + * which isn't assigned yet. We'll do an invalidate-all on the old ASID + * later, so it doesn't matter. + */ + cd->asid = new_asid; + /* + * Update ASID and invalidate CD in all associated masters. There will + * be some overlap between use of both ASIDs, until we invalidate the + * TLB. + */ + arm_smmu_write_ctx_desc(smmu_domain, 0, cd); + + /* Invalidate TLB entries previously associated with that context */ + arm_smmu_tlb_inv_asid(smmu, asid); + + xa_erase(&arm_smmu_asid_xa, asid); + return NULL; } __maybe_unused diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 06f148a9ed82..4a47b977ed01 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -873,6 +873,17 @@ static int arm_smmu_cmdq_batch_submit(struct arm_smmu_device *smmu, } /* Context descriptor manipulation functions */ +void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid) +{ + struct arm_smmu_cmdq_ent cmd = { + .opcode = CMDQ_OP_TLBI_NH_ASID, + .tlbi.asid = asid, + }; + + arm_smmu_cmdq_issue_cmd(smmu, &cmd); + arm_smmu_cmdq_issue_sync(smmu); +} + static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, int ssid, bool leaf) { @@ -953,8 +964,8 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain, return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS; } -static int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, - int ssid, struct arm_smmu_ctx_desc *cd) +int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, + struct arm_smmu_ctx_desc *cd) { /* * This function handles the following cases: @@ -1610,15 +1621,6 @@ static void arm_smmu_tlb_inv_context(void *cookie) struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cmdq_ent cmd; - if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { - cmd.opcode = CMDQ_OP_TLBI_NH_ASID; - cmd.tlbi.asid = smmu_domain->s1_cfg.cd.asid; - cmd.tlbi.vmid = 0; - } else { - cmd.opcode = CMDQ_OP_TLBI_S12_VMALL; - cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid; - } - /* * NOTE: when io-pgtable is in non-strict mode, we may get here with * PTEs previously cleared by unmaps on the current CPU not yet visible @@ -1626,8 +1628,14 @@ static void arm_smmu_tlb_inv_context(void *cookie) * insertion to guarantee those are observed before the TLBI. Do be * careful, 007. */ - arm_smmu_cmdq_issue_cmd(smmu, &cmd); - arm_smmu_cmdq_issue_sync(smmu); + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { + arm_smmu_tlb_inv_asid(smmu, smmu_domain->s1_cfg.cd.asid); + } else { + cmd.opcode = CMDQ_OP_TLBI_S12_VMALL; + cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid; + arm_smmu_cmdq_issue_cmd(smmu, &cmd); + arm_smmu_cmdq_issue_sync(smmu); + } arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0); } From patchwork Thu Jul 23 14:57:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681177 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 3C13E138A for ; Thu, 23 Jul 2020 15:09:09 +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 1351520771 for ; Thu, 23 Jul 2020 15:09:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iKT8oszA"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="DTNtyx73" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1351520771 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=+med98XpznpV9IyVG1Hd3FuJv5x9cpgYn2xHsoqbsgQ=; b=iKT8oszAR6VRefaOBGpljNmzm R2t7N5USAIjk4yPrTgsbA3Q7ref9b5SofWLQZ9kkFBoJKZ0hpQYmcEpjrWJrp2BN8taux9TE0zhag YwvR9O+Q69sbsD47bfWArnBWGN4aiqohlXiImyCyF5/uS6+2ny/DqnmW1ACIFfbnda+mgor3t2NX5 TBIItaNiJcO/doeE8G7bqJ4CQKFs9lfkiNF+C6iZXKVrAP7lh29heSAWL27/Liwz72wwEpgABMVsw mLQj17OKN2DfHhy184WrJ+oX0kqDT/Q1JSpBPYqhYVuRyJue7/ANACBmSfLiom6h45viwald3EVoB KbVAJ3PrA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycop-0002zj-WA; Thu, 23 Jul 2020 15:07:36 +0000 Received: from mail-ej1-x642.google.com ([2a00:1450:4864:20::642]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnG-0002QC-Qo for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:12 +0000 Received: by mail-ej1-x642.google.com with SMTP id w9so6731059ejc.8 for ; Thu, 23 Jul 2020 08:05:58 -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=A7i0TfeVtbmivmToJFYuNh5KNdNgY1vTU0jTEZh4S44=; b=DTNtyx73PEuwQyesbHMqyc9KRfKpkQLrDtcn1RgI9i4L3sTyOvObkePC3pFEX6wvt2 MIPUw9T6dRpslzm2jPvmVSks4HcWd+hvazFQVLaoWPm4qT56MkiVBeTrDo0ymJnURpj2 vtenI7sn7dpZj89RA0UTYa8k4TPsuWpYkHVMIPHJig94Dckhm80dkYcfoZaio9agcS3n xLhN7up9sW+t4vIeI5iXyj10DWuVy1aOXj157IP5Zw1Wvms2VzR7c2e//IYe0g83KWLS lL5EaldElZ6lyNR+eS+uTZrqidD/jtYbmwQjF5wEK/8KQOm0TvzjICgChVhbUs29LV1G 0cNA== 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=A7i0TfeVtbmivmToJFYuNh5KNdNgY1vTU0jTEZh4S44=; b=t84bktx3oqW0c8JDsALvQi8VAV6s07IbyXSSBkcQ4xvHbvyt2fICg2H262PEwj6Lfl 3jgaxAnwsNZQ1RN1KUABtvcUn6t8vzIKsP0VyNXQQCb1LhY8CfE7wKcyjdvpKwQJuRAM mDfY2e6Bvi2xnmB9poaZx4e0dF2+xf9vVvJ/UrGeaTTnaVtsC0Rce4qmhs63sijd93Q2 AwW7uHexHSqPJxT0e0Pan3tmbW73haGqMrTP0kXbzXan93GF3wSxD+yCr6ZxXGZ8Mzws FfZwcQeoDHy4ndO7hjZhse5W0omK3nU1hbUnbXSJtjGeX+DwJZR1ftWlqRUGpDWhr86D iy3Q== X-Gm-Message-State: AOAM530lPFvMhGopMXllYc/TbOmqeatzlalUvg1LTQhqSnDinOyVp/TC 60dQvFJjonc1DUeMqFAol0cJ7A== X-Google-Smtp-Source: ABdhPJyMNuQc7O5Fnv72xrZh/TQxEiIO6uTWkERHUtAM85C0vk1UvtHsBd9/BzGHJAnoYUE3RVudEw== X-Received: by 2002:a17:906:4e87:: with SMTP id v7mr4736862eju.242.1595516757878; Thu, 23 Jul 2020 08:05:57 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:57 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 10/13] iommu/arm-smmu-v3: Check for SVA features Date: Thu, 23 Jul 2020 16:57:22 +0200 Message-Id: <20200723145724.3014766-11-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110558_947821_5552FCBF X-CRM114-Status: GOOD ( 17.21 ) 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 [2a00:1450:4864:20:0:0:0:642 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, Suzuki K Poulose , robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Aggregate all sanity-checks for sharing CPU page tables with the SMMU under a single ARM_SMMU_FEAT_SVA bit. For PCIe SVA, users also need to check FEAT_ATS and FEAT_PRI. For platform SVA, they will have to check FEAT_STALLS. Introduce ARM_SMMU_FEAT_BTM (Broadcast TLB Maintenance), but don't enable it at the moment. Since the entire VMID space is shared with the CPU, enabling DVM (by clearing SMMU_CR2.PTM) could result in over-invalidation and affect performance of stage-2 mappings. Cc: Suzuki K Poulose Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm-smmu-v3.h | 10 ++++++++ drivers/iommu/arm-smmu-v3-sva.c | 43 +++++++++++++++++++++++++++++++++ drivers/iommu/arm-smmu-v3.c | 3 +++ 3 files changed, 56 insertions(+) diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index 90c08f156b43..7b14b48a26c7 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -602,6 +602,8 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_STALL_FORCE (1 << 13) #define ARM_SMMU_FEAT_VAX (1 << 14) #define ARM_SMMU_FEAT_RANGE_INV (1 << 15) +#define ARM_SMMU_FEAT_BTM (1 << 16) +#define ARM_SMMU_FEAT_SVA (1 << 17) u32 features; #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) @@ -683,4 +685,12 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid); bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); +#ifdef CONFIG_ARM_SMMU_V3_SVA +bool arm_smmu_sva_supported(struct arm_smmu_device *smmu); +#else /* CONFIG_ARM_SMMU_V3_SVA */ +static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) +{ + return false; +} +#endif /* CONFIG_ARM_SMMU_V3_SVA */ #endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c index d590c864bdf3..eedc6c8264f1 100644 --- a/drivers/iommu/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -153,3 +153,46 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) kfree(cd); } } + +bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) +{ + unsigned long reg, fld; + unsigned long oas; + unsigned long asid_bits; + + u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY; + + if ((smmu->features & feat_mask) != feat_mask) + return false; + + if (!(smmu->pgsize_bitmap & PAGE_SIZE)) + return false; + + /* + * Get the smallest PA size of all CPUs (sanitized by cpufeature). We're + * not even pretending to support AArch32 here. Abort if the MMU outputs + * addresses larger than what we support. + */ + reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1); + fld = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_PARANGE_SHIFT); + oas = id_aa64mmfr0_parange_to_phys_shift(fld); + if (smmu->oas < oas) + return false; + + /* We can support bigger ASIDs than the CPU, but not smaller */ + fld = cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR0_ASID_SHIFT); + asid_bits = fld ? 16 : 8; + if (smmu->asid_bits < asid_bits) + return false; + + /* + * See max_pinned_asids in arch/arm64/mm/context.c. The following is + * generally the maximum number of bindable processes. + */ + if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) + asid_bits--; + dev_dbg(smmu->dev, "%d shared contexts\n", (1 << asid_bits) - + num_possible_cpus() - 2); + + return true; +} diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 4a47b977ed01..558973e3cc1b 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -3258,6 +3258,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) smmu->ias = max(smmu->ias, smmu->oas); + if (arm_smmu_sva_supported(smmu)) + smmu->features |= ARM_SMMU_FEAT_SVA; + dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n", smmu->ias, smmu->oas, smmu->features); return 0; From patchwork Thu Jul 23 14:57:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681183 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 782D9722 for ; Thu, 23 Jul 2020 15:09:26 +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 4FFAD22B40 for ; Thu, 23 Jul 2020 15:09:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="SL6KuEbs"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="MA/ebgX5" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4FFAD22B40 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=3CktBfnxT4/vm3xi8wPm4mUd6zD5XxOoBRU4rtoVtAo=; b=SL6KuEbsl8fWaBXmGjgNnOtOU sSq8ngWlcah5pmgD+hgJi7/clcnhyqp9ziFljaBKuxYmGATCrq+1XvVXN6QataO+eFopNngNnsflL pSAQWDWXL2fnWHcPpDI2x4SjOMuZWtUY+/3yjAHykHcu0KNwfAvo9GxXCFznHtdWNxjHhXG0YSuTM +7xH5ORYQHLhUOaaeq7dksiYoB32D4r4tKDdZ+K5E/+OOirOLjUx0JYdlQ+H+C0N+572LhG+mel/V 7B/BpnjkeTS/abLqNIw0EmHhMAFpKqtG5aBIizj8NIFa657G+VI5Sv/Mlb3XnHID5WNHGA+B+6RQX YZPtp5sAg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycos-00031Y-Qi; Thu, 23 Jul 2020 15:07:38 +0000 Received: from mail-ed1-f66.google.com ([209.85.208.66]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnI-0002R5-N8 for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:14 +0000 Received: by mail-ed1-f66.google.com with SMTP id bm28so4782631edb.2 for ; Thu, 23 Jul 2020 08:06:00 -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=Jrw/NadD7mFzT8TBC8lMm0pIPDE9dyvhyfTA7s3Qrzw=; b=MA/ebgX5Se7spe9U3ykZrqU7upYgH1nEUv7j2VNLEiQBMMGEOtspTB9MAk4GWf6fDL fZiVo0Y6/RPZCPanxi1YVndp05AGW/dommTEjJEFISljrimpkhmFAJXQhc2FIrym4wh4 0tmJq8YDuYW1oSdrsApPP7gnoRMEojacDcPONQEKObfvlIw9+gBAbWkDlwgOaSgkHWdC vLBx+uePTPgUxOt50S0gd/02Ueb9AhXHnVEBo4qInLAvNp+iz/AfipW7x/Hl2PxpSm1Z SCLU3futU5dCG4raHOWP1VZxClEnW28EX5iJmfyf2QljA1Bp9eWAwDi0lpapKz2i1YKh 2iTA== 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=Jrw/NadD7mFzT8TBC8lMm0pIPDE9dyvhyfTA7s3Qrzw=; b=U98NxOPIDvDo6HDw0/zkYhrEBYmpkqE7LtBPdg8jeaG3V3Y+Qj1WxnWItS2Pdg1t+T 7qlI+Lku6+EWjQGi9JedkHMTPZXrzO0djYGCf5giDf5YyjZpHd+bCfKGPHwxMAD+uGeX raqwqxPla0/1zDoUaZfm7Hwt3s6yqVI60WtHcgMsv6uIJpKHs4XwunQfnxXZMhsgVr+h 5NVbSbt6BPc/oUekv0EGb7meMxHpGZt3+laoDrnHNFRN2fNNNV58w5APTRcnbFWNGSOV 8FaDDO1EdZ7OamSK2UB799+DnPe5XvZMwNIlX4wpLplYGD4zKgRih+KUQ6/zSCT9J0Ep CIEA== X-Gm-Message-State: AOAM530uIx7Je9ltFMGFrNprzLZUS6KFHsUtVmQTz+3XAPBZIVVGfr6j TM2vU1RbP2UBK61y1BBH0Ek5PA== X-Google-Smtp-Source: ABdhPJxWJieOow5IF9rR+um8s0iDowKOUoOfgOi0Ugh+W2dv56Mb0L6soYgMpIjyNrZdDv0HRz7IFw== X-Received: by 2002:a05:6402:b9b:: with SMTP id cf27mr4677754edb.84.1595516759135; Thu, 23 Jul 2020 08:05:59 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:58 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 11/13] iommu/arm-smmu-v3: Add SVA device feature Date: Thu, 23 Jul 2020 16:57:23 +0200 Message-Id: <20200723145724.3014766-12-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110600_841176_686D477A X-CRM114-Status: GOOD ( 19.59 ) 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 [209.85.208.66 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.208.66 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Implement the IOMMU device feature callbacks to support the SVA feature. At the moment dev_has_feat() returns false since I/O Page Faults isn't yet implemented. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm-smmu-v3.h | 26 +++++++++++ drivers/iommu/arm-smmu-v3-sva.c | 49 ++++++++++++++++++++ drivers/iommu/arm-smmu-v3.c | 79 +++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index 7b14b48a26c7..ba34914813ff 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -646,6 +646,8 @@ struct arm_smmu_master { u32 *sids; unsigned int num_sids; bool ats_enabled; + bool sva_enabled; + struct list_head bonds; unsigned int ssid_bits; }; @@ -687,10 +689,34 @@ bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); #ifdef CONFIG_ARM_SMMU_V3_SVA bool arm_smmu_sva_supported(struct arm_smmu_device *smmu); +bool arm_smmu_master_sva_supported(struct arm_smmu_master *master); +bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master); +int arm_smmu_master_enable_sva(struct arm_smmu_master *master); +int arm_smmu_master_disable_sva(struct arm_smmu_master *master); #else /* CONFIG_ARM_SMMU_V3_SVA */ static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) { return false; } + +static inline bool arm_smmu_master_sva_supported(struct arm_smmu_master *master) +{ + return false; +} + +static inline bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master) +{ + return false; +} + +static inline int arm_smmu_master_enable_sva(struct arm_smmu_master *master) +{ + return -ENODEV; +} + +static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) +{ + return -ENODEV; +} #endif /* CONFIG_ARM_SMMU_V3_SVA */ #endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c index eedc6c8264f1..b6805effede4 100644 --- a/drivers/iommu/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -10,6 +10,8 @@ #include "arm-smmu-v3.h" #include "io-pgtable-arm.h" +static DEFINE_MUTEX(sva_lock); + /* * Try to reserve this ASID in the SMMU. If it is in use, try to steal it from * the private entry. Careful here, we may be modifying the context tables of @@ -196,3 +198,50 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) return true; } + +static bool arm_smmu_iopf_supported(struct arm_smmu_master *master) +{ + return false; +} + +bool arm_smmu_master_sva_supported(struct arm_smmu_master *master) +{ + if (!(master->smmu->features & ARM_SMMU_FEAT_SVA)) + return false; + + /* SSID and IOPF support are mandatory for the moment */ + return master->ssid_bits && arm_smmu_iopf_supported(master); +} + +bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master) +{ + bool enabled; + + mutex_lock(&sva_lock); + enabled = master->sva_enabled; + mutex_unlock(&sva_lock); + return enabled; +} + +int arm_smmu_master_enable_sva(struct arm_smmu_master *master) +{ + mutex_lock(&sva_lock); + master->sva_enabled = true; + mutex_unlock(&sva_lock); + + return 0; +} + +int arm_smmu_master_disable_sva(struct arm_smmu_master *master) +{ + mutex_lock(&sva_lock); + if (!list_empty(&master->bonds)) { + dev_err(master->dev, "cannot disable SVA, device is bound\n"); + mutex_unlock(&sva_lock); + return -EBUSY; + } + master->sva_enabled = false; + mutex_unlock(&sva_lock); + + return 0; +} diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 558973e3cc1b..0fd63d93bd2c 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2163,6 +2163,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) master = dev_iommu_priv_get(dev); smmu = master->smmu; + /* + * Checking that SVA is disabled ensures that this device isn't bound to + * any mm, and can be safely detached from its old domain. Bonds cannot + * be removed concurrently since we're holding the group mutex. + */ + if (arm_smmu_master_sva_enabled(master)) { + dev_err(dev, "cannot attach - SVA enabled\n"); + return -EBUSY; + } + arm_smmu_detach_dev(master); mutex_lock(&smmu_domain->init_mutex); @@ -2310,6 +2320,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev) master->smmu = smmu; master->sids = fwspec->ids; master->num_sids = fwspec->num_ids; + INIT_LIST_HEAD(&master->bonds); dev_iommu_priv_set(dev, master); /* Check the SIDs are in range of the SMMU and our stream table */ @@ -2362,6 +2373,7 @@ static void arm_smmu_release_device(struct device *dev) return; master = dev_iommu_priv_get(dev); + WARN_ON(arm_smmu_master_sva_enabled(master)); arm_smmu_detach_dev(master); arm_smmu_disable_pasid(master); kfree(master); @@ -2479,6 +2491,69 @@ static void arm_smmu_get_resv_regions(struct device *dev, iommu_dma_get_resv_regions(dev, head); } +static bool arm_smmu_dev_has_feature(struct device *dev, + enum iommu_dev_features feat) +{ + struct arm_smmu_master *master = dev_iommu_priv_get(dev); + + if (!master) + return false; + + switch (feat) { + case IOMMU_DEV_FEAT_SVA: + return arm_smmu_master_sva_supported(master); + default: + return false; + } +} + +static bool arm_smmu_dev_feature_enabled(struct device *dev, + enum iommu_dev_features feat) +{ + struct arm_smmu_master *master = dev_iommu_priv_get(dev); + + if (!master) + return false; + + switch (feat) { + case IOMMU_DEV_FEAT_SVA: + return arm_smmu_master_sva_enabled(master); + default: + return false; + } +} + +static int arm_smmu_dev_enable_feature(struct device *dev, + enum iommu_dev_features feat) +{ + if (!arm_smmu_dev_has_feature(dev, feat)) + return -ENODEV; + + if (arm_smmu_dev_feature_enabled(dev, feat)) + return -EBUSY; + + switch (feat) { + case IOMMU_DEV_FEAT_SVA: + return arm_smmu_master_enable_sva(dev_iommu_priv_get(dev)); + default: + return -EINVAL; + } +} + +static int arm_smmu_dev_disable_feature(struct device *dev, + enum iommu_dev_features feat) +{ + if (!arm_smmu_dev_feature_enabled(dev, feat)) + return -EINVAL; + + switch (feat) { + case IOMMU_DEV_FEAT_SVA: + return arm_smmu_master_disable_sva(dev_iommu_priv_get(dev)); + default: + return -EINVAL; + } +} + static struct iommu_ops arm_smmu_ops = { .capable = arm_smmu_capable, .domain_alloc = arm_smmu_domain_alloc, @@ -2497,6 +2572,10 @@ static struct iommu_ops arm_smmu_ops = { .of_xlate = arm_smmu_of_xlate, .get_resv_regions = arm_smmu_get_resv_regions, .put_resv_regions = generic_iommu_put_resv_regions, + .dev_has_feat = arm_smmu_dev_has_feature, + .dev_feat_enabled = arm_smmu_dev_feature_enabled, + .dev_enable_feat = arm_smmu_dev_enable_feature, + .dev_disable_feat = arm_smmu_dev_disable_feature, .pgsize_bitmap = -1UL, /* Restricted during device attach */ }; From patchwork Thu Jul 23 14:57:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681217 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 07DE8138C for ; Thu, 23 Jul 2020 15:27:06 +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 C320C22B40 for ; Thu, 23 Jul 2020 15:27:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="BVnwr18+"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="JtG71i7A"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="U4fhKkMG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C320C22B40 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=EmUz8dyDYsq2M2axeEFlcOftKvGm6CDcqYloTll2D7Q=; b=BVnwr18+1XmWCgZdtfkiIGx1Q OrnpCWrhE7U/AjlBWqJtte/8cBhb6VfAHjJNNOBoSEd4ifJZg1VAPyRxn17DF4LVf5JxW/TfRgi2e 3Gk/WSL/qLHK8eb3+gLn6yy+XH5Kwk424SdUgZMtFY8PMJ/Vexux+PUO0OqfWt597q62KrJcqDOLh I8DmAvu8AVZTiXmtBrOYRDNVN3cqZA/rTqtqIOwN8vDWDK9/NxBSV4TXQK6+Ho1O+z8IoEXUakDmY Dzt6Wf6F7Ur4JKPfZpJ1WhNRVp3d+E+EfKly3dr/lGoWzbKRBQJsiCShxA0hPKCmTXPm/hPeIQySi lwtxknr1w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jyd66-0006qi-MG; Thu, 23 Jul 2020 15:25:26 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jyd64-0006ln-16 for linux-arm-kernel@merlin.infradead.org; Thu, 23 Jul 2020 15:25:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=Mk8rfxkDw1PWo2f4BS9IArvvvnje70F6yQIOzpOD8IE=; b=JtG71i7AXOhUN5NMD0keRzJWFP zIf8Z9M2nyq0VGTiDBQYYcw/k2Ky49xBwSQaMt3b/BsErj1bJLSpQW+0EVbUj2FNHVesL4mwFMh3Y EBWipGjFigiweXVLPuHrBh5LOsluiEASBr7srKXvQtYaRWEQBp/2IIxrxUgCjecZQfuxZk9BZ9m3M HoYvk+8TL/3VuGzkZPHADYHWZ0cAY5pWg6IKpq4yPoUSMd7UZ/H6aSdUGzR5iPJvlt4QCz3vc4yNr J+0CSnXr9BpJ3hr18X63KzJSxV0SsVvPrxE2q67Ieq2r8QyigOIW1XWin6XXfDNcmGrHMwXihuRXl 6MP3ofaA==; Received: from mail-ed1-x544.google.com ([2a00:1450:4864:20::544]) by casper.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnM-0000hI-N0 for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:11 +0000 Received: by mail-ed1-x544.google.com with SMTP id by13so4735779edb.11 for ; Thu, 23 Jul 2020 08:06:01 -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=Mk8rfxkDw1PWo2f4BS9IArvvvnje70F6yQIOzpOD8IE=; b=U4fhKkMGWaZ7UQ9bJAW+0wCHxyBWb2e+wAcH3hCBcLXarR/1hw8C7KW6PC43KAOa85 6Kisq+Cnbi2f1X9FUlyYdRbL5Th4fHsImfo8Uml1LFd5IeikdNXorA4tSHCmOe5Bpmy2 zZyJ29h/Rn3ocyeFYy5TmhGQYtfUf5zucp+mQq8E4w4jxRpTRan/DTcUnMj19Ql7CzdC AqFcaO46/XFB9xyc47RtzBx526+v+DEqpsdAM/uIMHmhPWOTTuvRrXiVhysalUL9pJp2 TdgrhdczKE2VTwvsLcM2Tphf3p+ekP3p3x7jiaZEILBntocIIC9+tlOzjaEeFJ145cP5 asww== 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=Mk8rfxkDw1PWo2f4BS9IArvvvnje70F6yQIOzpOD8IE=; b=uM3p0OX2P3WRFf2yZ9F3YnvelmdHqmz3mGnoc7TJY7gXykj0Je2H3vOFhrnADC/gst 9TEiqas5acrRs3zinw7Ud0GwvZ+QY5ksoVYkWi0Q0lwgNVPO4rSuA7rS2vD+hB3ED6X4 u9KbQehfPhxhdCmapYlYuaN9g85ZDvRpeWvr4d5PgjmgIab5udaZb1OdaqF9LxiQqPq2 q2VwHsXB/0+v2shi+xCXwMeEMWFacKm2q4CnVVT4WdkytdbSJPa2aprW6bfjpbCzHfjI oQIOmfI1z5I867vu+FW4G7pril4jA81W/4sLAcRmQ5DuSUF0VD01rsL+v3ogtcTw+Zbg R5fA== X-Gm-Message-State: AOAM533Ye7biWp5agRr140AdlqjcYpvj1mUglVB4qn0IilWAYre2V3kA t8QA87817RiDvtcGsWb8nXkRmQvQqXk= X-Google-Smtp-Source: ABdhPJwSlP//G+7+0FWTltT7MdleVtcsana2ram3En2LIIAiVx0hmuABWMxHroM+0IYv8b2AZ4FLkA== X-Received: by 2002:aa7:ca05:: with SMTP id y5mr4669915eds.204.1595516760287; Thu, 23 Jul 2020 08:06:00 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.05.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:05:59 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 12/13] iommu/arm-smmu-v3: Implement iommu_sva_bind/unbind() Date: Thu, 23 Jul 2020 16:57:24 +0200 Message-Id: <20200723145724.3014766-13-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_160605_704760_605CEC62 X-CRM114-Status: GOOD ( 28.07 ) X-Spam-Score: -2.1 (--) X-Spam-Report: SpamAssassin version 3.4.4 on casper.infradead.org summary: Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:544 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The sva_bind() function allows devices to access process address spaces using a PASID (aka SSID). (1) bind() allocates or gets an existing MMU notifier tied to the (domain, mm) pair. Each mm gets one PASID. (2) Any change to the address space calls invalidate_range() which sends ATC invalidations (in a subsequent patch). (3) When the process address space dies, the release() notifier disables the CD to allow reclaiming the page tables. Since release() has to be light we do not instruct device drivers to stop DMA here, we just ignore incoming page faults from this point onwards. To avoid any event 0x0a print (C_BAD_CD) we disable translation without clearing CD.V. PCIe Translation Requests and Page Requests are silently denied. Don't clear the R bit because the S bit can't be cleared when STALL_MODEL==0b10 (forced), and clearing R without clearing S is useless. Faulting transactions will stall and will be aborted by the IOPF handler. (4) After stopping DMA, the device driver releases the bond by calling unbind(). We release the MMU notifier, free the PASID and the bond. Three structures keep track of bonds: * arm_smmu_bond: one per {device, mm} pair, the handle returned to the device driver for a bind() request. * arm_smmu_mmu_notifier: one per {domain, mm} pair, deals with ATS/TLB invalidations and clearing the context descriptor on mm exit. * arm_smmu_ctx_desc: one per mm, holds the pinned ASID and pgd. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/Kconfig | 2 + drivers/iommu/arm-smmu-v3.h | 28 ++++ drivers/iommu/arm-smmu-v3-sva.c | 230 +++++++++++++++++++++++++++++++- drivers/iommu/arm-smmu-v3.c | 32 +++-- 4 files changed, 282 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index afe355c02a50..2d05aa570f51 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -449,6 +449,8 @@ config ARM_SMMU_V3 config ARM_SMMU_V3_SVA bool "Shared Virtual Addressing support for the ARM SMMUv3" depends on ARM_SMMU_V3 + select IOMMU_SVA_LIB + select MMU_NOTIFIER help Support for sharing process address spaces with devices using the SMMUv3. diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index ba34914813ff..6365c81a4614 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -677,10 +677,18 @@ struct arm_smmu_domain { struct list_head devices; spinlock_t devices_lock; + + struct list_head mmu_notifiers; }; +static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) +{ + return container_of(dom, struct arm_smmu_domain, domain); +} + extern struct xarray arm_smmu_asid_xa; extern struct mutex arm_smmu_asid_lock; +extern struct arm_smmu_ctx_desc quiet_cd; int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, struct arm_smmu_ctx_desc *cd); @@ -693,6 +701,11 @@ bool arm_smmu_master_sva_supported(struct arm_smmu_master *master); bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master); int arm_smmu_master_enable_sva(struct arm_smmu_master *master); int arm_smmu_master_disable_sva(struct arm_smmu_master *master); +struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, + void *drvdata); +void arm_smmu_sva_unbind(struct iommu_sva *handle); +int arm_smmu_sva_get_pasid(struct iommu_sva *handle); +void arm_smmu_sva_notifier_synchronize(void); #else /* CONFIG_ARM_SMMU_V3_SVA */ static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) { @@ -718,5 +731,20 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) { return -ENODEV; } + +static inline struct iommu_sva * +arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata) +{ + return ERR_PTR(-ENODEV); +} + +static inline void arm_smmu_sva_unbind(struct iommu_sva *handle) {} + +static inline int arm_smmu_sva_get_pasid(struct iommu_sva *handle) +{ + return IOMMU_PASID_INVALID; +} + +static inline void arm_smmu_sva_notifier_synchronize(void) {} #endif /* CONFIG_ARM_SMMU_V3_SVA */ #endif /* _ARM_SMMU_V3_H */ diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c index b6805effede4..a77abbb7a9d7 100644 --- a/drivers/iommu/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -5,11 +5,35 @@ #include #include +#include #include #include "arm-smmu-v3.h" +#include "iommu-sva-lib.h" #include "io-pgtable-arm.h" +struct arm_smmu_mmu_notifier { + struct mmu_notifier mn; + struct arm_smmu_ctx_desc *cd; + bool cleared; + refcount_t refs; + struct list_head list; + struct arm_smmu_domain *domain; +}; + +#define mn_to_smmu(mn) container_of(mn, struct arm_smmu_mmu_notifier, mn) + +struct arm_smmu_bond { + struct iommu_sva sva; + struct mm_struct *mm; + struct arm_smmu_mmu_notifier *smmu_mn; + struct list_head list; + refcount_t refs; +}; + +#define sva_to_bond(handle) \ + container_of(handle, struct arm_smmu_bond, sva) + static DEFINE_MUTEX(sva_lock); /* @@ -65,7 +89,6 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid) return NULL; } -__maybe_unused static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm) { u16 asid; @@ -146,7 +169,6 @@ static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm) return err < 0 ? ERR_PTR(err) : ret; } -__maybe_unused static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) { if (arm_smmu_free_asid(cd)) { @@ -156,6 +178,201 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) } } +static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) +{ + struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); + struct arm_smmu_domain *smmu_domain = smmu_mn->domain; + + mutex_lock(&sva_lock); + if (smmu_mn->cleared) { + mutex_unlock(&sva_lock); + return; + } + + /* + * DMA may still be running. Keep the cd valid to avoid C_BAD_CD events, + * but disable translation. + */ + arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, &quiet_cd); + + arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid); + + smmu_mn->cleared = true; + mutex_unlock(&sva_lock); +} + +static void arm_smmu_mmu_notifier_free(struct mmu_notifier *mn) +{ + kfree(mn_to_smmu(mn)); +} + +static struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { + .release = arm_smmu_mm_release, + .free_notifier = arm_smmu_mmu_notifier_free, +}; + +/* Allocate or get existing MMU notifier for this {domain, mm} pair */ +static struct arm_smmu_mmu_notifier * +arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, + struct mm_struct *mm) +{ + int ret; + struct arm_smmu_ctx_desc *cd; + struct arm_smmu_mmu_notifier *smmu_mn; + + list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) { + if (smmu_mn->mn.mm == mm) { + refcount_inc(&smmu_mn->refs); + return smmu_mn; + } + } + + cd = arm_smmu_alloc_shared_cd(mm); + if (IS_ERR(cd)) + return ERR_CAST(cd); + + smmu_mn = kzalloc(sizeof(*smmu_mn), GFP_KERNEL); + if (!smmu_mn) { + ret = -ENOMEM; + goto err_free_cd; + } + + refcount_set(&smmu_mn->refs, 1); + smmu_mn->cd = cd; + smmu_mn->domain = smmu_domain; + smmu_mn->mn.ops = &arm_smmu_mmu_notifier_ops; + + ret = mmu_notifier_register(&smmu_mn->mn, mm); + if (ret) { + kfree(smmu_mn); + goto err_free_cd; + } + + ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd); + if (ret) + goto err_put_notifier; + + list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers); + return smmu_mn; + +err_put_notifier: + /* Frees smmu_mn */ + mmu_notifier_put(&smmu_mn->mn); +err_free_cd: + arm_smmu_free_shared_cd(cd); + return ERR_PTR(ret); +} + +static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) +{ + struct mm_struct *mm = smmu_mn->mn.mm; + struct arm_smmu_ctx_desc *cd = smmu_mn->cd; + struct arm_smmu_domain *smmu_domain = smmu_mn->domain; + + if (!refcount_dec_and_test(&smmu_mn->refs)) + return; + + list_del(&smmu_mn->list); + arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, NULL); + + /* + * If we went through clear(), we've already invalidated, and no + * new TLB entry can have been formed. + */ + if (!smmu_mn->cleared) + arm_smmu_tlb_inv_asid(smmu_domain->smmu, cd->asid); + + /* Frees smmu_mn */ + mmu_notifier_put(&smmu_mn->mn); + arm_smmu_free_shared_cd(cd); +} + +static struct iommu_sva * +__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) +{ + int ret; + struct arm_smmu_bond *bond; + struct arm_smmu_master *master = dev_iommu_priv_get(dev); + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + + if (!master || !master->sva_enabled) + return ERR_PTR(-ENODEV); + + /* If bind() was already called for this {dev, mm} pair, reuse it. */ + list_for_each_entry(bond, &master->bonds, list) { + if (bond->mm == mm) { + refcount_inc(&bond->refs); + return &bond->sva; + } + } + + bond = kzalloc(sizeof(*bond), GFP_KERNEL); + if (!bond) + return ERR_PTR(-ENOMEM); + + /* Allocate a PASID for this mm if necessary */ + ret = iommu_sva_alloc_pasid(mm, 1, (1U << master->ssid_bits) - 1); + if (ret) + goto err_free_bond; + + bond->mm = mm; + bond->sva.dev = dev; + refcount_set(&bond->refs, 1); + + bond->smmu_mn = arm_smmu_mmu_notifier_get(smmu_domain, mm); + if (IS_ERR(bond->smmu_mn)) { + ret = PTR_ERR(bond->smmu_mn); + goto err_free_pasid; + } + + list_add(&bond->list, &master->bonds); + return &bond->sva; + +err_free_pasid: + iommu_sva_free_pasid(mm); +err_free_bond: + kfree(bond); + return ERR_PTR(ret); +} + +struct iommu_sva * +arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata) +{ + struct iommu_sva *handle; + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + + if (smmu_domain->stage != ARM_SMMU_DOMAIN_S1) + return ERR_PTR(-EINVAL); + + mutex_lock(&sva_lock); + handle = __arm_smmu_sva_bind(dev, mm); + mutex_unlock(&sva_lock); + return handle; +} + +void arm_smmu_sva_unbind(struct iommu_sva *handle) +{ + struct arm_smmu_bond *bond = sva_to_bond(handle); + + mutex_lock(&sva_lock); + if (refcount_dec_and_test(&bond->refs)) { + list_del(&bond->list); + arm_smmu_mmu_notifier_put(bond->smmu_mn); + iommu_sva_free_pasid(bond->mm); + kfree(bond); + } + mutex_unlock(&sva_lock); +} + +int arm_smmu_sva_get_pasid(struct iommu_sva *handle) +{ + struct arm_smmu_bond *bond = sva_to_bond(handle); + + return bond->mm->pasid; +} + bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) { unsigned long reg, fld; @@ -245,3 +462,12 @@ int arm_smmu_master_disable_sva(struct arm_smmu_master *master) return 0; } + +void arm_smmu_sva_notifier_synchronize(void) +{ + /* + * Some MMU notifiers may still be waiting to be freed, using + * arm_smmu_mmu_notifier_free(). Wait for them. + */ + mmu_notifier_synchronize(); +} diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 0fd63d93bd2c..ad71c07e783f 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -71,6 +71,12 @@ struct arm_smmu_option_prop { DEFINE_XARRAY_ALLOC1(arm_smmu_asid_xa); DEFINE_MUTEX(arm_smmu_asid_lock); +/* + * Special value used by SVA when a process dies, to quiesce a CD without + * disabling it. + */ +struct arm_smmu_ctx_desc quiet_cd = { 0 }; + static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"}, @@ -86,11 +92,6 @@ static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset, return smmu->base + offset; } -static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) -{ - return container_of(dom, struct arm_smmu_domain, domain); -} - static void parse_driver_options(struct arm_smmu_device *smmu) { int i = 0; @@ -974,7 +975,9 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, * (2) Install a secondary CD, for SID+SSID traffic. * (3) Update ASID of a CD. Atomically write the first 64 bits of the * CD, then invalidate the old entry and mappings. - * (4) Remove a secondary CD. + * (4) Quiesce the context without clearing the valid bit. Disable + * translation, and ignore any translation fault. + * (5) Remove a secondary CD. */ u64 val; bool cd_live; @@ -991,8 +994,10 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, val = le64_to_cpu(cdptr[0]); cd_live = !!(val & CTXDESC_CD_0_V); - if (!cd) { /* (4) */ + if (!cd) { /* (5) */ val = 0; + } else if (cd == &quiet_cd) { /* (4) */ + val |= CTXDESC_CD_0_TCR_EPD0; } else if (cd_live) { /* (3) */ val &= ~CTXDESC_CD_0_ASID; val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid); @@ -1785,6 +1790,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) mutex_init(&smmu_domain->init_mutex); INIT_LIST_HEAD(&smmu_domain->devices); spin_lock_init(&smmu_domain->devices_lock); + INIT_LIST_HEAD(&smmu_domain->mmu_notifiers); return &smmu_domain->domain; } @@ -2576,6 +2582,9 @@ static struct iommu_ops arm_smmu_ops = { .dev_feat_enabled = arm_smmu_dev_feature_enabled, .dev_enable_feat = arm_smmu_dev_enable_feature, .dev_disable_feat = arm_smmu_dev_disable_feature, + .sva_bind = arm_smmu_sva_bind, + .sva_unbind = arm_smmu_sva_unbind, + .sva_get_pasid = arm_smmu_sva_get_pasid, .pgsize_bitmap = -1UL, /* Restricted during device attach */ }; @@ -3595,6 +3604,12 @@ static const struct of_device_id arm_smmu_of_match[] = { }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +static void arm_smmu_driver_unregister(struct platform_driver *drv) +{ + arm_smmu_sva_notifier_synchronize(); + platform_driver_unregister(drv); +} + static struct platform_driver arm_smmu_driver = { .driver = { .name = "arm-smmu-v3", @@ -3605,7 +3620,8 @@ static struct platform_driver arm_smmu_driver = { .remove = arm_smmu_device_remove, .shutdown = arm_smmu_device_shutdown, }; -module_platform_driver(arm_smmu_driver); +module_driver(arm_smmu_driver, platform_driver_register, + arm_smmu_driver_unregister); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); MODULE_AUTHOR("Will Deacon "); From patchwork Thu Jul 23 14:57:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 11681181 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 69F56722 for ; Thu, 23 Jul 2020 15:09:24 +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 41A4620771 for ; Thu, 23 Jul 2020 15:09:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="NmpJLKWL"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="mvhLrEgw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 41A4620771 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=HcOW/AXi2d1iMK+G/ji+8fdzj6cyAA/jdCOJe9lwygo=; b=NmpJLKWLWsUPqIspZXvXszu/M kkHdLm88zKuqhlXUl3Zg4LjZeJZjpvUUcOdOtTHVMhbyzYKInp68h5IDivi6k2R0rbhCIhkFrhuX6 N516z/rNjmbtWuUFsVhlZjY1v73v4p6UMhweikxxi5ABSuBA54/dEtRlXpms0606Dkg2YB4w8uW3s Q7Khf020MGx15xx8fyNUebuACfYrtaMawPp5YJq2gFRj3pCJTXPih2ZS67ojnOnrVA1Fk+FrF+Byu 9bDbuOibUcYMh15BDV/mfnEcmff8FUVBdft2Jmv0CN+9v6MzTOG3pcT3nSksH3H54zigFsERkCDzj OfFB/QQUw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycox-00034Q-VZ; Thu, 23 Jul 2020 15:07:44 +0000 Received: from mail-ej1-x641.google.com ([2a00:1450:4864:20::641]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jycnK-0002SO-Pl for linux-arm-kernel@lists.infradead.org; Thu, 23 Jul 2020 15:06:20 +0000 Received: by mail-ej1-x641.google.com with SMTP id n22so6752713ejy.3 for ; Thu, 23 Jul 2020 08:06:02 -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=S5AED+AmLuc340wZRBghHkZgD6fSHnG17Dhcvbb6LG8=; b=mvhLrEgwzR3iZucDURuIlZgKpouE3ax9X6RmoyEIoxJtpfKwhaFUyz1wyceDW/uD4V ANI1CA/B02+gizy2dXsrDVev6D5HIUj73+3SLV9QeevQaqnerDuNqQzp/o/4fKW4zUTw 6nOyVRFVtYTPloI13JUmCUVWK2zJ3GDyV078QkI9Uf2lU1Iiw9whqcq4eVhL2AZXOzoS 9sBcohXUxueKQP4XYT7gWYF1aHJCH/xhl9MwDkvrM44w1J4EGC11LxYWc8Jf7Ix+HsDX 47FqCavQPLPdjBxiiBP4Hq3P9zEB7rkZ7Z8T6vW3Oc5Oi61+iu8pM3ezm8msx0Mp/eWw EDRw== 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=S5AED+AmLuc340wZRBghHkZgD6fSHnG17Dhcvbb6LG8=; b=pTtCsx37KkmJvIIUg+RbPnJHIpJr1e/eA+yZ9k7es3Pj3RU+VYmtwLFGr77/RIuvTi JfKdueSe4gQGxqW/MIs59aRlxkHO299dbzHxjN+fsGiNcfJlWmPzYpWcm55a+pyxQAsb LtZvjGxdDEMx1PwvMi2TUESKycnSjFXPQUH8H0pL4u1Vk/dCld/wqMZ6SHGSZnR94dop D9McN8ujf7ES4K+QqrK+AtJGx5+63KMorcqYzikvMdlWdpU39eV6m6KxX7vzjw7sdiKH U+3QwKnG0bY+oNTOfxlGwgYCkDUiSCmCFs4q4JuS4XvKQLO6uaoIm/iHvBtf4q+qZrnp 8T0g== X-Gm-Message-State: AOAM533hJucVmVJt+tYsKnJqXsRQTFTS6KSjD+KG2kHfKbNH05imfrNl p4B8WibnRcEoR0kxkexnHswlyw== X-Google-Smtp-Source: ABdhPJyrN8twrBRM3dxZpKdtlRVWMv5PMVBDdBZ78Mz4WMqAp4xvT88XtwgShlREF2NsMPW+hYUiWg== X-Received: by 2002:a17:906:8608:: with SMTP id o8mr2836958ejx.156.1595516761662; Thu, 23 Jul 2020 08:06:01 -0700 (PDT) Received: from localhost.localdomain ([2001:1715:4e26:a7e0:116c:c27a:3e7f:5eaf]) by smtp.gmail.com with ESMTPSA id k15sm2145952eji.49.2020.07.23.08.06.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:06:00 -0700 (PDT) From: Jean-Philippe Brucker To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Subject: [PATCH v9 13/13] iommu/arm-smmu-v3: Hook up ATC invalidation to mm ops Date: Thu, 23 Jul 2020 16:57:25 +0200 Message-Id: <20200723145724.3014766-14-jean-philippe@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200723145724.3014766-1-jean-philippe@linaro.org> References: <20200723145724.3014766-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200723_110602_968249_DCB9BE69 X-CRM114-Status: GOOD ( 15.44 ) 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 [2a00:1450:4864:20:0:0:0:641 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 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: fenghua.yu@intel.com, jacob.jun.pan@linux.intel.com, Jean-Philippe Brucker , catalin.marinas@arm.com, joro@8bytes.org, robin.murphy@arm.com, hch@infradead.org, zhengxiang9@huawei.com, Jonathan.Cameron@huawei.com, zhangfei.gao@linaro.org, will@kernel.org, xuzaibo@huawei.com, baolu.lu@linux.intel.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The invalidate_range() notifier is called for any change to the address space. Perform the required ATC invalidations. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm-smmu-v3.h | 2 ++ drivers/iommu/arm-smmu-v3-sva.c | 16 +++++++++++++++- drivers/iommu/arm-smmu-v3.c | 18 ++++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.h b/drivers/iommu/arm-smmu-v3.h index 6365c81a4614..baa80498ad9f 100644 --- a/drivers/iommu/arm-smmu-v3.h +++ b/drivers/iommu/arm-smmu-v3.h @@ -694,6 +694,8 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, struct arm_smmu_ctx_desc *cd); void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid); bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); +int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid, + unsigned long iova, size_t size); #ifdef CONFIG_ARM_SMMU_V3_SVA bool arm_smmu_sva_supported(struct arm_smmu_device *smmu); diff --git a/drivers/iommu/arm-smmu-v3-sva.c b/drivers/iommu/arm-smmu-v3-sva.c index a77abbb7a9d7..1ed6b92b2c72 100644 --- a/drivers/iommu/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm-smmu-v3-sva.c @@ -178,6 +178,16 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) } } +static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn, + struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); + + arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start, + end - start + 1); +} + static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) { struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); @@ -196,6 +206,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, &quiet_cd); arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid); + arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0); smmu_mn->cleared = true; mutex_unlock(&sva_lock); @@ -207,6 +218,7 @@ static void arm_smmu_mmu_notifier_free(struct mmu_notifier *mn) } static struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { + .invalidate_range = arm_smmu_mm_invalidate_range, .release = arm_smmu_mm_release, .free_notifier = arm_smmu_mmu_notifier_free, }; @@ -279,8 +291,10 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) * If we went through clear(), we've already invalidated, and no * new TLB entry can have been formed. */ - if (!smmu_mn->cleared) + if (!smmu_mn->cleared) { arm_smmu_tlb_inv_asid(smmu_domain->smmu, cd->asid); + arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0); + } /* Frees smmu_mn */ mmu_notifier_put(&smmu_mn->mn); diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index ad71c07e783f..89efa9db7869 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1515,6 +1515,20 @@ arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, size_t size, size_t inval_grain_shift = 12; unsigned long page_start, page_end; + /* + * ATS and PASID: + * + * If substream_valid is clear, the PCIe TLP is sent without a PASID + * prefix. In that case all ATC entries within the address range are + * invalidated, including those that were requested with a PASID! There + * is no way to invalidate only entries without PASID. + * + * When using STRTAB_STE_1_S1DSS_SSID0 (reserving CD 0 for non-PASID + * traffic), translation requests without PASID create ATC entries + * without PASID, which must be invalidated with substream_valid clear. + * This has the unpleasant side-effect of invalidating all PASID-tagged + * ATC entries within the address range. + */ *cmd = (struct arm_smmu_cmdq_ent) { .opcode = CMDQ_OP_ATC_INV, .substream_valid = !!ssid, @@ -1573,8 +1587,8 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master *master) return arm_smmu_cmdq_issue_sync(master->smmu); } -static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, - int ssid, unsigned long iova, size_t size) +int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid, + unsigned long iova, size_t size) { int i; unsigned long flags;