Received: by 2002:a05:6358:701b:b0:131:369:b2a3 with SMTP id 27csp3807871rwo; Mon, 24 Jul 2023 17:36:53 -0700 (PDT) X-Google-Smtp-Source: APBJJlHsC6BhK4F4kb2pIYPhwZOyuJyt/2vRS0VYofCaIeTrIs/qGeoGUbV0yC4liaqOU16zi8nE X-Received: by 2002:a37:ef06:0:b0:768:75c:a323 with SMTP id j6-20020a37ef06000000b00768075ca323mr1443453qkk.30.1690245413259; Mon, 24 Jul 2023 17:36:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690245413; cv=none; d=google.com; s=arc-20160816; b=dVcijU+Thmt9hq2jy4RVrRUPtkSyUV/7v6VP9giSakpQCQ2ZFl8InOnbqvbBf66qbj N7Z0XoQmQ5jKcKXy7a+B2DhHgmN67uZ0gPtowYIZ+rC7EWql3MN+oBsfCFTjIdAOeYR8 VJKLK7HqYo9/38VoSHLUItGn9qcDWCIybE5xqBDSf/3oT/LTRJ4Lxe2e59ZgTJPnJtJb GDSMsrbQJF4/P/uc3XPDZCrTPNTQNOi4FtagU6SOpRlZJPJqLl36QuqKLI7e/7Phba47 f1GMFEcDz9944n7vavHtdycveoO8jLJh4fsirZHbufPuT/4cd70oEYhHIR2fk6g4CUtH VqcA== 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=e0mroYY/Q+E3WASJPJ1+3+EoVVjYVBRKscbYAniwIHk=; fh=bGo/Q4ro8pFaOByjLYWhYmu9zFeFMbnTLIEA0/9l4hc=; b=c3S6d98wzbqPfnYt66LDeSDh6LwSmgAskt2Je91PBrpstacKLIik6cMwf5ndjCWk1Y 4NnCv+JJReAVYCf7Z+cwzoyVmZIkMUSdrf2TBhaWljzg+j+KF/18fwmZB6J7nqe6GDED d+QPwDDqD+i58KxfrBDG+UjKS4XRiH8mQGyM4jHDCS58KEObuj4uICfY4OX0/BbYTyTl zH5cHLf8WrI9JHka44CLbgxO6M5A4XCROfMLsRDVmRv/fUrnnEkTv+L4/shbKQpjjlui XMMQITqpGVE0PIYgqY7pv84gQ+vlPf59zxSJCYHF+YFP6O2XExO45bcr0tHDpWq6wPfJ oCew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=eTMviSLM; 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 t9-20020a170902e84900b001b3ac2cdacasi10760421plg.553.2023.07.24.17.36.41; Mon, 24 Jul 2023 17:36:53 -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=eTMviSLM; 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 S231464AbjGXWVD (ORCPT + 99 others); Mon, 24 Jul 2023 18:21:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231187AbjGXWUq (ORCPT ); Mon, 24 Jul 2023 18:20:46 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A557C173E for ; Mon, 24 Jul 2023 15:20:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1690237243; x=1721773243; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1U8+TyCupULYtSWMx35NBr85fp+ePo8sW8Qahn6gkpM=; b=eTMviSLMoanrlc/w9D4etjaGjcg/hFSnAhyZUuIHvlGA84/hPqy88FTO fFlsexYnbPYBcLT8LAK8vkqwyHch+P71aYEr/pPe62eha36S3u6jPsmWw wCRL9pWu1nn+T4KgYn1xlRhW1jg6M+DePZJP2WFAS6o+vOe45yiCQ8s1e snd7KZozCfG/ftfmqCTCqqHIeXNOz6BtIE7j/9V6ygDJJL2+QweQsmVzS UoZYJCb45mzZ+7zBKK2BHM3FOL5o1fG0A5Ta9e4tPhp71jTv3kN7eepdM lBQ8Qhv6IOAd6RxYDE5Cp3ZRXwfwdPzoE+cF+vJxaj6IJgTpRBTCvr+vd Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10781"; a="398476735" X-IronPort-AV: E=Sophos;i="6.01,229,1684825200"; d="scan'208";a="398476735" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jul 2023 15:20:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10781"; a="899675515" X-IronPort-AV: E=Sophos;i="6.01,229,1684825200"; d="scan'208";a="899675515" Received: from srinivas-otcpl-7600.jf.intel.com (HELO jacob-builder.jf.intel.com) ([10.54.97.184]) by orsmga005.jf.intel.com with ESMTP; 24 Jul 2023 15:20:41 -0700 From: Jacob Pan To: LKML , iommu@lists.linux.dev, "Lu Baolu" , Joerg Roedel , Jean-Philippe Brucker , "Robin Murphy" Cc: Jason Gunthorpe , "Will Deacon" , "Tian, Kevin" , Yi Liu , "Yu, Fenghua" , Tony Luck , Jacob Pan Subject: [PATCH v11 7/8] iommu/vt-d: Add set_dev_pasid callback for dma domain Date: Mon, 24 Jul 2023 15:25:37 -0700 Message-Id: <20230724222538.3902553-8-jacob.jun.pan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230724222538.3902553-1-jacob.jun.pan@linux.intel.com> References: <20230724222538.3902553-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, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE 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 From: Lu Baolu This allows the upper layers to set a domain to a PASID of a device if the PASID feature is supported by the IOMMU hardware. The typical use cases are, for example, kernel DMA with PASID and hardware assisted mediated device drivers. The attaching device and pasid information is tracked in a per-domain list and is used for IOTLB and devTLB invalidation. Signed-off-by: Lu Baolu Signed-off-by: Jacob Pan --- drivers/iommu/intel/iommu.c | 104 ++++++++++++++++++++++++++++++++++-- drivers/iommu/intel/iommu.h | 7 +++ 2 files changed, 106 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 4a41aca6a2ba..f939fc2aa66c 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1359,6 +1359,7 @@ domain_lookup_dev_info(struct dmar_domain *domain, static void domain_update_iotlb(struct dmar_domain *domain) { + struct dev_pasid_info *dev_pasid; struct device_domain_info *info; bool has_iotlb_device = false; unsigned long flags; @@ -1370,6 +1371,14 @@ static void domain_update_iotlb(struct dmar_domain *domain) break; } } + + list_for_each_entry(dev_pasid, &domain->dev_pasids, link_domain) { + info = dev_iommu_priv_get(dev_pasid->dev); + if (info->ats_enabled) { + has_iotlb_device = true; + break; + } + } domain->has_iotlb_device = has_iotlb_device; spin_unlock_irqrestore(&domain->lock, flags); } @@ -1455,6 +1464,7 @@ static void __iommu_flush_dev_iotlb(struct device_domain_info *info, static void iommu_flush_dev_iotlb(struct dmar_domain *domain, u64 addr, unsigned mask) { + struct dev_pasid_info *dev_pasid; struct device_domain_info *info; unsigned long flags; @@ -1464,6 +1474,19 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, spin_lock_irqsave(&domain->lock, flags); list_for_each_entry(info, &domain->devices, link) __iommu_flush_dev_iotlb(info, addr, mask); + + list_for_each_entry(dev_pasid, &domain->dev_pasids, link_domain) { + info = dev_iommu_priv_get(dev_pasid->dev); + + if (!info->ats_enabled) + continue; + + qi_flush_dev_iotlb_pasid(info->iommu, + PCI_DEVID(info->bus, info->devfn), + info->pfsid, dev_pasid->pasid, + info->ats_qdep, addr, + mask); + } spin_unlock_irqrestore(&domain->lock, flags); } @@ -1472,9 +1495,13 @@ static void domain_flush_pasid_iotlb(struct intel_iommu *iommu, unsigned long npages, bool ih) { u16 did = domain_id_iommu(domain, iommu); + struct dev_pasid_info *dev_pasid; unsigned long flags; spin_lock_irqsave(&domain->lock, flags); + list_for_each_entry(dev_pasid, &domain->dev_pasids, link_domain) + qi_flush_piotlb(iommu, did, dev_pasid->pasid, addr, npages, ih); + if (!list_empty(&domain->devices)) qi_flush_piotlb(iommu, did, IOMMU_NO_PASID, addr, npages, ih); spin_unlock_irqrestore(&domain->lock, flags); @@ -1739,6 +1766,7 @@ static struct dmar_domain *alloc_domain(unsigned int type) domain->use_first_level = true; domain->has_iotlb_device = false; INIT_LIST_HEAD(&domain->devices); + INIT_LIST_HEAD(&domain->dev_pasids); spin_lock_init(&domain->lock); xa_init(&domain->iommu_array); @@ -4719,7 +4747,10 @@ static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain, static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid) { struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL); + struct dev_pasid_info *curr, *dev_pasid = NULL; + struct dmar_domain *dmar_domain; struct iommu_domain *domain; + unsigned long flags; domain = iommu_get_domain_for_dev_pasid(dev, pasid, 0); if (WARN_ON_ONCE(!domain)) @@ -4735,17 +4766,79 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid) goto out_tear_down; } - /* - * Should never reach here until we add support for attaching - * non-SVA domain to a pasid. - */ - WARN_ON(1); + dmar_domain = to_dmar_domain(domain); + spin_lock_irqsave(&dmar_domain->lock, flags); + list_for_each_entry(curr, &dmar_domain->dev_pasids, link_domain) { + if (curr->dev == dev && curr->pasid == pasid) { + list_del(&curr->link_domain); + dev_pasid = curr; + break; + } + } + WARN_ON_ONCE(!dev_pasid); + spin_unlock_irqrestore(&dmar_domain->lock, flags); + domain_detach_iommu(dmar_domain, iommu); + kfree(dev_pasid); out_tear_down: intel_pasid_tear_down_entry(iommu, dev, pasid, false); intel_drain_pasid_prq(dev, pasid); } +static int intel_iommu_set_dev_pasid(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid) +{ + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct dmar_domain *dmar_domain = to_dmar_domain(domain); + struct intel_iommu *iommu = info->iommu; + struct dev_pasid_info *dev_pasid; + unsigned long flags; + int ret; + + if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev)) + return -EOPNOTSUPP; + + if (context_copied(iommu, info->bus, info->devfn)) + return -EBUSY; + + ret = prepare_domain_attach_device(domain, dev); + if (ret) + return ret; + + dev_pasid = kzalloc(sizeof(*dev_pasid), GFP_KERNEL); + if (!dev_pasid) + return -ENOMEM; + + ret = domain_attach_iommu(dmar_domain, iommu); + if (ret) + goto out_free; + + if (domain_type_is_si(dmar_domain)) + ret = intel_pasid_setup_pass_through(iommu, dmar_domain, + dev, pasid); + else if (dmar_domain->use_first_level) + ret = domain_setup_first_level(iommu, dmar_domain, + dev, pasid); + else + ret = intel_pasid_setup_second_level(iommu, dmar_domain, + dev, pasid); + if (ret) + goto out_detach_iommu; + + dev_pasid->dev = dev; + dev_pasid->pasid = pasid; + spin_lock_irqsave(&dmar_domain->lock, flags); + list_add(&dev_pasid->link_domain, &dmar_domain->dev_pasids); + spin_unlock_irqrestore(&dmar_domain->lock, flags); + + return 0; +out_detach_iommu: + domain_detach_iommu(dmar_domain, iommu); +out_free: + kfree(dev_pasid); + return ret; +} + const struct iommu_ops intel_iommu_ops = { .capable = intel_iommu_capable, .domain_alloc = intel_iommu_domain_alloc, @@ -4765,6 +4858,7 @@ const struct iommu_ops intel_iommu_ops = { #endif .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = intel_iommu_attach_device, + .set_dev_pasid = intel_iommu_set_dev_pasid, .map_pages = intel_iommu_map_pages, .unmap_pages = intel_iommu_unmap_pages, .iotlb_sync_map = intel_iommu_iotlb_sync_map, diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 6d94a29f5d52..c18fb699c87a 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -595,6 +595,7 @@ struct dmar_domain { spinlock_t lock; /* Protect device tracking lists */ struct list_head devices; /* all devices' list */ + struct list_head dev_pasids; /* all attached pasids */ struct dma_pte *pgd; /* virtual address */ int gaw; /* max guest address width */ @@ -717,6 +718,12 @@ struct device_domain_info { struct pasid_table *pasid_table; /* pasid table */ }; +struct dev_pasid_info { + struct list_head link_domain; /* link to domain siblings */ + struct device *dev; + ioasid_t pasid; +}; + static inline void __iommu_flush_cache( struct intel_iommu *iommu, void *addr, int size) { -- 2.25.1