From nobody Sun Apr 26 10:50:24 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96B2DC43334 for ; Wed, 29 Jun 2022 07:52:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232042AbiF2Hv6 (ORCPT ); Wed, 29 Jun 2022 03:51:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36284 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231194AbiF2Hvz (ORCPT ); Wed, 29 Jun 2022 03:51:55 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4EC8134645 for ; Wed, 29 Jun 2022 00:51:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489114; x=1688025114; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+H3iqUVrNt1aGjueQ2PCPg/gSRm34eU6k9Nmq35zT4I=; b=K4tRYidevQR5KQ3noedBNLpVSzXNOJhjZTmVvCW9q4mdDrw0ZnQxbpV4 96r15ZOogWOjZMjGumHJ91mYy8zg7M6yfFCV5PsXvKHYEcFLCHB7+RCAI RZulqfE8zetsCSQmV2L8i/iAAHnNa+xGdw3A8K3QiCxf5EJUpKcJ/IJJP db8JkBsvd4vvYwKDPEweUVcjjZT/KIDHfKuHP1KNYTSXq3I2oy+qgdJed 3YQLMUYthat/P5NK9Dl6hrW7jRpXjiVeDCels9hrDZgaNoQR59XxHnC8R gR5TQO5Q4lRFRqlYLjPXJHH30n6RQ4Yvul6jVpP+O1MD5vFNTgkTbp1dr A==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719364" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719364" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:51:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209580" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:51:51 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 01/11] iommu/vt-d: debugfs: Remove device_domain_lock usage Date: Wed, 29 Jun 2022 15:47:15 +0800 Message-Id: <20220629074725.2331441-2-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The domain_translation_struct debugfs node is used to dump the DMAR page tables for the PCI devices. It potentially races with setting domains to devices. The existing code uses the global spinlock device_domain_lock to avoid the races. This removes the use of device_domain_lock outside of iommu.c by replacing it with the group mutex lock. Using the group mutex lock is cleaner and more compatible to following cleanups. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.h | 1 - drivers/iommu/intel/debugfs.c | 43 +++++++++++++++++++++++++---------- drivers/iommu/intel/iommu.c | 2 +- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 8285fcfa5fea..8deb745d8b36 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -480,7 +480,6 @@ enum { #define VTD_FLAG_SVM_CAPABLE (1 << 2) =20 extern int intel_iommu_sm; -extern spinlock_t device_domain_lock; =20 #define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap)) #define pasid_supported(iommu) (sm_supported(iommu) && \ diff --git a/drivers/iommu/intel/debugfs.c b/drivers/iommu/intel/debugfs.c index d927ef10641b..6e1a3f88abc8 100644 --- a/drivers/iommu/intel/debugfs.c +++ b/drivers/iommu/intel/debugfs.c @@ -342,13 +342,13 @@ static void pgtable_walk_level(struct seq_file *m, st= ruct dma_pte *pde, } } =20 -static int show_device_domain_translation(struct device *dev, void *data) +static int __show_device_domain_translation(struct device *dev, void *data) { - struct device_domain_info *info =3D dev_iommu_priv_get(dev); - struct dmar_domain *domain =3D info->domain; + struct dmar_domain *domain; struct seq_file *m =3D data; u64 path[6] =3D { 0 }; =20 + domain =3D to_dmar_domain(iommu_get_domain_for_dev(dev)); if (!domain) return 0; =20 @@ -359,20 +359,39 @@ static int show_device_domain_translation(struct devi= ce *dev, void *data) pgtable_walk_level(m, domain->pgd, domain->agaw + 2, 0, path); seq_putc(m, '\n'); =20 - return 0; + /* Don't iterate */ + return 1; } =20 -static int domain_translation_struct_show(struct seq_file *m, void *unused) +static int show_device_domain_translation(struct device *dev, void *data) { - unsigned long flags; - int ret; + struct iommu_group *group; =20 - spin_lock_irqsave(&device_domain_lock, flags); - ret =3D bus_for_each_dev(&pci_bus_type, NULL, m, - show_device_domain_translation); - spin_unlock_irqrestore(&device_domain_lock, flags); + group =3D iommu_group_get(dev); + if (group) { + /* + * The group->mutex is held across the callback, which will + * block calls to iommu_attach/detach_group/device. Hence, + * the domain of the device will not change during traversal. + * + * All devices in an iommu group share a single domain, hence + * we only dump the domain of the first device. Even though, + * this code still possibly races with the iommu_unmap() + * interface. This could be solved by RCU-freeing the page + * table pages in the iommu_unmap() path. + */ + iommu_group_for_each_dev(group, data, + __show_device_domain_translation); + iommu_group_put(group); + } =20 - return ret; + return 0; +} + +static int domain_translation_struct_show(struct seq_file *m, void *unused) +{ + return bus_for_each_dev(&pci_bus_type, NULL, m, + show_device_domain_translation); } DEFINE_SHOW_ATTRIBUTE(domain_translation_struct); =20 diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 10bda4bec8fe..3b6571681bdd 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -314,7 +314,7 @@ static int iommu_skip_te_disable; #define IDENTMAP_GFX 2 #define IDENTMAP_AZALIA 4 =20 -DEFINE_SPINLOCK(device_domain_lock); +static DEFINE_SPINLOCK(device_domain_lock); static LIST_HEAD(device_domain_list); =20 const struct iommu_ops intel_iommu_ops; --=20 2.25.1 From nobody Sun Apr 26 10:50:24 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 685A8C433EF for ; Wed, 29 Jun 2022 07:52:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232487AbiF2HwC (ORCPT ); Wed, 29 Jun 2022 03:52:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230514AbiF2Hv5 (ORCPT ); Wed, 29 Jun 2022 03:51:57 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80AD625C46 for ; Wed, 29 Jun 2022 00:51:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489116; x=1688025116; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hkGm7YDPu5xil+VGf8bn6+rNMEI6Bw40A3ib6a6DFDY=; b=Ijr7Jg3BrD3Sb0WiVl9c2J+tp40WyAJD3zFc7OUh8e5FEzneSVVzNSgB vVXtmLZEJxwji5D46FgFY4rot3AOzm6sVfjICD5SCwpOCf4MXgFqwK3ft K/wHVuwPNQaBb+L2ebpyLPI2NIV52Z6PPsBEQPUMT94N2IuJvj0wICuwc XtslxF0BouNO8DlZ6rE2n46m51MBXXMSL8gvVciepvetUD34neEEFfmEB 2pwrB+9tjeTYD3L7LdSy9bHrlaZMLcH9lQOz7CvtQrDn11+AISh2lejXR r5xd1vxzIV0m5+kx5Q3yMUjvZJb5e+8n9BvA9oB9Hc16PHlthEDzZ95x5 g==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719369" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719369" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:51:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209588" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:51:54 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 02/11] iommu/vt-d: Remove clearing translation data in disable_dmar_iommu() Date: Wed, 29 Jun 2022 15:47:16 +0800 Message-Id: <20220629074725.2331441-3-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The disable_dmar_iommu() is called when IOMMU initialization fails or the IOMMU is hot-removed from the system. In both cases, there is no need to clear the IOMMU translation data structures for devices. On the initialization path, the device probing only happens after the IOMMU is initialized successfully, hence there're no translation data structures. On the hot-remove path, there is no real use case where the IOMMU is hot-removed, but the devices that it manages are still alive in the system. The translation data structures were torn down during device release, hence there's no need to repeat it in IOMMU hot-remove path either. This removes the unnecessary code and only leaves a check. Signed-off-by: Lu Baolu --- drivers/iommu/intel/pasid.h | 1 + drivers/iommu/intel/iommu.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h index bf5b937848b4..20c54e50f533 100644 --- a/drivers/iommu/intel/pasid.h +++ b/drivers/iommu/intel/pasid.h @@ -39,6 +39,7 @@ * only and pass-through transfer modes. */ #define FLPT_DEFAULT_DID 1 +#define NUM_RESERVED_DID 2 =20 /* * The SUPERVISOR_MODE flag indicates a first level translation which diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 3b6571681bdd..43aaec5bdd84 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1716,23 +1716,16 @@ static int iommu_init_domains(struct intel_iommu *i= ommu) =20 static void disable_dmar_iommu(struct intel_iommu *iommu) { - struct device_domain_info *info, *tmp; - unsigned long flags; - if (!iommu->domain_ids) return; =20 - spin_lock_irqsave(&device_domain_lock, flags); - list_for_each_entry_safe(info, tmp, &device_domain_list, global) { - if (info->iommu !=3D iommu) - continue; - - if (!info->dev || !info->domain) - continue; - - __dmar_remove_one_dev_info(info); - } - spin_unlock_irqrestore(&device_domain_lock, flags); + /* + * All iommu domains must have been detached from the devices, + * hence there should be no domain IDs in use. + */ + if (WARN_ON(bitmap_weight(iommu->domain_ids, cap_ndoms(iommu->cap)) + > NUM_RESERVED_DID)) + return; =20 if (iommu->gcmd & DMA_GCMD_TE) iommu_disable_translation(iommu); --=20 2.25.1 From nobody Sun Apr 26 10:50:24 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E39BC43334 for ; Wed, 29 Jun 2022 07:52:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230201AbiF2HwF (ORCPT ); Wed, 29 Jun 2022 03:52:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36356 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232211AbiF2Hv7 (ORCPT ); Wed, 29 Jun 2022 03:51:59 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C286E37037 for ; Wed, 29 Jun 2022 00:51:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489118; x=1688025118; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=d3apr3bU9mf+okAIPMYSp8s/p9GHpJYjT6FHqDZj33g=; b=OliTqLGf2OPztSig2dVe/TjFPJNHK2Brf63nsM5OoZ1CVxVv6aaSo6aW 1NXyI2nWh3zUpwtY5aJ6dqJ4jPugEObFOxyYYrFzbv7/8jdP6x++HKt2K AvLl3UJ4btrPavXj2qzlXcHCbtePfxOZa1h5rCQN5oT/EyfSLlk6nD81M 2odf/QS01bWtPEqHaNJ8ZWQxOpTKVRiWzXOrgFYNJ4bntR/meOdpR4kG8 2fXE00BLHeD46x9MRcWYo0sPqdh6Kbxw1uBrTEMRhLawevg91zZHQHU/i +dVFrkhSII7x8hvBefX/XCPW91mKbWHLawAJ4Vdnq90C7UYrO20btvJjf A==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719381" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719381" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:51:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209610" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:51:56 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu , Jason Gunthorpe Subject: [PATCH v3 03/11] iommu/vt-d: Use pci_get_domain_bus_and_slot() in pgtable_walk() Date: Wed, 29 Jun 2022 15:47:17 +0800 Message-Id: <20220629074725.2331441-4-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Use pci_get_domain_bus_and_slot() instead of searching the global list to retrieve the pci device pointer. This also removes the global device_domain_list as there isn't any consumer anymore. Signed-off-by: Lu Baolu Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.h | 1 - drivers/iommu/intel/iommu.c | 34 ++++++---------------------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 8deb745d8b36..198c6c822ef4 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -609,7 +609,6 @@ struct intel_iommu { /* PCI domain-device relationship */ struct device_domain_info { struct list_head link; /* link to domain siblings */ - struct list_head global; /* link to global list */ u32 segment; /* PCI segment number */ u8 bus; /* PCI bus number */ u8 devfn; /* PCI devfn number */ diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 43aaec5bdd84..77915d61f7ec 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -131,8 +131,6 @@ static struct intel_iommu **g_iommus; =20 static void __init check_tylersburg_isoch(void); static int rwbf_quirk; -static inline struct device_domain_info * -dmar_search_domain_by_dev_info(int segment, int bus, int devfn); =20 /* * set to 1 to panic kernel if can't successfully enable VT-d @@ -315,8 +313,6 @@ static int iommu_skip_te_disable; #define IDENTMAP_AZALIA 4 =20 static DEFINE_SPINLOCK(device_domain_lock); -static LIST_HEAD(device_domain_list); - const struct iommu_ops intel_iommu_ops; =20 static bool translation_pre_enabled(struct intel_iommu *iommu) @@ -846,9 +842,14 @@ static void pgtable_walk(struct intel_iommu *iommu, un= signed long pfn, u8 bus, u struct device_domain_info *info; struct dma_pte *parent, *pte; struct dmar_domain *domain; + struct pci_dev *pdev; int offset, level; =20 - info =3D dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); + pdev =3D pci_get_domain_bus_and_slot(iommu->segment, bus, devfn); + if (!pdev) + return; + + info =3D dev_iommu_priv_get(&pdev->dev); if (!info || !info->domain) { pr_info("device [%02x:%02x.%d] not probed\n", bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); @@ -2357,19 +2358,6 @@ static void domain_remove_dev_info(struct dmar_domai= n *domain) spin_unlock_irqrestore(&device_domain_lock, flags); } =20 -static inline struct device_domain_info * -dmar_search_domain_by_dev_info(int segment, int bus, int devfn) -{ - struct device_domain_info *info; - - list_for_each_entry(info, &device_domain_list, global) - if (info->segment =3D=3D segment && info->bus =3D=3D bus && - info->devfn =3D=3D devfn) - return info; - - return NULL; -} - static int domain_setup_first_level(struct intel_iommu *iommu, struct dmar_domain *domain, struct device *dev, @@ -4573,7 +4561,6 @@ static struct iommu_device *intel_iommu_probe_device(= struct device *dev) struct pci_dev *pdev =3D dev_is_pci(dev) ? to_pci_dev(dev) : NULL; struct device_domain_info *info; struct intel_iommu *iommu; - unsigned long flags; u8 bus, devfn; =20 iommu =3D device_to_iommu(dev, &bus, &devfn); @@ -4616,10 +4603,7 @@ static struct iommu_device *intel_iommu_probe_device= (struct device *dev) } } =20 - spin_lock_irqsave(&device_domain_lock, flags); - list_add(&info->global, &device_domain_list); dev_iommu_priv_set(dev, info); - spin_unlock_irqrestore(&device_domain_lock, flags); =20 return &iommu->iommu; } @@ -4627,15 +4611,9 @@ static struct iommu_device *intel_iommu_probe_device= (struct device *dev) static void intel_iommu_release_device(struct device *dev) { struct device_domain_info *info =3D dev_iommu_priv_get(dev); - unsigned long flags; =20 dmar_remove_one_dev_info(dev); - - spin_lock_irqsave(&device_domain_lock, flags); dev_iommu_priv_set(dev, NULL); - list_del(&info->global); - spin_unlock_irqrestore(&device_domain_lock, flags); - kfree(info); set_dma_ops(dev, NULL); } --=20 2.25.1 From nobody Sun Apr 26 10:50:24 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93AACC433EF for ; Wed, 29 Jun 2022 07:52:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232516AbiF2HwK (ORCPT ); Wed, 29 Jun 2022 03:52:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232477AbiF2HwB (ORCPT ); Wed, 29 Jun 2022 03:52:01 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF95A3915F for ; Wed, 29 Jun 2022 00:52:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489120; x=1688025120; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1CTKfefQ/h6z94Nvf/sEonitLTLnAFkKkQpkqf1GosQ=; b=hAUPUIa/ksNXS/I6IiYZVvglnQCZ90PhI/VF3MpmF+J0GSAQ2Nu8q+Il 3gZ/CpMchwLke6hAkAYeXBLPBp/i9jdco2+VLg6bFT+Ac/mdU8w5IdvVF DVTvlM8W0vuw/3kkV4d6rbrTqJOC66vOD6DxWhkm/RTXgR4aTXBToYUqR M4vXBawTKOqHZwRrb8tCghXuMt4gT2Ny8Fj5mrZbOTAWh6tJHluFokm4k gAh1DWu3XDSiY8v4pq5O+XCiRyuwnWKqS5gajSTopu+FhUdYcvbx/Razu DdobrMNeq4eqQ9AaYm8irfGabNKzM9ezNItiu118YQNy494AZlWHoUf7R Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719387" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719387" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209622" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:51:58 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 04/11] iommu/vt-d: Unnecessary spinlock for root table alloc and free Date: Wed, 29 Jun 2022 15:47:18 +0800 Message-Id: <20220629074725.2331441-5-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The IOMMU root table is allocated and freed in the IOMMU initialization code in static boot or hot-remove paths. There's no need for a spinlock. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 77915d61f7ec..ff49c9460ede 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -809,14 +809,12 @@ static int device_context_mapped(struct intel_iommu *= iommu, u8 bus, u8 devfn) =20 static void free_context_table(struct intel_iommu *iommu) { - int i; - unsigned long flags; struct context_entry *context; + int i; + + if (!iommu->root_entry) + return; =20 - spin_lock_irqsave(&iommu->lock, flags); - if (!iommu->root_entry) { - goto out; - } for (i =3D 0; i < ROOT_ENTRY_NR; i++) { context =3D iommu_context_addr(iommu, i, 0, 0); if (context) @@ -828,12 +826,10 @@ static void free_context_table(struct intel_iommu *io= mmu) context =3D iommu_context_addr(iommu, i, 0x80, 0); if (context) free_pgtable_page(context); - } + free_pgtable_page(iommu->root_entry); iommu->root_entry =3D NULL; -out: - spin_unlock_irqrestore(&iommu->lock, flags); } =20 #ifdef CONFIG_DMAR_DEBUG @@ -1232,7 +1228,6 @@ static void domain_unmap(struct dmar_domain *domain, = unsigned long start_pfn, static int iommu_alloc_root_entry(struct intel_iommu *iommu) { struct root_entry *root; - unsigned long flags; =20 root =3D (struct root_entry *)alloc_pgtable_page(iommu->node); if (!root) { @@ -1242,10 +1237,7 @@ static int iommu_alloc_root_entry(struct intel_iommu= *iommu) } =20 __iommu_flush_cache(iommu, root, ROOT_SIZE); - - spin_lock_irqsave(&iommu->lock, flags); iommu->root_entry =3D root; - spin_unlock_irqrestore(&iommu->lock, flags); =20 return 0; } --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DDBCEC433EF for ; Wed, 29 Jun 2022 07:52:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232505AbiF2HwP (ORCPT ); Wed, 29 Jun 2022 03:52:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231194AbiF2HwE (ORCPT ); Wed, 29 Jun 2022 03:52:04 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35A1A38DBE for ; Wed, 29 Jun 2022 00:52:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489123; x=1688025123; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7xJG/RHuTiPYTwDACaNvM5KqLLJ+9JGGZJR7/2WHQCo=; b=ZSn1Dz1lpgaC7QzAOqYYfcd7ppTcHnENZH8+piLDu7MK+nh7c9IqoAnB 12FRp5ihcXFdseWMtheQ8gE6bPHwpgB/DuRnJDAQVwjt8a1QvRsLc87C9 Kv6BbOUAk8wQr5qnK8QeI5APrx7J2PPx+4oeDISz4ot808AvZmwesq22i eI/RFuwXhdJN1frNxx5HZPfbpZAwHJZz6u/6DegEKp8bwNUM33+zX8W50 PVMKihYA54Zkfrc7gpKWMGRHTtXgwZ5yeJoqRTbQh9QFsiOgKU22WXz5q PDyM7E02F+ffogbC8rhresprUtKurRnq37VxB9pIQ0PL9EthZ/sg270a+ A==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719406" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719406" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209637" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:00 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 05/11] iommu/vt-d: Replace spin_lock_irqsave() with spin_lock() Date: Wed, 29 Jun 2022 15:47:19 +0800 Message-Id: <20220629074725.2331441-6-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The iommu->lock is used to protect changes in root/context/pasid tables and domain ID allocation. There's no use case to change these resources in any interrupt context. Therefore, it's unnecessary to disable the interrupts when the spinlock is held. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/debugfs.c | 6 ++---- drivers/iommu/intel/iommu.c | 26 +++++++++++--------------- drivers/iommu/intel/svm.c | 6 +++--- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/iommu/intel/debugfs.c b/drivers/iommu/intel/debugfs.c index 6e1a3f88abc8..1f925285104e 100644 --- a/drivers/iommu/intel/debugfs.c +++ b/drivers/iommu/intel/debugfs.c @@ -263,10 +263,9 @@ static void ctx_tbl_walk(struct seq_file *m, struct in= tel_iommu *iommu, u16 bus) =20 static void root_tbl_walk(struct seq_file *m, struct intel_iommu *iommu) { - unsigned long flags; u16 bus; =20 - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); seq_printf(m, "IOMMU %s: Root Table Address: 0x%llx\n", iommu->name, (u64)virt_to_phys(iommu->root_entry)); seq_puts(m, "B.D.F\tRoot_entry\t\t\t\tContext_entry\t\t\t\tPASID\tPASID_t= able_entry\n"); @@ -278,8 +277,7 @@ static void root_tbl_walk(struct seq_file *m, struct in= tel_iommu *iommu) */ for (bus =3D 0; bus < 256; bus++) ctx_tbl_walk(m, iommu, bus); - - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); } =20 static int dmar_translation_struct_show(struct seq_file *m, void *unused) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ff49c9460ede..a81bdddf1091 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -797,13 +797,12 @@ static int device_context_mapped(struct intel_iommu *= iommu, u8 bus, u8 devfn) { struct context_entry *context; int ret =3D 0; - unsigned long flags; =20 - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); context =3D iommu_context_addr(iommu, bus, devfn, 0); if (context) ret =3D context_present(context); - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); return ret; } =20 @@ -2296,16 +2295,15 @@ static void domain_context_clear_one(struct device_= domain_info *info, u8 bus, u8 { struct intel_iommu *iommu =3D info->iommu; struct context_entry *context; - unsigned long flags; u16 did_old; =20 if (!iommu) return; =20 - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); context =3D iommu_context_addr(iommu, bus, devfn, 0); if (!context) { - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); return; } =20 @@ -2320,7 +2318,7 @@ static void domain_context_clear_one(struct device_do= main_info *info, u8 bus, u8 =20 context_clear_entry(context); __iommu_flush_cache(iommu, context, sizeof(*context)); - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); iommu->flush.flush_context(iommu, did_old, (((u16)bus) << 8) | devfn, @@ -2499,7 +2497,7 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) } =20 /* Setup the PASID entry for requests without PASID: */ - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); if (hw_pass_through && domain_type_is_si(domain)) ret =3D intel_pasid_setup_pass_through(iommu, domain, dev, PASID_RID2PASID); @@ -2509,7 +2507,7 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) else ret =3D intel_pasid_setup_second_level(iommu, domain, dev, PASID_RID2PASID); - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); if (ret) { dev_err(dev, "Setup RID2PASID failed\n"); dmar_remove_one_dev_info(dev); @@ -2777,7 +2775,6 @@ static int copy_translation_tables(struct intel_iommu= *iommu) struct root_entry *old_rt; phys_addr_t old_rt_phys; int ctxt_table_entries; - unsigned long flags; u64 rtaddr_reg; int bus, ret; bool new_ext, ext; @@ -2820,7 +2817,7 @@ static int copy_translation_tables(struct intel_iommu= *iommu) } } =20 - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); =20 /* Context tables are copied, now write them to the root_entry table */ for (bus =3D 0; bus < 256; bus++) { @@ -2839,7 +2836,7 @@ static int copy_translation_tables(struct intel_iommu= *iommu) iommu->root_entry[bus].hi =3D val; } =20 - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); =20 kfree(ctxt_tbls); =20 @@ -4166,7 +4163,6 @@ static void __dmar_remove_one_dev_info(struct device_= domain_info *info) { struct dmar_domain *domain; struct intel_iommu *iommu; - unsigned long flags; =20 assert_spin_locked(&device_domain_lock); =20 @@ -4188,9 +4184,9 @@ static void __dmar_remove_one_dev_info(struct device_= domain_info *info) =20 list_del(&info->link); =20 - spin_lock_irqsave(&iommu->lock, flags); + spin_lock(&iommu->lock); domain_detach_iommu(domain, iommu); - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock(&iommu->lock); } =20 static void dmar_remove_one_dev_info(struct device *dev) diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index 580713aa9e07..82288a50660d 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -328,9 +328,9 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel= _iommu *iommu, unsigned int flags) { struct device_domain_info *info =3D dev_iommu_priv_get(dev); - unsigned long iflags, sflags; struct intel_svm_dev *sdev; struct intel_svm *svm; + unsigned long sflags; int ret =3D 0; =20 svm =3D pasid_private_find(mm->pasid); @@ -394,10 +394,10 @@ static struct iommu_sva *intel_svm_bind_mm(struct int= el_iommu *iommu, sflags =3D (flags & SVM_FLAG_SUPERVISOR_MODE) ? PASID_FLAG_SUPERVISOR_MODE : 0; sflags |=3D cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0; - spin_lock_irqsave(&iommu->lock, iflags); + spin_lock(&iommu->lock); ret =3D intel_pasid_setup_first_level(iommu, dev, mm->pgd, mm->pasid, FLPT_DEFAULT_DID, sflags); - spin_unlock_irqrestore(&iommu->lock, iflags); + spin_unlock(&iommu->lock); =20 if (ret) goto free_sdev; --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DB83BC433EF for ; Wed, 29 Jun 2022 07:52:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232503AbiF2HwT (ORCPT ); Wed, 29 Jun 2022 03:52:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230514AbiF2HwL (ORCPT ); Wed, 29 Jun 2022 03:52:11 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA2593969A for ; Wed, 29 Jun 2022 00:52:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489125; x=1688025125; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4dG8u4WuqlreDbxvltEqLapsgzPYKKWe1Wl/fUnZ9aQ=; b=D8PQMHv4ZvAd5XBnhYu8EABnsbxJpfhTkDnTWmSZaWbidYTewv9Wcc62 3OJedp6NoHlwyAYRnq5uS2zs6SvqzUU5I6pistr0kfw2hdm0qWqlIg9Sa McSTKMoMQku85YtY57imMnwQ0JrR8Y60TNXHkSgqCgY14q+bKs2gwKjdE RpdKCS3yMPQz+OFVFl07F8G1sLM8T4zXqsxsJi3VSZIrDMk4kcegWgKIw lgThQXNp2FVW3WwLg+YRoUsKZHUUZ794OCHggYvKXxKomUdPJOSt5rYWu +31SrQ0C6cZOPwKy2XSoPxu2fwKW23aUBZ6nJzLN4nwvcoSR+af2u7SxT A==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719430" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719430" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209662" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:03 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 06/11] iommu/vt-d: Acquiring lock in domain ID allocation helpers Date: Wed, 29 Jun 2022 15:47:20 +0800 Message-Id: <20220629074725.2331441-7-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The iommu->lock is used to protect the per-IOMMU domain ID resource. Moving the lock into the ID alloc/free helpers makes the code more compact. At the same time, the device_domain_lock is irrelevant to the domain ID resource, remove its assertion as well. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index a81bdddf1091..5681b8ef11f1 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1781,16 +1781,13 @@ static struct dmar_domain *alloc_domain(unsigned in= t type) return domain; } =20 -/* Must be called with iommu->lock */ static int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu) { unsigned long ndomains; - int num; - - assert_spin_locked(&device_domain_lock); - assert_spin_locked(&iommu->lock); + int num, ret =3D 0; =20 + spin_lock(&iommu->lock); domain->iommu_refcnt[iommu->seq_id] +=3D 1; if (domain->iommu_refcnt[iommu->seq_id] =3D=3D 1) { ndomains =3D cap_ndoms(iommu->cap); @@ -1799,7 +1796,8 @@ static int domain_attach_iommu(struct dmar_domain *do= main, if (num >=3D ndomains) { pr_err("%s: No free domain ids\n", iommu->name); domain->iommu_refcnt[iommu->seq_id] -=3D 1; - return -ENOSPC; + ret =3D -ENOSPC; + goto out_unlock; } =20 set_bit(num, iommu->domain_ids); @@ -1808,7 +1806,9 @@ static int domain_attach_iommu(struct dmar_domain *do= main, domain_update_iommu_cap(domain); } =20 - return 0; +out_unlock: + spin_unlock(&iommu->lock); + return ret; } =20 static void domain_detach_iommu(struct dmar_domain *domain, @@ -1816,9 +1816,7 @@ static void domain_detach_iommu(struct dmar_domain *d= omain, { int num; =20 - assert_spin_locked(&device_domain_lock); - assert_spin_locked(&iommu->lock); - + spin_lock(&iommu->lock); domain->iommu_refcnt[iommu->seq_id] -=3D 1; if (domain->iommu_refcnt[iommu->seq_id] =3D=3D 0) { num =3D domain->iommu_did[iommu->seq_id]; @@ -1826,6 +1824,7 @@ static void domain_detach_iommu(struct dmar_domain *d= omain, domain_update_iommu_cap(domain); domain->iommu_did[iommu->seq_id] =3D 0; } + spin_unlock(&iommu->lock); } =20 static inline int guestwidth_to_adjustwidth(int gaw) @@ -2477,9 +2476,7 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) =20 spin_lock_irqsave(&device_domain_lock, flags); info->domain =3D domain; - spin_lock(&iommu->lock); ret =3D domain_attach_iommu(domain, iommu); - spin_unlock(&iommu->lock); if (ret) { spin_unlock_irqrestore(&device_domain_lock, flags); return ret; @@ -4183,10 +4180,7 @@ static void __dmar_remove_one_dev_info(struct device= _domain_info *info) } =20 list_del(&info->link); - - spin_lock(&iommu->lock); domain_detach_iommu(domain, iommu); - spin_unlock(&iommu->lock); } =20 static void dmar_remove_one_dev_info(struct device *dev) --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02AB4C43334 for ; Wed, 29 Jun 2022 07:52:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230342AbiF2HwX (ORCPT ); Wed, 29 Jun 2022 03:52:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232539AbiF2HwM (ORCPT ); Wed, 29 Jun 2022 03:52:12 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90C4425C57 for ; Wed, 29 Jun 2022 00:52:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489128; x=1688025128; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ysJ4ffCxYuGIljHcsD8yIGNkMC1bHM5rK/nPjUrdCIU=; b=BxJn5QGIa1IS0fcS/VE98kbEM9S8o4MSIsnkeA0abkbLr093DXt+wsUA G/kfjnFJmR8KpdZ6FW3ARPajLAxQd8g8NccqBTYUwfwLEGjQ/4X+VXgU3 5QP7CJER2pK91dUZf0LCGieH/6EFCHU98z1aEFPXuwcM1X8hck5T2JLtF 2/UtSgbqBGcwjCmxj51NuRHgpOi6GXvuc7/HgSWpdFDDAkuIkfPySWl85 dY8WVNzLcz9cqpqoOqicgy8FDYi0bdgYRFF5c4TDsJ8XzkiwhEvi9IUNP rCo8dh7eFgva1rW9QCCc4hvg4qOwBQIHXuWqqpCoLVe3hbJ52pac65HXf w==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719455" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719455" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209690" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:05 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 07/11] iommu/vt-d: Acquiring lock in pasid manipulation helpers Date: Wed, 29 Jun 2022 15:47:21 +0800 Message-Id: <20220629074725.2331441-8-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The iommu->lock is used to protect the per-IOMMU pasid directory table and pasid table. Move the spinlock acquisition/release into the helpers to make the code self-contained. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 2 - drivers/iommu/intel/pasid.c | 103 +++++++++++++++++++----------------- drivers/iommu/intel/svm.c | 3 -- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 5681b8ef11f1..f45a769695c3 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -2494,7 +2494,6 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) } =20 /* Setup the PASID entry for requests without PASID: */ - spin_lock(&iommu->lock); if (hw_pass_through && domain_type_is_si(domain)) ret =3D intel_pasid_setup_pass_through(iommu, domain, dev, PASID_RID2PASID); @@ -2504,7 +2503,6 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) else ret =3D intel_pasid_setup_second_level(iommu, domain, dev, PASID_RID2PASID); - spin_unlock(&iommu->lock); if (ret) { dev_err(dev, "Setup RID2PASID failed\n"); dmar_remove_one_dev_info(dev); diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index 43f090381ec7..7792a1b2ebc4 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -450,17 +450,17 @@ void intel_pasid_tear_down_entry(struct intel_iommu *= iommu, struct device *dev, struct pasid_entry *pte; u16 did, pgtt; =20 + spin_lock(&iommu->lock); pte =3D intel_pasid_get_entry(dev, pasid); - if (WARN_ON(!pte)) - return; - - if (!pasid_pte_is_present(pte)) + if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) { + spin_unlock(&iommu->lock); return; + } =20 did =3D pasid_get_domain_id(pte); pgtt =3D pasid_pte_get_pgtt(pte); - intel_pasid_clear_entry(dev, pasid, fault_ignore); + spin_unlock(&iommu->lock); =20 if (!ecap_coherent(iommu->ecap)) clflush_cache_range(pte, sizeof(*pte)); @@ -496,22 +496,6 @@ static void pasid_flush_caches(struct intel_iommu *iom= mu, } } =20 -static inline int pasid_enable_wpe(struct pasid_entry *pte) -{ -#ifdef CONFIG_X86 - unsigned long cr0 =3D read_cr0(); - - /* CR0.WP is normally set but just to be sure */ - if (unlikely(!(cr0 & X86_CR0_WP))) { - pr_err_ratelimited("No CPU write protect!\n"); - return -EINVAL; - } -#endif - pasid_set_wpe(pte); - - return 0; -}; - /* * Set up the scalable mode pasid table entry for first only * translation type. @@ -528,39 +512,52 @@ int intel_pasid_setup_first_level(struct intel_iommu = *iommu, return -EINVAL; } =20 - pte =3D intel_pasid_get_entry(dev, pasid); - if (WARN_ON(!pte)) + if (flags & PASID_FLAG_SUPERVISOR_MODE) { +#ifdef CONFIG_X86 + unsigned long cr0 =3D read_cr0(); + + /* CR0.WP is normally set but just to be sure */ + if (unlikely(!(cr0 & X86_CR0_WP))) { + pr_err("No CPU write protect!\n"); + return -EINVAL; + } +#endif + if (!ecap_srs(iommu->ecap)) { + pr_err("No supervisor request support on %s\n", + iommu->name); + return -EINVAL; + } + } + + if ((flags & PASID_FLAG_FL5LP) && !cap_5lp_support(iommu->cap)) { + pr_err("No 5-level paging support for first-level on %s\n", + iommu->name); return -EINVAL; + } =20 - /* Caller must ensure PASID entry is not in use. */ - if (pasid_pte_is_present(pte)) + spin_lock(&iommu->lock); + pte =3D intel_pasid_get_entry(dev, pasid); + if (!pte) { + spin_unlock(&iommu->lock); + return -ENODEV; + } + + if (pasid_pte_is_present(pte)) { + spin_unlock(&iommu->lock); return -EBUSY; + } =20 pasid_clear_entry(pte); =20 /* Setup the first level page table pointer: */ pasid_set_flptr(pte, (u64)__pa(pgd)); if (flags & PASID_FLAG_SUPERVISOR_MODE) { - if (!ecap_srs(iommu->ecap)) { - pr_err("No supervisor request support on %s\n", - iommu->name); - return -EINVAL; - } pasid_set_sre(pte); - if (pasid_enable_wpe(pte)) - return -EINVAL; - + pasid_set_wpe(pte); } =20 - if (flags & PASID_FLAG_FL5LP) { - if (cap_5lp_support(iommu->cap)) { - pasid_set_flpm(pte, 1); - } else { - pr_err("No 5-level paging support for first-level\n"); - pasid_clear_entry(pte); - return -EINVAL; - } - } + if (flags & PASID_FLAG_FL5LP) + pasid_set_flpm(pte, 1); =20 if (flags & PASID_FLAG_PAGE_SNOOP) pasid_set_pgsnp(pte); @@ -572,6 +569,8 @@ int intel_pasid_setup_first_level(struct intel_iommu *i= ommu, /* Setup Present and PASID Granular Transfer Type: */ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY); pasid_set_present(pte); + spin_unlock(&iommu->lock); + pasid_flush_caches(iommu, pte, pasid, did); =20 return 0; @@ -629,15 +628,17 @@ int intel_pasid_setup_second_level(struct intel_iommu= *iommu, pgd_val =3D virt_to_phys(pgd); did =3D domain->iommu_did[iommu->seq_id]; =20 + spin_lock(&iommu->lock); pte =3D intel_pasid_get_entry(dev, pasid); if (!pte) { - dev_err(dev, "Failed to get pasid entry of PASID %d\n", pasid); + spin_unlock(&iommu->lock); return -ENODEV; } =20 - /* Caller must ensure PASID entry is not in use. */ - if (pasid_pte_is_present(pte)) + if (pasid_pte_is_present(pte)) { + spin_unlock(&iommu->lock); return -EBUSY; + } =20 pasid_clear_entry(pte); pasid_set_domain_id(pte, did); @@ -654,6 +655,8 @@ int intel_pasid_setup_second_level(struct intel_iommu *= iommu, if (pasid !=3D PASID_RID2PASID) pasid_set_sre(pte); pasid_set_present(pte); + spin_unlock(&iommu->lock); + pasid_flush_caches(iommu, pte, pasid, did); =20 return 0; @@ -669,15 +672,17 @@ int intel_pasid_setup_pass_through(struct intel_iommu= *iommu, u16 did =3D FLPT_DEFAULT_DID; struct pasid_entry *pte; =20 + spin_lock(&iommu->lock); pte =3D intel_pasid_get_entry(dev, pasid); if (!pte) { - dev_err(dev, "Failed to get pasid entry of PASID %d\n", pasid); + spin_unlock(&iommu->lock); return -ENODEV; } =20 - /* Caller must ensure PASID entry is not in use. */ - if (pasid_pte_is_present(pte)) + if (pasid_pte_is_present(pte)) { + spin_unlock(&iommu->lock); return -EBUSY; + } =20 pasid_clear_entry(pte); pasid_set_domain_id(pte, did); @@ -692,6 +697,8 @@ int intel_pasid_setup_pass_through(struct intel_iommu *= iommu, */ pasid_set_sre(pte); pasid_set_present(pte); + spin_unlock(&iommu->lock); + pasid_flush_caches(iommu, pte, pasid, did); =20 return 0; diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index 82288a50660d..64072e628bbd 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -394,11 +394,8 @@ static struct iommu_sva *intel_svm_bind_mm(struct inte= l_iommu *iommu, sflags =3D (flags & SVM_FLAG_SUPERVISOR_MODE) ? PASID_FLAG_SUPERVISOR_MODE : 0; sflags |=3D cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0; - spin_lock(&iommu->lock); ret =3D intel_pasid_setup_first_level(iommu, dev, mm->pgd, mm->pasid, FLPT_DEFAULT_DID, sflags); - spin_unlock(&iommu->lock); - if (ret) goto free_sdev; =20 --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 89A1BC433EF for ; Wed, 29 Jun 2022 07:52:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232663AbiF2Hwb (ORCPT ); Wed, 29 Jun 2022 03:52:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232565AbiF2HwN (ORCPT ); Wed, 29 Jun 2022 03:52:13 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5768137037 for ; Wed, 29 Jun 2022 00:52:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489131; x=1688025131; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tY87hduj2nEXRCDnGcy4jdRoPUkGGPAyuDpSb24r7bs=; b=WzffmzITNRxx1pKEPzP6Nw51+i1DIfyA0flkf27f85sDOBezm1+xitmU 5Y+YmiHx9pbaL1IRw6xS1apRtfbkuPrZadSoZ0vy9v2H3DhiTfmPUboIR c2+969OJ7TcbVXfWBT9/a2mhCSbbQyEsidb88uQ65D1Yh3cbM5KnOa2GR Iwk4a5u7ij4KM4ohVxwjMsvdSg4V2jWVyhvVAR2c9kU7uDskE38+Nr0Cf RjVdO/QL9N2SopAkUPT/LfXJeStYoAbQce79T/E64Li/hQJ5pd0SNlXxG aa8EqXfAOfLkDsZ0ecDFfnnIjVJQlXtxD++r1m0GQu+ZQ5O7axY2SaKla w==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719478" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719478" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209710" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:08 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu , Jason Gunthorpe Subject: [PATCH v3 08/11] iommu/vt-d: Check device list of domain in domain free path Date: Wed, 29 Jun 2022 15:47:22 +0800 Message-Id: <20220629074725.2331441-9-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" When the IOMMU domain is about to be freed, it should not be set on any device. Instead of silently dealing with some bug cases, it's better to trigger a warning to report and fix any potential bugs at the first time. Signed-off-by: Lu Baolu Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index f45a769695c3..94f41981b75b 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -294,7 +294,6 @@ static LIST_HEAD(dmar_satc_units); /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; =20 -static void domain_remove_dev_info(struct dmar_domain *domain); static void dmar_remove_one_dev_info(struct device *dev); static void __dmar_remove_one_dev_info(struct device_domain_info *info); =20 @@ -1843,10 +1842,6 @@ static inline int guestwidth_to_adjustwidth(int gaw) =20 static void domain_exit(struct dmar_domain *domain) { - - /* Remove associated devices and clear attached or cached domains */ - domain_remove_dev_info(domain); - if (domain->pgd) { LIST_HEAD(freelist); =20 @@ -1854,6 +1849,9 @@ static void domain_exit(struct dmar_domain *domain) put_pages_list(&freelist); } =20 + if (WARN_ON(!list_empty(&domain->devices))) + return; + kfree(domain); } =20 @@ -2336,17 +2334,6 @@ static void domain_context_clear_one(struct device_d= omain_info *info, u8 bus, u8 __iommu_flush_dev_iotlb(info, 0, MAX_AGAW_PFN_WIDTH); } =20 -static void domain_remove_dev_info(struct dmar_domain *domain) -{ - struct device_domain_info *info, *tmp; - unsigned long flags; - - spin_lock_irqsave(&device_domain_lock, flags); - list_for_each_entry_safe(info, tmp, &domain->devices, link) - __dmar_remove_one_dev_info(info); - spin_unlock_irqrestore(&device_domain_lock, flags); -} - static int domain_setup_first_level(struct intel_iommu *iommu, struct dmar_domain *domain, struct device *dev, --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 667C1C433EF for ; Wed, 29 Jun 2022 07:52:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232035AbiF2Hwq (ORCPT ); Wed, 29 Jun 2022 03:52:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36754 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232569AbiF2HwQ (ORCPT ); Wed, 29 Jun 2022 03:52:16 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AE2A39B97 for ; Wed, 29 Jun 2022 00:52:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489133; x=1688025133; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WngZy2RXcl507LUfl56SWWZdud4Z0sU0Rtwz35+5lWQ=; b=kEAb9zYx9l+keaTUOVGoO3LXnMHlpVU6bhdol0nRSc1SuJpUhmKg4nMQ TxpPbBbKnDRT9aSM8woMeFY2G6CpE5AzGP9Dl8dydmt39HMefCJAJ9SvH QamYD+qOJHta7fV6bU5HeLe3UIy0vWujk3/Orc4AYHs6uhfrkeEYDaQmN fveCwjIIFiOlQ6Glcp7E3YxcIXOfsz2WUCJ4Db7GBLMBzn6VWUJyeAsrg Q3eEEm3CpmAbkV25sATSGT8qESfEXmcQZI9ta/pYf1+aNfGr2GRgTwK7+ U6+/8Bh+nADJET62/oMVDrK2Z3TJ7se0I04kM9qSKpBCE8OO1s/oChmA/ Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719494" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719494" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209721" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:11 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 09/11] iommu/vt-d: Fold __dmar_remove_one_dev_info() into its caller Date: Wed, 29 Jun 2022 15:47:23 +0800 Message-Id: <20220629074725.2331441-10-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Fold __dmar_remove_one_dev_info() into dmar_remove_one_dev_info() which is its only caller. Make the spin lock critical range only cover the device list change code and remove some unnecessary checks. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 94f41981b75b..3038aafecff9 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -295,7 +295,6 @@ static LIST_HEAD(dmar_satc_units); static int g_num_of_iommus; =20 static void dmar_remove_one_dev_info(struct device *dev); -static void __dmar_remove_one_dev_info(struct device_domain_info *info); =20 int dmar_disabled =3D !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON); int intel_iommu_sm =3D IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT= _ON); @@ -4141,20 +4140,13 @@ static void domain_context_clear(struct device_doma= in_info *info) &domain_context_clear_one_cb, info); } =20 -static void __dmar_remove_one_dev_info(struct device_domain_info *info) +static void dmar_remove_one_dev_info(struct device *dev) { - struct dmar_domain *domain; - struct intel_iommu *iommu; - - assert_spin_locked(&device_domain_lock); - - if (WARN_ON(!info)) - return; - - iommu =3D info->iommu; - domain =3D info->domain; + struct device_domain_info *info =3D dev_iommu_priv_get(dev); + struct intel_iommu *iommu =3D info->iommu; + unsigned long flags; =20 - if (info->dev && !dev_is_real_dma_subdevice(info->dev)) { + if (!dev_is_real_dma_subdevice(info->dev)) { if (dev_is_pci(info->dev) && sm_supported(iommu)) intel_pasid_tear_down_entry(iommu, info->dev, PASID_RID2PASID, false); @@ -4164,20 +4156,11 @@ static void __dmar_remove_one_dev_info(struct devic= e_domain_info *info) intel_pasid_free_table(info->dev); } =20 - list_del(&info->link); - domain_detach_iommu(domain, iommu); -} - -static void dmar_remove_one_dev_info(struct device *dev) -{ - struct device_domain_info *info; - unsigned long flags; - spin_lock_irqsave(&device_domain_lock, flags); - info =3D dev_iommu_priv_get(dev); - if (info) - __dmar_remove_one_dev_info(info); + list_del(&info->link); spin_unlock_irqrestore(&device_domain_lock, flags); + + domain_detach_iommu(info->domain, iommu); } =20 static int md_domain_init(struct dmar_domain *domain, int guest_width) --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86AA2C433EF for ; Wed, 29 Jun 2022 07:52:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232569AbiF2Hwu (ORCPT ); Wed, 29 Jun 2022 03:52:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232477AbiF2HwS (ORCPT ); Wed, 29 Jun 2022 03:52:18 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD4CF3A195 for ; Wed, 29 Jun 2022 00:52:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489135; x=1688025135; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yfKGiGqgBCGt3LELuF8+oSTbi0JzvMyYgIXr3AIdF+4=; b=I48EWSNGJGz3tloRvrw9KeQHh5xTFdl1p+dPMwF6nSKVHZJSLVKYyYY/ aVoBODAGD/6c3kfUzh6w9URPOU0FAa7A6VbdJUkhWQWusSaxOp9j9B5xm 1r2k0Vm4NXfwAtU1WleU8gH1lmbn66n0jvqcuArmfo5fJao6sc6ZIZ4Dm Ay+vjRD7k1JocRKc6+lo6+UnsuNgOZbmIpXQsXuWRHNvUIJphqKvQGWTC 5S9xE0QkiZb5e4tHbzn7qm4/4M4lsyqUZley/ddZe8J1+4HAusif7Bar/ 0iJGAaFaZGmUOYa5o0JHxeRXs2pisLGvmoStKeMD9ltYIaN/EpzPTeeqJ A==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719507" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719507" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:15 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209743" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:13 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 10/11] iommu/vt-d: Use device_domain_lock accurately Date: Wed, 29 Jun 2022 15:47:24 +0800 Message-Id: <20220629074725.2331441-11-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The device_domain_lock is used to protect the device tracking list of a domain. Remove unnecessary spin_lock/unlock()'s and move the necessary ones around the list access. Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 61 ++++++++++++++----------------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 3038aafecff9..1783859b511a 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -534,16 +534,10 @@ static int domain_update_device_node(struct dmar_doma= in *domain) { struct device_domain_info *info; int nid =3D NUMA_NO_NODE; + unsigned long flags; =20 - assert_spin_locked(&device_domain_lock); - - if (list_empty(&domain->devices)) - return NUMA_NO_NODE; - + spin_lock_irqsave(&device_domain_lock, flags); list_for_each_entry(info, &domain->devices, link) { - if (!info->dev) - continue; - /* * There could possibly be multiple device numa nodes as devices * within the same domain may sit behind different IOMMUs. There @@ -554,6 +548,7 @@ static int domain_update_device_node(struct dmar_domain= *domain) if (nid !=3D NUMA_NO_NODE) break; } + spin_unlock_irqrestore(&device_domain_lock, flags); =20 return nid; } @@ -1376,23 +1371,24 @@ static void __iommu_flush_iotlb(struct intel_iommu = *iommu, u16 did, } =20 static struct device_domain_info * -iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *i= ommu, - u8 bus, u8 devfn) +iommu_support_dev_iotlb(struct dmar_domain *domain, struct intel_iommu *io= mmu, + u8 bus, u8 devfn) { struct device_domain_info *info; - - assert_spin_locked(&device_domain_lock); + unsigned long flags; =20 if (!iommu->qi) return NULL; =20 - list_for_each_entry(info, &domain->devices, link) + spin_lock_irqsave(&device_domain_lock, flags); + list_for_each_entry(info, &domain->devices, link) { if (info->iommu =3D=3D iommu && info->bus =3D=3D bus && info->devfn =3D=3D devfn) { - if (info->ats_supported && info->dev) - return info; - break; + spin_unlock_irqrestore(&device_domain_lock, flags); + return info->ats_supported ? info : NULL; } + } + spin_unlock_irqrestore(&device_domain_lock, flags); =20 return NULL; } @@ -1401,24 +1397,23 @@ static void domain_update_iotlb(struct dmar_domain = *domain) { struct device_domain_info *info; bool has_iotlb_device =3D false; + unsigned long flags; =20 - assert_spin_locked(&device_domain_lock); - - list_for_each_entry(info, &domain->devices, link) + spin_lock_irqsave(&device_domain_lock, flags); + list_for_each_entry(info, &domain->devices, link) { if (info->ats_enabled) { has_iotlb_device =3D true; break; } - + } domain->has_iotlb_device =3D has_iotlb_device; + spin_unlock_irqrestore(&device_domain_lock, flags); } =20 static void iommu_enable_dev_iotlb(struct device_domain_info *info) { struct pci_dev *pdev; =20 - assert_spin_locked(&device_domain_lock); - if (!info || !dev_is_pci(info->dev)) return; =20 @@ -1464,8 +1459,6 @@ static void iommu_disable_dev_iotlb(struct device_dom= ain_info *info) { struct pci_dev *pdev; =20 - assert_spin_locked(&device_domain_lock); - if (!dev_is_pci(info->dev)) return; =20 @@ -1908,11 +1901,11 @@ static int domain_context_mapping_one(struct dmar_d= omain *domain, struct pasid_table *table, u8 bus, u8 devfn) { + struct device_domain_info *info =3D + iommu_support_dev_iotlb(domain, iommu, bus, devfn); u16 did =3D domain->iommu_did[iommu->seq_id]; int translation =3D CONTEXT_TT_MULTI_LEVEL; - struct device_domain_info *info =3D NULL; struct context_entry *context; - unsigned long flags; int ret; =20 WARN_ON(did =3D=3D 0); @@ -1925,7 +1918,6 @@ static int domain_context_mapping_one(struct dmar_dom= ain *domain, =20 BUG_ON(!domain->pgd); =20 - spin_lock_irqsave(&device_domain_lock, flags); spin_lock(&iommu->lock); =20 ret =3D -ENOMEM; @@ -1978,7 +1970,6 @@ static int domain_context_mapping_one(struct dmar_dom= ain *domain, * Setup the Device-TLB enable bit and Page request * Enable bit: */ - info =3D iommu_support_dev_iotlb(domain, iommu, bus, devfn); if (info && info->ats_supported) context_set_sm_dte(context); if (info && info->pri_supported) @@ -2001,7 +1992,6 @@ static int domain_context_mapping_one(struct dmar_dom= ain *domain, goto out_unlock; } =20 - info =3D iommu_support_dev_iotlb(domain, iommu, bus, devfn); if (info && info->ats_supported) translation =3D CONTEXT_TT_DEV_IOTLB; else @@ -2047,7 +2037,6 @@ static int domain_context_mapping_one(struct dmar_dom= ain *domain, =20 out_unlock: spin_unlock(&iommu->lock); - spin_unlock_irqrestore(&device_domain_lock, flags); =20 return ret; } @@ -2460,13 +2449,12 @@ static int domain_add_dev_info(struct dmar_domain *= domain, struct device *dev) if (!iommu) return -ENODEV; =20 - spin_lock_irqsave(&device_domain_lock, flags); - info->domain =3D domain; ret =3D domain_attach_iommu(domain, iommu); - if (ret) { - spin_unlock_irqrestore(&device_domain_lock, flags); + if (ret) return ret; - } + + info->domain =3D domain; + spin_lock_irqsave(&device_domain_lock, flags); list_add(&info->link, &domain->devices); spin_unlock_irqrestore(&device_domain_lock, flags); =20 @@ -4636,7 +4624,6 @@ int intel_iommu_enable_pasid(struct intel_iommu *iomm= u, struct device *dev) struct device_domain_info *info =3D dev_iommu_priv_get(dev); struct context_entry *context; struct dmar_domain *domain; - unsigned long flags; u64 ctx_lo; int ret; =20 @@ -4644,7 +4631,6 @@ int intel_iommu_enable_pasid(struct intel_iommu *iomm= u, struct device *dev) if (!domain) return -EINVAL; =20 - spin_lock_irqsave(&device_domain_lock, flags); spin_lock(&iommu->lock); =20 ret =3D -EINVAL; @@ -4676,7 +4662,6 @@ int intel_iommu_enable_pasid(struct intel_iommu *iomm= u, struct device *dev) =20 out: spin_unlock(&iommu->lock); - spin_unlock_irqrestore(&device_domain_lock, flags); =20 return ret; } --=20 2.25.1 From nobody Sun Apr 26 10:50:25 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3B1DC43334 for ; Wed, 29 Jun 2022 07:54:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231767AbiF2HyX (ORCPT ); Wed, 29 Jun 2022 03:54:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232603AbiF2HwY (ORCPT ); Wed, 29 Jun 2022 03:52:24 -0400 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26ED73A708 for ; Wed, 29 Jun 2022 00:52:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1656489138; x=1688025138; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rDw7P6FJi7QTKFVWwAK42b0Q1umngDHKfvQybxOrxMU=; b=Ix33XUlsrLcln0zTLeE6tBb5BsYDs6Rainh+U+9YtlwDjJFufyRtwtPl y2gmka7ngEhP0RrEK1VtOM2egCTe6H+0HI98xYdq6leOl5c5SECdWcWli BJ5kAVFFTYsyyASFCsxtsL/0CtEF031SS03qotQVJmZs2u4rOD088XYhE 6azanCaX33N4iT5r7tVZHWNf/pXSzs5pxRUlADjTRRbNA5FQ/METWQuIE VY4i738GjJ4GTObKLE2/BOcu6Tfly+jt28asy7WJUsk44ilN3k9zhVMhG HzlZ86wTasJvymWp68X7MF5YFy5mzwYoo91HfAosbVitm/Q18+ItgXy0c Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10392"; a="270719520" X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="270719520" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jun 2022 00:52:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,230,1650956400"; d="scan'208";a="588209753" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga007.jf.intel.com with ESMTP; 29 Jun 2022 00:52:15 -0700 From: Lu Baolu To: iommu@lists.linux-foundation.org, iommu@lists.linux.dev Cc: Kevin Tian , Ashok Raj , Liu Yi L , Jacob jun Pan , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 11/11] iommu/vt-d: Convert global spinlock into per domain lock Date: Wed, 29 Jun 2022 15:47:25 +0800 Message-Id: <20220629074725.2331441-12-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220629074725.2331441-1-baolu.lu@linux.intel.com> References: <20220629074725.2331441-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Using a global device_domain_lock spinlock to protect per-domain device tracking lists is an inefficient way, especially considering this lock is also needed in the hot paths. This optimizes the locking mechanism by converting the global lock to per domain lock. On the other hand, as the device tracking lists are never accessed in any interrupt context, there is no need to disable interrupts while spinning. Replace irqsave variant with spinlock calls. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.h | 1 + drivers/iommu/intel/iommu.c | 50 ++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 198c6c822ef4..df64d3d9c49a 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -541,6 +541,7 @@ struct dmar_domain { u8 force_snooping : 1; /* Create IOPTEs with snoop control */ u8 set_pte_snp:1; =20 + spinlock_t lock; /* Protect device tracking lists */ struct list_head devices; /* all devices' list */ =20 struct dma_pte *pgd; /* virtual address */ diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 1783859b511a..da6cfea0f0d6 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -310,7 +310,6 @@ static int iommu_skip_te_disable; #define IDENTMAP_GFX 2 #define IDENTMAP_AZALIA 4 =20 -static DEFINE_SPINLOCK(device_domain_lock); const struct iommu_ops intel_iommu_ops; =20 static bool translation_pre_enabled(struct intel_iommu *iommu) @@ -534,9 +533,8 @@ static int domain_update_device_node(struct dmar_domain= *domain) { struct device_domain_info *info; int nid =3D NUMA_NO_NODE; - unsigned long flags; =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_for_each_entry(info, &domain->devices, link) { /* * There could possibly be multiple device numa nodes as devices @@ -548,7 +546,7 @@ static int domain_update_device_node(struct dmar_domain= *domain) if (nid !=3D NUMA_NO_NODE) break; } - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); =20 return nid; } @@ -1375,20 +1373,19 @@ iommu_support_dev_iotlb(struct dmar_domain *domain,= struct intel_iommu *iommu, u8 bus, u8 devfn) { struct device_domain_info *info; - unsigned long flags; =20 if (!iommu->qi) return NULL; =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_for_each_entry(info, &domain->devices, link) { if (info->iommu =3D=3D iommu && info->bus =3D=3D bus && info->devfn =3D=3D devfn) { - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); return info->ats_supported ? info : NULL; } } - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); =20 return NULL; } @@ -1397,9 +1394,8 @@ static void domain_update_iotlb(struct dmar_domain *d= omain) { struct device_domain_info *info; bool has_iotlb_device =3D false; - unsigned long flags; =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_for_each_entry(info, &domain->devices, link) { if (info->ats_enabled) { has_iotlb_device =3D true; @@ -1407,7 +1403,7 @@ static void domain_update_iotlb(struct dmar_domain *d= omain) } } domain->has_iotlb_device =3D has_iotlb_device; - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); } =20 static void iommu_enable_dev_iotlb(struct device_domain_info *info) @@ -1498,17 +1494,15 @@ static void __iommu_flush_dev_iotlb(struct device_d= omain_info *info, static void iommu_flush_dev_iotlb(struct dmar_domain *domain, u64 addr, unsigned mask) { - unsigned long flags; struct device_domain_info *info; =20 if (!domain->has_iotlb_device) return; =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_for_each_entry(info, &domain->devices, link) __iommu_flush_dev_iotlb(info, addr, mask); - - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); } =20 static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, @@ -1768,6 +1762,7 @@ static struct dmar_domain *alloc_domain(unsigned int = type) domain->flags |=3D DOMAIN_FLAG_USE_FIRST_LEVEL; domain->has_iotlb_device =3D false; INIT_LIST_HEAD(&domain->devices); + spin_lock_init(&domain->lock); =20 return domain; } @@ -2441,7 +2436,6 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) { struct device_domain_info *info =3D dev_iommu_priv_get(dev); struct intel_iommu *iommu; - unsigned long flags; u8 bus, devfn; int ret; =20 @@ -2454,9 +2448,9 @@ static int domain_add_dev_info(struct dmar_domain *do= main, struct device *dev) return ret; =20 info->domain =3D domain; - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_add(&info->link, &domain->devices); - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); =20 /* PASID table is mandatory for a PCI device in scalable mode. */ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { @@ -4131,8 +4125,8 @@ static void domain_context_clear(struct device_domain= _info *info) static void dmar_remove_one_dev_info(struct device *dev) { struct device_domain_info *info =3D dev_iommu_priv_get(dev); + struct dmar_domain *domain =3D info->domain; struct intel_iommu *iommu =3D info->iommu; - unsigned long flags; =20 if (!dev_is_real_dma_subdevice(info->dev)) { if (dev_is_pci(info->dev) && sm_supported(iommu)) @@ -4144,11 +4138,11 @@ static void dmar_remove_one_dev_info(struct device = *dev) intel_pasid_free_table(info->dev); } =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&domain->lock); list_del(&info->link); - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&domain->lock); =20 - domain_detach_iommu(info->domain, iommu); + domain_detach_iommu(domain, iommu); } =20 static int md_domain_init(struct dmar_domain *domain, int guest_width) @@ -4430,7 +4424,7 @@ static bool domain_support_force_snooping(struct dmar= _domain *domain) struct device_domain_info *info; bool support =3D true; =20 - assert_spin_locked(&device_domain_lock); + assert_spin_locked(&domain->lock); list_for_each_entry(info, &domain->devices, link) { if (!ecap_sc_support(info->iommu->ecap)) { support =3D false; @@ -4445,8 +4439,7 @@ static void domain_set_force_snooping(struct dmar_dom= ain *domain) { struct device_domain_info *info; =20 - assert_spin_locked(&device_domain_lock); - + assert_spin_locked(&domain->lock); /* * Second level page table supports per-PTE snoop control. The * iommu_map() interface will handle this by setting SNP bit. @@ -4464,20 +4457,19 @@ static void domain_set_force_snooping(struct dmar_d= omain *domain) static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domai= n) { struct dmar_domain *dmar_domain =3D to_dmar_domain(domain); - unsigned long flags; =20 if (dmar_domain->force_snooping) return true; =20 - spin_lock_irqsave(&device_domain_lock, flags); + spin_lock(&dmar_domain->lock); if (!domain_support_force_snooping(dmar_domain)) { - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&dmar_domain->lock); return false; } =20 domain_set_force_snooping(dmar_domain); dmar_domain->force_snooping =3D true; - spin_unlock_irqrestore(&device_domain_lock, flags); + spin_unlock(&dmar_domain->lock); =20 return true; } --=20 2.25.1