Message ID | 20240122073903.24406-1-baolu.lu@linux.intel.com |
---|---|
Headers |
Return-Path: <linux-kernel+bounces-32451-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp2441170dyb; Mon, 22 Jan 2024 00:48:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IFIInAdyl5jS8au5nmnJPZ7XHhXy5gI+rFGt8FMsGMU3pVPyhnc5bm309GKO5xp+wTuFtPG X-Received: by 2002:a17:902:e548:b0:1d7:4cf0:60a8 with SMTP id n8-20020a170902e54800b001d74cf060a8mr731367plf.97.1705913324674; Mon, 22 Jan 2024 00:48:44 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705913324; cv=pass; d=google.com; s=arc-20160816; b=vQTu/GervWXr6wyvHo39gI2MkdVqqu9iMaq42CoCh50MdqosS86p6Xb2A579QioCnI 9Sb0OdFy77b6my6e0mO8SJj7dBhff6epWY+y60G71cBNsprdlkoVKQtai34Al4lp39SI mmwbsgFWma4Q7PTXi3YifPvMeDVnNB4DqA8PLeIdlfbmSBUuhfIhHFpLBgdkwpaRXufK gF9BYLDtiopu9jPR6dWB6nhJWZEafLA6cWHiaDBiYZXBw4TpgPoQLyNhZ0pZka9Q1A9g LTKPE2pqfe3N3W2+TboGlWebmkjJ/hQ9hbxQs47FmsInnsmYorHmiFgPJ2IHQRFFeWrT 25hQ== 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:message-id:date:subject:cc:to :from:dkim-signature; bh=y6mNd8ukwt/cavaxiLc2Jxy1lq9Hti6hBMLCgyGpW0I=; fh=tXslIEC/iII+0o9YvlUtRXapl6zSPusBr1yEidN1Q7w=; b=SIZQkYAisV3Ab7GkDV/LtulfjFfYVoRTDP4bt4fmmzhk/IpR/GXAQZ98fiqztsO1Ww xHYVQe/jWmxMqd0W52enXfsUibQpYSnDmkN/QTGFx79oEOxRsGAu8BCv3qegXZmBBII3 lgZoZsAKQnV3nQBfc485JNn9bZado3QM0KtoXO+bQISpr33Y5JlsIHBJWTt0wXX9Phq/ 4BU4iNrcHxp7UuHHhxn7cJyUbQ+0jowabZ+0sNgqZnvtON1TBXs+p5eiOqnp0OU1DrIE t/ExpSKRD3yhjP7zLeadzODW3IHmWz081uN6BYVAl1jEWk3hRRVTYyqW8qgYSE+jmA9H ktlg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=iJngVLvI; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-32451-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-32451-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id y9-20020a17090322c900b001d5f3875154si7730175plg.319.2024.01.22.00.48.44 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jan 2024 00:48:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-32451-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=iJngVLvI; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-32451-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-32451-ouuuleilei=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 sy.mirrors.kernel.org (Postfix) with ESMTPS id 0CE22B2424F for <ouuuleilei@gmail.com>; Mon, 22 Jan 2024 07:44:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C15F9171D5; Mon, 22 Jan 2024 07:44:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="iJngVLvI" Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.7]) (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 5E09116416 for <linux-kernel@vger.kernel.org>; Mon, 22 Jan 2024 07:44:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705909474; cv=none; b=r6z/O0/v680yT8sd7VOougL/b6oduXuWibDNY10ovtSH85muni7eo53QPqDk+pSgIbj1z7f5EfwUKqE0OI9r3a1dBk4ozQ3fy6yQpifzPsWolLsyscWb2sFb9/DdQxVRh5xX7qh22p36lRgpSzWzKeTL8sb1U6u9j9YU6MLixCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705909474; c=relaxed/simple; bh=WaeZbozXHzble1W02cueiTjc38Ii0RT3AX9RzeBAuRA=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=pzzcs//BIxEioMR9/cVRdoigU4LVnNzjFBwWsTfJIj36oB8vd4IMGKfslx/c/HzwwTCtO7Fi2gq81NTqlqRlkRU95tLij1cGFxzlVZRoe16yue9fWHtOyqmA88A7IcTaezQzIskYi2tTmOtkMqCIUGAuwLiGPdsjdNQLMF0FP6A= 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=iJngVLvI; arc=none smtp.client-ip=192.198.163.7 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=1705909473; x=1737445473; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=WaeZbozXHzble1W02cueiTjc38Ii0RT3AX9RzeBAuRA=; b=iJngVLvILBFpjOQVM9vO+sOS12IBRx2dgRLz8k8leq5dXUZ2VX4uK6Nc d48mMD8aPqd+ftoScUlV2YpaI5d4USkPrPIp9Z+VPMYKQDNvkhshIxvUc N9mscpKBVNyvwqSFc4QmwE4gcrPob72fuLm++69fRNDeIMiDriTtQ5Rng emzn3Ms4JNgWX/4EK5jPsPQm23zeQ9lNeuiRyhKDFtxb9Rf9z2+K8noeB 4fMBE2Gemmfj8UAAvKpDeESIvZizSsryf7Lq9YX8tG/wDMR+TIRzV7Olo +CwVNK4k09KaZkS37oAI0/5prU5BnToGrlUx1CP6741bHw/3Zdk9xKH+L w==; X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="22611477" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="22611477" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmvoesa101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jan 2024 23:44:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="778504953" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="778504953" Received: from allen-box.sh.intel.com ([10.239.159.127]) by orsmga007.jf.intel.com with ESMTP; 21 Jan 2024 23:44:27 -0800 From: Lu Baolu <baolu.lu@linux.intel.com> To: Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>, Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>, Robin Murphy <robin.murphy@arm.com>, Jean-Philippe Brucker <jean-philippe@linaro.org>, Nicolin Chen <nicolinc@nvidia.com>, Yi Liu <yi.l.liu@intel.com>, Jacob Pan <jacob.jun.pan@linux.intel.com>, Joel Granados <j.granados@samsung.com> Cc: iommu@lists.linux.dev, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com> Subject: [PATCH v3 0/8] IOMMUFD: Deliver IO page faults to user space Date: Mon, 22 Jan 2024 15:38:55 +0800 Message-Id: <20240122073903.24406-1-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788779770605710873 X-GMAIL-MSGID: 1788779770605710873 |
Series |
IOMMUFD: Deliver IO page faults to user space
|
|
Message
Baolu Lu
Jan. 22, 2024, 7:38 a.m. UTC
This series implements the functionality of delivering IO page faults to user space through the IOMMUFD framework. One feasible use case is the nested translation. Nested translation is a hardware feature that supports two-stage translation tables for IOMMU. The second-stage translation table is managed by the host VMM, while the first-stage translation table is owned by user space. This allows user space to control the IOMMU mappings for its devices. When an IO page fault occurs on the first-stage translation table, the IOMMU hardware can deliver the page fault to user space through the IOMMUFD framework. User space can then handle the page fault and respond to the device top-down through the IOMMUFD. This allows user space to implement its own IO page fault handling policies. User space application that is capable of handling IO page faults should allocate a fault object, and bind the fault object to any domain that it is willing to handle the fault generatd for them. On a successful return of fault object allocation, the user can retrieve and respond to page faults by reading or writing to the file descriptor (FD) returned. The iommu selftest framework has been updated to test the IO page fault delivery and response functionality. This series is based on the page fault handling framework refactoring in the IOMMU core [1]. The series and related patches are available on GitHub: [2] [1] https://lore.kernel.org/linux-iommu/20240122054308.23901-1-baolu.lu@linux.intel.com/ [2] https://github.com/LuBaolu/intel-iommu/commits/iommufd-io-pgfault-delivery-v3 Best regards, baolu Change log: v3: - Add iopf domain attach/detach/replace interfaces to manage the reference counters of hwpt and device, ensuring that both can only be destroyed after all outstanding IOPFs have been responded to. - Relocate the fault handling file descriptor from hwpt to a fault object to enable a single fault handling object to be utilized across multiple domains. - Miscellaneous cleanup and performance improvements. v2: https://lore.kernel.org/linux-iommu/20231026024930.382898-1-baolu.lu@linux.intel.com/ - Move all iommu refactoring patches into a sparated series and discuss it in a different thread. The latest patch series [v6] is available at https://lore.kernel.org/linux-iommu/20230928042734.16134-1-baolu.lu@linux.intel.com/ - We discussed the timeout of the pending page fault messages. We agreed that we shouldn't apply any timeout policy for the page fault handling in user space. https://lore.kernel.org/linux-iommu/20230616113232.GA84678@myrica/ - Jason suggested that we adopt a simple file descriptor interface for reading and responding to I/O page requests, so that user space applications can improve performance using io_uring. https://lore.kernel.org/linux-iommu/ZJWjD1ajeem6pK3I@ziepe.ca/ v1: https://lore.kernel.org/linux-iommu/20230530053724.232765-1-baolu.lu@linux.intel.com/ Lu Baolu (8): iommu: Add iopf domain attach/detach/replace interface iommu/sva: Use iopf domain attach/detach interface iommufd: Add fault and response message definitions iommufd: Add iommufd fault object iommufd: Associate fault object with iommufd_hw_pgtable iommufd: IOPF-capable hw page table attach/detach/replace iommufd/selftest: Add IOPF support for mock device iommufd/selftest: Add coverage for IOPF test include/linux/iommu.h | 40 +- drivers/iommu/iommufd/iommufd_private.h | 41 ++ drivers/iommu/iommufd/iommufd_test.h | 8 + include/uapi/linux/iommufd.h | 91 ++++ tools/testing/selftests/iommu/iommufd_utils.h | 83 +++- drivers/iommu/io-pgfault.c | 215 ++++++++-- drivers/iommu/iommu-sva.c | 48 ++- drivers/iommu/iommufd/device.c | 16 +- drivers/iommu/iommufd/fault.c | 391 ++++++++++++++++++ drivers/iommu/iommufd/hw_pagetable.c | 36 +- drivers/iommu/iommufd/main.c | 6 + drivers/iommu/iommufd/selftest.c | 63 +++ tools/testing/selftests/iommu/iommufd.c | 17 + .../selftests/iommu/iommufd_fail_nth.c | 2 +- drivers/iommu/iommufd/Makefile | 1 + 15 files changed, 1001 insertions(+), 57 deletions(-) create mode 100644 drivers/iommu/iommufd/fault.c
Comments
On Mon, 22 Jan 2024 at 15:46, Lu Baolu <baolu.lu@linux.intel.com> wrote: > > When allocating a user iommufd_hw_pagetable, the user space is allowed to > associate a fault object with the hw_pagetable by specifying the fault > object ID in the page table allocation data and setting the > IOMMU_HWPT_FAULT_ID_VALID flag bit. > > On a successful return of hwpt allocation, the user can retrieve and > respond to page faults by reading and writing the file interface of the > fault object. > > Once a fault object has been associated with a hwpt, the hwpt is > iopf-capable, indicated by fault_capable set to true. Attaching, > detaching, or replacing an iopf-capable hwpt to an RID or PASID will > differ from those that are not iopf-capable. The implementation of these > will be introduced in the next patch. > > Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> > --- > drivers/iommu/iommufd/iommufd_private.h | 11 ++++++++ > include/uapi/linux/iommufd.h | 6 +++++ > drivers/iommu/iommufd/fault.c | 14 ++++++++++ > drivers/iommu/iommufd/hw_pagetable.c | 36 +++++++++++++++++++------ > 4 files changed, 59 insertions(+), 8 deletions(-) > > diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h > index 52d83e888bd0..2780bed0c6b1 100644 > --- a/drivers/iommu/iommufd/iommufd_private.h > +++ b/drivers/iommu/iommufd/iommufd_private.h > @@ -293,6 +293,8 @@ 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; > + bool fault_capable : 1; > }; > > struct iommufd_hwpt_paging { > @@ -446,8 +448,17 @@ struct iommufd_fault { > struct wait_queue_head wait_queue; > }; > > +static inline struct iommufd_fault * > +iommufd_get_fault(struct iommufd_ucmd *ucmd, u32 id) > +{ > + return container_of(iommufd_get_object(ucmd->ictx, id, > + IOMMUFD_OBJ_FAULT), > + struct iommufd_fault, obj); > +} > + > int iommufd_fault_alloc(struct iommufd_ucmd *ucmd); > void iommufd_fault_destroy(struct iommufd_object *obj); > +int iommufd_fault_iopf_handler(struct iopf_group *group); > > #ifdef CONFIG_IOMMUFD_TEST > int iommufd_test(struct iommufd_ucmd *ucmd); > diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h > index c32d62b02306..7481cdd57027 100644 > --- a/include/uapi/linux/iommufd.h > +++ b/include/uapi/linux/iommufd.h > @@ -357,10 +357,13 @@ struct iommu_vfio_ioas { > * the parent HWPT in a nesting configuration. > * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU is > * enforced on device attachment > + * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is > + * valid. > */ > enum iommufd_hwpt_alloc_flags { > IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0, > IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1, > + IOMMU_HWPT_FAULT_ID_VALID = 1 << 2, > }; > > /** > @@ -411,6 +414,8 @@ enum iommu_hwpt_data_type { > * @__reserved: Must be 0 > * @data_type: One of enum iommu_hwpt_data_type > * @data_len: Length of the type specific data > + * @fault_id: The ID of IOMMUFD_FAULT object. Valid only if flags field of > + * IOMMU_HWPT_FAULT_ID_VALID is set. > * @data_uptr: User pointer to the type specific data > * > * Explicitly allocate a hardware page table object. This is the same object > @@ -441,6 +446,7 @@ struct iommu_hwpt_alloc { > __u32 __reserved; > __u32 data_type; > __u32 data_len; > + __u32 fault_id; > __aligned_u64 data_uptr; > }; > #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC) > diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c > index 9844a85feeb2..e752d1c49dde 100644 > --- a/drivers/iommu/iommufd/fault.c > +++ b/drivers/iommu/iommufd/fault.c > @@ -253,3 +253,17 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd) > > return rc; > } > + > +int iommufd_fault_iopf_handler(struct iopf_group *group) > +{ > + struct iommufd_hw_pagetable *hwpt = group->cookie->domain->fault_data; > + struct iommufd_fault *fault = hwpt->fault; > + > + mutex_lock(&fault->mutex); > + list_add_tail(&group->node, &fault->deliver); > + mutex_unlock(&fault->mutex); > + > + wake_up_interruptible(&fault->wait_queue); > + > + return 0; > +} > diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c > index 3f3f1fa1a0a9..2703d5aea4f5 100644 > --- a/drivers/iommu/iommufd/hw_pagetable.c > +++ b/drivers/iommu/iommufd/hw_pagetable.c > @@ -8,6 +8,15 @@ > #include "../iommu-priv.h" > #include "iommufd_private.h" > > +static void __iommufd_hwpt_destroy(struct iommufd_hw_pagetable *hwpt) > +{ > + if (hwpt->domain) > + iommu_domain_free(hwpt->domain); > + > + if (hwpt->fault) > + iommufd_put_object(hwpt->fault->ictx, &hwpt->fault->obj); > +} > + > void iommufd_hwpt_paging_destroy(struct iommufd_object *obj) > { > struct iommufd_hwpt_paging *hwpt_paging = > @@ -22,9 +31,7 @@ void iommufd_hwpt_paging_destroy(struct iommufd_object *obj) > hwpt_paging->common.domain); > } > > - if (hwpt_paging->common.domain) > - iommu_domain_free(hwpt_paging->common.domain); > - > + __iommufd_hwpt_destroy(&hwpt_paging->common); > refcount_dec(&hwpt_paging->ioas->obj.users); > } > > @@ -49,9 +56,7 @@ void iommufd_hwpt_nested_destroy(struct iommufd_object *obj) > struct iommufd_hwpt_nested *hwpt_nested = > container_of(obj, struct iommufd_hwpt_nested, common.obj); > > - if (hwpt_nested->common.domain) > - iommu_domain_free(hwpt_nested->common.domain); > - > + __iommufd_hwpt_destroy(&hwpt_nested->common); > refcount_dec(&hwpt_nested->parent->common.obj.users); > } > > @@ -213,7 +218,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, > struct iommufd_hw_pagetable *hwpt; > int rc; > > - if (flags || !user_data->len || !ops->domain_alloc_user) > + if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) || > + !user_data->len || !ops->domain_alloc_user) > return ERR_PTR(-EOPNOTSUPP); > if (parent->auto_domain || !parent->nest_parent) > return ERR_PTR(-EINVAL); > @@ -227,7 +233,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, > refcount_inc(&parent->common.obj.users); > hwpt_nested->parent = parent; > > - hwpt->domain = ops->domain_alloc_user(idev->dev, flags, > + hwpt->domain = ops->domain_alloc_user(idev->dev, 0, > parent->common.domain, user_data); Why remove flags? typo or any reason? arm_smmu_domain_alloc_user can not get flags from the user app. User should set IOMMU_HWPT_FAULT_ID_VALID, right? Thanks