Received: by 2002:ab2:60d1:0:b0:1f7:5705:b850 with SMTP id i17csp37642lqm; Tue, 30 Apr 2024 11:58:45 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXE1pAhs7UfKdbKxWSdvZ/WW+Xu8xZykIjKbCeWK92JI7tWIQLKInVBqx4t8vZI7H91EPtHyDHtI3OS/8mdaE1+2oDaXzxfen1JYVCm1A== X-Google-Smtp-Source: AGHT+IFRAXpr6tBaBPYpYpLC8ZdRpWQowtiJEW3UvZpjCPupqL5BUs22/kBw3KKwmEo4mDt8sNJ2 X-Received: by 2002:a17:90b:fc3:b0:2b2:b4e8:ccce with SMTP id gd3-20020a17090b0fc300b002b2b4e8cccemr421887pjb.13.1714503525685; Tue, 30 Apr 2024 11:58:45 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714503525; cv=pass; d=google.com; s=arc-20160816; b=fAqiRCU7K30cztqTohzeLSzeLJMLM9LVGuPR7uLdKhVW7MKNHSKMCnIOImxUP/a88s en3R2Uy6yRXyOIClT8ZgrJORZGYz2lbggBcQcg6v4n1UcfSRUBfomTRF/icvHaZPH2it 1W+L7zivr4UZxVTnTEcKcBiW7OaMFChLnNUT/7u6tXcuo4u1do+DL1NOkWl5kN0ZV8Xg y+902nQY/vXOK5bdsKAU3/fs5bAX8FPaYPjZU7asg4kw4ydsxdAKoCKuqtgGo1LNsguj 2CpUuMn6jv8uGwKC82jxfvMurMPQSc873jxKiEIvTJGHRzYbEDLTiCWGjml8ddgC3NZ+ NEFA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=ps+J+VHXbp4XJj5ocqrKfuqeiIPbRGsmEw5gh9Xkybw=; fh=tXslIEC/iII+0o9YvlUtRXapl6zSPusBr1yEidN1Q7w=; b=D92BA061tfOQKZT00xv8Elqi7Z7cOOCAB3z1HT7pARP1zlJSSzatS6occm3EzckSzD 3vqarQUZaL9euupUOVSpO8V+s9EA07xQRFpdLq3pyofquNijDB4DN70/JdvlywOhEqV8 QbTaImnqP02rc9E0qC1FNYNcotlSr07ty5nbfgNImZ5L5VtonnKauXbBOtqsZGrYQH8y qavlmMQqr4PgQ3HvWsS3UWYiSMRLTlMaQGBrrmwg3UX2aceiAxn+9CM1ZN9AacaYINyS Pjgpd3zH79p1IwysogW2b4KfafVt7hFnSbH8HjWbSsEiYghFxX5IcO8BF8t0RVK9LiM+ yBkw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Ae7HQGVL; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-164216-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-164216-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id pd3-20020a17090b1dc300b002b0f6355af7si6643775pjb.169.2024.04.30.11.58.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Apr 2024 11:58:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-164216-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Ae7HQGVL; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-164216-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-164216-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 9320F28558C for ; Tue, 30 Apr 2024 15:00:55 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id DFEAA143738; Tue, 30 Apr 2024 14:59:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Ae7HQGVL" Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6606317556B for ; Tue, 30 Apr 2024 14:59:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714489152; cv=none; b=RT3fSOjnq0Yqf/QyoVPlDLUd92uNSCcwHuL1KihVqT9m0TkNSMgU6yRe1wJioEZv9Rj8ParL8FQDk5n9aP25eb0i0VswQzGw1H7HNooLfSnw9HwhTW2qv1WGJp82GvL23MKG/hFfBbqr5hdJy9LYro1By28bqcghiAZslBMsLgo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714489152; c=relaxed/simple; bh=RbRitu0aNliYqOdOFIez38o3G2ZOc9u3LX3xSh1/REk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YpRoZ6aJvd4du0QhtJ/8W+a1jjL/Nqrzc6Y3bvnsCPwSF9au6esA2ZAcXU2/+0g0dptBjo+27NADi0XxkWW31T6olRYnjght3guiiSNwaDzVhdkmmXSyEaVEG0P+pl7uBHuf/4TWKgo1K/4jjwO2XbJE5xIrisInwK9VZ5M+JKk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Ae7HQGVL; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1714489152; x=1746025152; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RbRitu0aNliYqOdOFIez38o3G2ZOc9u3LX3xSh1/REk=; b=Ae7HQGVLZjvjwzccAS1gSphpXM6f6rSuize/CRvg4ath1x9z/9wD46oS kJRtP1JYIoxMjIFAYyIszuY4bTZWSDwhbOBvbdlJw2fMBHlj2zoR/+WOB 0R6GRQRgS33vCTopcEK3uY7LV8fbJuJmUC8qQVHEqEysIgdt9VCQFrSYC W+IrAduGufvQ9EpdbD71h952Q/rTwTbimlUr8vKHMds7c/wlc1uplhyxv HxzVcs2ciXbkIHMkc2/dHMg/Jeoqb15GgKqSuUG9uHDnkAcq1mL5d4b60 1BSwkWWdNUTQS+Cqo0sUJ4Nx5FT0M1/dHhoapxPFOWWI5AYvIsKggT114 g==; X-CSE-ConnectionGUID: ndDlnyOITB+lB2UesG/fZg== X-CSE-MsgGUID: dOK+eCN+QTefUOi2TrKBRA== X-IronPort-AV: E=McAfee;i="6600,9927,11060"; a="10059913" X-IronPort-AV: E=Sophos;i="6.07,242,1708416000"; d="scan'208";a="10059913" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Apr 2024 07:59:11 -0700 X-CSE-ConnectionGUID: TJv/Tz6xR0qroJPOE1VCyw== X-CSE-MsgGUID: l12weAd+RBOqJLRpcxy+aw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,242,1708416000"; d="scan'208";a="31282223" Received: from unknown (HELO allen-box.sh.intel.com) ([10.239.159.127]) by orviesa004.jf.intel.com with ESMTP; 30 Apr 2024 07:59:08 -0700 From: Lu Baolu To: Jason Gunthorpe , Kevin Tian , Joerg Roedel , Will Deacon , Robin Murphy , Jean-Philippe Brucker , Nicolin Chen , Yi Liu , Jacob Pan , Joel Granados Cc: iommu@lists.linux.dev, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v5 6/9] iommufd: Fault-capable hwpt attach/detach/replace Date: Tue, 30 Apr 2024 22:57:07 +0800 Message-Id: <20240430145710.68112-7-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240430145710.68112-1-baolu.lu@linux.intel.com> References: <20240430145710.68112-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add iopf-capable hw page table attach/detach/replace helpers. The pointer to iommufd_device is stored in the domain attachment handle, so that it can be echo'ed back in the iopf_group. The iopf-capable hw page tables can only be attached to devices that support the IOMMU_DEV_FEAT_IOPF feature. On the first attachment of an iopf-capable hw_pagetable to the device, the IOPF feature is enabled on the device. Similarly, after the last iopf-capable hwpt is detached from the device, the IOPF feature is disabled on the device. The current implementation allows a replacement between iopf-capable and non-iopf-capable hw page tables. This matches the nested translation use case, where a parent domain is attached by default and can then be replaced with a nested user domain with iopf support. Signed-off-by: Lu Baolu --- drivers/iommu/iommufd/iommufd_private.h | 10 ++ drivers/iommu/iommufd/device.c | 15 ++- drivers/iommu/iommufd/fault.c | 118 ++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h index acb89bbf9f8e..18c8d7d38dcd 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -293,6 +293,7 @@ int iommufd_check_iova_range(struct io_pagetable *iopt, struct iommufd_hw_pagetable { struct iommufd_object obj; struct iommu_domain *domain; + struct iommufd_fault *fault; }; struct iommufd_hwpt_paging { @@ -396,6 +397,7 @@ struct iommufd_device { /* always the physical device */ struct device *dev; bool enforce_cache_coherency; + bool iopf_enabled; /* outstanding faults awaiting response indexed by fault group id */ struct xarray faults; }; @@ -450,6 +452,14 @@ struct iommufd_fault { int iommufd_fault_alloc(struct iommufd_ucmd *ucmd); void iommufd_fault_destroy(struct iommufd_object *obj); +int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt, + struct iommufd_device *idev); +void iommufd_fault_domain_detach_dev(struct iommufd_hw_pagetable *hwpt, + struct iommufd_device *idev); +int iommufd_fault_domain_replace_dev(struct iommufd_device *idev, + struct iommufd_hw_pagetable *hwpt, + struct iommufd_hw_pagetable *old); + #ifdef CONFIG_IOMMUFD_TEST int iommufd_test(struct iommufd_ucmd *ucmd); void iommufd_selftest_destroy(struct iommufd_object *obj); diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 22e22969363a..2bee3f399ec7 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -377,7 +377,10 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, * attachment. */ if (list_empty(&idev->igroup->device_list)) { - rc = iommu_attach_group(hwpt->domain, idev->igroup->group); + if (hwpt->fault) + rc = iommufd_fault_domain_attach_dev(hwpt, idev); + else + rc = iommu_attach_group(hwpt->domain, idev->igroup->group); if (rc) goto err_unresv; idev->igroup->hwpt = hwpt; @@ -403,7 +406,10 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev) mutex_lock(&idev->igroup->lock); list_del(&idev->group_item); if (list_empty(&idev->igroup->device_list)) { - iommu_detach_group(hwpt->domain, idev->igroup->group); + if (hwpt->fault) + iommufd_fault_domain_detach_dev(hwpt, idev); + else + iommu_detach_group(hwpt->domain, idev->igroup->group); idev->igroup->hwpt = NULL; } if (hwpt_is_paging(hwpt)) @@ -498,7 +504,10 @@ iommufd_device_do_replace(struct iommufd_device *idev, goto err_unlock; } - rc = iommu_group_replace_domain(igroup->group, hwpt->domain); + if (old_hwpt->fault || hwpt->fault) + rc = iommufd_fault_domain_replace_dev(idev, hwpt, old_hwpt); + else + rc = iommu_group_replace_domain(igroup->group, hwpt->domain); if (rc) goto err_unresv; diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c index 13125c0feecb..6357229bf3b4 100644 --- a/drivers/iommu/iommufd/fault.c +++ b/drivers/iommu/iommufd/fault.c @@ -15,6 +15,124 @@ #include "../iommu-priv.h" #include "iommufd_private.h" +static int iommufd_fault_iopf_enable(struct iommufd_device *idev) +{ + int ret; + + if (idev->iopf_enabled) + return 0; + + ret = iommu_dev_enable_feature(idev->dev, IOMMU_DEV_FEAT_IOPF); + if (ret) + return ret; + + idev->iopf_enabled = true; + + return 0; +} + +static void iommufd_fault_iopf_disable(struct iommufd_device *idev) +{ + if (!idev->iopf_enabled) + return; + + iommu_dev_disable_feature(idev->dev, IOMMU_DEV_FEAT_IOPF); + idev->iopf_enabled = false; +} + +int iommufd_fault_domain_attach_dev(struct iommufd_hw_pagetable *hwpt, + struct iommufd_device *idev) +{ + struct iommu_attach_handle *handle; + int ret; + + if (!hwpt->fault) + return -EINVAL; + + ret = iommufd_fault_iopf_enable(idev); + if (ret) + return ret; + + ret = iommu_attach_group(hwpt->domain, idev->igroup->group); + if (ret) { + iommufd_fault_iopf_disable(idev); + return ret; + } + + handle = iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0); + handle->idev = idev; + + return 0; +} + +static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt, + struct iommufd_device *idev) +{ + struct iommufd_fault *fault = hwpt->fault; + struct iopf_group *group, *next; + unsigned long index; + + if (!fault) + return; + + mutex_lock(&fault->mutex); + list_for_each_entry_safe(group, next, &fault->deliver, node) { + if (group->domain != hwpt->domain || + group->fault_param->dev != idev->dev) + continue; + list_del(&group->node); + iopf_group_response(group, IOMMU_PAGE_RESP_INVALID); + iopf_free_group(group); + } + + xa_for_each(&idev->faults, index, group) { + if (group->domain != hwpt->domain) + continue; + xa_erase(&idev->faults, index); + iopf_group_response(group, IOMMU_PAGE_RESP_INVALID); + iopf_free_group(group); + } + mutex_unlock(&fault->mutex); +} + +void iommufd_fault_domain_detach_dev(struct iommufd_hw_pagetable *hwpt, + struct iommufd_device *idev) +{ + iommu_detach_group(hwpt->domain, idev->igroup->group); + iommufd_fault_iopf_disable(idev); + iommufd_auto_response_faults(hwpt, idev); +} + +int iommufd_fault_domain_replace_dev(struct iommufd_device *idev, + struct iommufd_hw_pagetable *hwpt, + struct iommufd_hw_pagetable *old) +{ + struct iommu_attach_handle *handle; + int ret; + + if (hwpt->fault) + ret = iommufd_fault_iopf_enable(idev); + else + iommufd_fault_iopf_disable(idev); + + ret = iommu_group_replace_domain(idev->igroup->group, hwpt->domain); + if (ret) + goto out_cleanup; + + iommufd_auto_response_faults(old, idev); + handle = iommu_attach_handle_get(idev->igroup->group, IOMMU_NO_PASID, 0); + handle->idev = idev; + + return 0; +out_cleanup: + if (old->fault) + ret = iommufd_fault_iopf_enable(idev); + else + iommufd_fault_iopf_disable(idev); + + return ret; +} + void iommufd_fault_destroy(struct iommufd_object *obj) { struct iommufd_fault *fault = container_of(obj, struct iommufd_fault, obj); -- 2.34.1