Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp9952326rwd; Wed, 21 Jun 2023 14:12:04 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5ZOXtU4KiOLklo4S5tMogVojgTBM8VMqefNcCyOn+kC/QmFMtqfMqwjyroFA7p5/wOHzdx X-Received: by 2002:a05:6a20:72a3:b0:121:6f57:8fb9 with SMTP id o35-20020a056a2072a300b001216f578fb9mr7735292pzk.58.1687381924125; Wed, 21 Jun 2023 14:12:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1687381924; cv=none; d=google.com; s=arc-20160816; b=MrQdxosZ9fOyHadj4r28ibS7jLYmGRiesa9HlKIK7gKZSvGCrDnXIReZEh0qxtmPkK bL0bFcYs22lIhw1tcWXFrCsMXMoX23FzxNVL0K7m6NJ+w/7WxKJWiPmfYTNQcX8sfbsP NaoHfzX5ezc+YQqjS2MhZ8ghQ00nGZrzBpqTRm/cXFmUeePLrqAqtiCDy0HdFd9EWsti nipWDrBaTEIywXhuFtjwRkLGhHYDJV3gnLRNtp2miSnFkCrJ8fAyYvmKYzc++OHPOldV 0cVqjxB0ULM301NngRd+KEFcQ4FZKr5aLlJvwbNNI8+y1sdtrsVS5hDFvbVAArfjYKkI u6Vg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=85tzoPSMFXV/Ts5NUbDMbEV5urwkuCHM1iZzONgMWko=; b=WS0/j+EVTA6o5WMNQEj2ZSar9hIhvCYnSeMSESaNOCaqEKN5qG9IIC7+HhMkO3AR7B ByCnSASHnNvB1DvVku5awjKHzFC6GH6gUsXlQeC0AGnQ7n7E6wTvw57NJMmIsNiLte8k j6GBsOBMeTCN8rZG/OuODOfgb6y0KBcqlpI4hkzPlLZ5mji1JzkusRd2ueDKsfWA56Xd rnmGxDD/k1u09vEpa9Zyzu5IwqsfUpSE04UR5d/p/2fb75vh6XpB3qC0TYrdMGy6YCM6 n+V/vFQQLLskdzEjWpS692QSLHPGcnX7CCBa+QyETMaBzfaslThi6dIm2/huydm1Nyzm 90ww== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Sdt6qrN2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ld11-20020a170902facb00b001b465c3ca56si1991513plb.148.2023.06.21.14.11.50; Wed, 21 Jun 2023 14:12:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Sdt6qrN2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229814AbjFUUzP (ORCPT + 99 others); Wed, 21 Jun 2023 16:55:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230246AbjFUUzI (ORCPT ); Wed, 21 Jun 2023 16:55:08 -0400 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5B5519C; Wed, 21 Jun 2023 13:55:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687380907; x=1718916907; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4ZLNWA9lbj3RPDCkZaIcBniRXsCD3rLw+gS6G1GEZhI=; b=Sdt6qrN26BL9Z8d50uU7VS1RZfPNlY5ytfl7psdDfEg1IuV95mtAb4FX ZB1bR7KNw59E5AtDaviqE93hUxnlZv1yJ8eob0j5nf60YUCX1UtpllyFy P0r/jxqAdbdh898m94t6kopNpCPfJPpC3UkuH1TJYlGY4zxXMw2n5+zOO 5St9nl35egQFXjbNmgV6bENmeviklVrFIit97yp0i1nKVmUSqtK8PsaJx JvJoTcMA1Gmhvy6aMQZ//lvVBBDMHWkKKZS6fI/XmL6Qvy+u1Hxq2euPX BFtpfb4YAqlHMGTxGN+ZQfDAukfHF98QOzIwwEPs7d90epNepLW+A9vMx w==; X-IronPort-AV: E=McAfee;i="6600,9927,10748"; a="359168908" X-IronPort-AV: E=Sophos;i="6.00,261,1681196400"; d="scan'208";a="359168908" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jun 2023 13:55:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10748"; a="827597900" X-IronPort-AV: E=Sophos;i="6.00,261,1681196400"; d="scan'208";a="827597900" Received: from srinivas-otcpl-7600.jf.intel.com (HELO jacob-builder.jf.intel.com) ([10.54.97.184]) by fmsmga002.fm.intel.com with ESMTP; 21 Jun 2023 13:55:04 -0700 From: Jacob Pan To: LKML , iommu@lists.linux.dev, Jason Gunthorpe , "Lu Baolu" , Joerg Roedel , "Robin Murphy" , Jean-Philippe Brucker , dmaengine@vger.kernel.org, vkoul@kernel.org Cc: "Will Deacon" , David Woodhouse , Raj Ashok , "Tian, Kevin" , Yi Liu , "Yu, Fenghua" , Dave Jiang , Tony Luck , "Zanussi, Tom" , rex.zhang@intel.com, xiaochen.shen@intel.com, narayan.ranganathan@intel.com, Jacob Pan Subject: [PATCH v9 2/7] iommu: Move global PASID allocation from SVA to core Date: Wed, 21 Jun 2023 13:59:42 -0700 Message-Id: <20230621205947.1327094-3-jacob.jun.pan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230621205947.1327094-1-jacob.jun.pan@linux.intel.com> References: <20230621205947.1327094-1-jacob.jun.pan@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_NONE,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Global PASID can be used beyond SVA. For example, drivers that use Intel ENQCMD to submit work must use global PASIDs in that PASID is stored in a per CPU MSR. When such device need to submit work for in-kernel DMA with PASID, it must allocate PASIDs from the same global number space to avoid conflict. This patch moves global PASID allocation APIs from SVA to IOMMU APIs. Reserved PASIDs, currently only RID_PASID, are excluded from the global PASID allocation. It is expected that device drivers will use the allocated PASIDs to attach to appropriate IOMMU domains for use. Reviewed-by: Lu Baolu Reviewed-by: Kevin Tian Signed-off-by: Jacob Pan --- v8: fix off-by-one in max_pasid check v7: simplify range check (Baolu) v6: explicitly exclude reserved a range from SVA PASID allocation check mm PASID compatibility with device v5: move PASID range check inside API so that device drivers only pass in struct device* (Kevin) v4: move dummy functions outside ifdef CONFIG_IOMMU_SVA (Baolu) --- drivers/iommu/iommu-sva.c | 28 ++++++++++------------------ drivers/iommu/iommu.c | 28 ++++++++++++++++++++++++++++ include/linux/iommu.h | 10 ++++++++++ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index 9821bc44f5ac..b033cc415a00 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -10,33 +10,30 @@ #include "iommu-sva.h" static DEFINE_MUTEX(iommu_sva_lock); -static DEFINE_IDA(iommu_global_pasid_ida); /* Allocate a PASID for the mm within range (inclusive) */ -static int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) +static int iommu_sva_alloc_pasid(struct mm_struct *mm, struct device *dev) { + ioasid_t pasid; int ret = 0; - if (min == IOMMU_PASID_INVALID || - max == IOMMU_PASID_INVALID || - min == 0 || max < min) - return -EINVAL; - if (!arch_pgtable_dma_compat(mm)) return -EBUSY; mutex_lock(&iommu_sva_lock); /* Is a PASID already associated with this mm? */ if (mm_valid_pasid(mm)) { - if (mm->pasid < min || mm->pasid > max) + if (mm->pasid >= dev->iommu->max_pasids) ret = -EOVERFLOW; goto out; } - ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL); - if (ret < min) + pasid = iommu_alloc_global_pasid_dev(dev); + if (pasid == IOMMU_PASID_INVALID) { + ret = -ENOSPC; goto out; - mm->pasid = ret; + } + mm->pasid = pasid; ret = 0; out: mutex_unlock(&iommu_sva_lock); @@ -63,15 +60,10 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm { struct iommu_domain *domain; struct iommu_sva *handle; - ioasid_t max_pasids; int ret; - max_pasids = dev->iommu->max_pasids; - if (!max_pasids) - return ERR_PTR(-EOPNOTSUPP); - /* Allocate mm->pasid if necessary. */ - ret = iommu_sva_alloc_pasid(mm, 1, max_pasids - 1); + ret = iommu_sva_alloc_pasid(mm, dev); if (ret) return ERR_PTR(ret); @@ -216,5 +208,5 @@ void mm_pasid_drop(struct mm_struct *mm) if (likely(!mm_valid_pasid(mm))) return; - ida_free(&iommu_global_pasid_ida, mm->pasid); + iommu_free_global_pasid(mm->pasid); } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index f1dcfa3f1a1b..d4f9ab210d6b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -39,6 +39,7 @@ static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); +static DEFINE_IDA(iommu_global_pasid_ida); static unsigned int iommu_def_domain_type __read_mostly; static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT); @@ -3393,3 +3394,30 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev, return domain; } + +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) +{ + int ret; + ioasid_t max; + + max = dev->iommu->max_pasids; + /* + * max_pasids is set up by vendor driver based on number of PASID bits + * supported but the IDA allocation is inclusive. + */ + ret = ida_alloc_range(&iommu_global_pasid_ida, IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); + if (ret < 0) + return IOMMU_PASID_INVALID; + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); + +void iommu_free_global_pasid(ioasid_t pasid) +{ + if (WARN_ON(pasid == IOMMU_PASID_INVALID)) + return; + + ida_free(&iommu_global_pasid_ida, pasid); +} +EXPORT_SYMBOL_GPL(iommu_free_global_pasid); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index c714d659d114..f7bfe03bda19 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -191,6 +191,7 @@ enum iommu_dev_features { }; #define IOMMU_NO_PASID (0U) /* Reserved for DMA w/o PASID */ +#define IOMMU_FIRST_GLOBAL_PASID (1U) /*starting range for allocation */ #define IOMMU_PASID_INVALID (-1U) typedef unsigned int ioasid_t; @@ -722,6 +723,8 @@ void iommu_detach_device_pasid(struct iommu_domain *domain, struct iommu_domain * iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid, unsigned int type); +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev); +void iommu_free_global_pasid(ioasid_t pasid); #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -1083,6 +1086,13 @@ iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid, { return NULL; } + +static inline ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) +{ + return IOMMU_PASID_INVALID; +} + +static inline void iommu_free_global_pasid(ioasid_t pasid) {} #endif /* CONFIG_IOMMU_API */ /** -- 2.25.1