From nobody Tue Apr 7 16:13:03 2026 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4C5353C73F8 for ; Thu, 12 Mar 2026 15:56:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773331002; cv=none; b=JXhjP84jHvzdPC09Z0sTheG3SKNvP9g64kFnvUi/w19CiwTkI9swN2WZ/s68hYb8OxPPAmutPEXLeRCyW4cT6uHq4dqj46/VndiIl4LEa0XChq8ocAy3S7EhwD7SrUMPitFJhIDT0VSF/1QqeJJYSa7lgjmYS6EDCo75AyoQRaQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773331002; c=relaxed/simple; bh=jq5qTcsaoCOYsl1jW0F01Uz6kAYc6e2RZaLegbuHqqs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cXwgX4vPGesAnmSZ+m/mdBEhp2MtoFtxeAWDVPtrbSiVAbn9h8M+BE668akh4CZz2WqRL9FF/cSjDFEjz1jYQGjHgKXe0yvNP6xN1fnv6JWJfF3CKnN00lI5Rgh6jb9I2NHRV1a24ui8QpMa2n5RSa7JayTWrl3dEG+oWV16wSY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=BJAVaP6J; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="BJAVaP6J" Received: from DESKTOP-0403QTC.corp.microsoft.com (unknown [52.148.138.235]) by linux.microsoft.com (Postfix) with ESMTPSA id 3A03420B6F08; Thu, 12 Mar 2026 08:56:39 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 3A03420B6F08 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1773330999; bh=1aYAnL2eR52QY8qJUJRJndthj5NuHcgN66qFz2M8XyQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BJAVaP6JqME4zdg/8KGPnFuoMGvANyUNsZZrk6r0gqsvpcjm2W7RLn0Qyqi/dSr8y jx4gUCmE8lxvnRIdRtCUF3O0bkLdRVgWwHJ+Dzky9E+96P9zFGLjfZGr3aAgu1nYfq 7KMegAWzVZBs5+qil3PnF7Ct0prsBUhVZjQFcTx0= From: Jacob Pan To: linux-kernel@vger.kernel.org, "iommu@lists.linux.dev" , Jason Gunthorpe , Alex Williamson , Joerg Roedel , David Matlack , Robin Murphy , Nicolin Chen , "Tian, Kevin" , Yi Liu Cc: skhawaja@google.com, pasha.tatashin@soleen.com, Will Deacon , Jacob Pan , Baolu Lu Subject: [PATCH V2 01/11] iommufd: Support a HWPT without an iommu driver for noiommu Date: Thu, 12 Mar 2026 08:56:27 -0700 Message-Id: <20260312155637.376854-2-jacob.pan@linux.microsoft.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260312155637.376854-1-jacob.pan@linux.microsoft.com> References: <20260312155637.376854-1-jacob.pan@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jason Gunthorpe Create just a little part of a real iommu driver, enough to slot in under the dev_iommu_ops() and allow iommufd to call domain_alloc_paging_flags() and fail everything else. This allows explicitly creating a HWPT under an IOAS. Signed-off-by: Jason Gunthorpe Signed-off-by: Jacob Pan --- drivers/iommu/iommufd/Makefile | 1 + drivers/iommu/iommufd/hw_pagetable.c | 11 ++- drivers/iommu/iommufd/hwpt_noiommu.c | 91 +++++++++++++++++++++++++ drivers/iommu/iommufd/iommufd_private.h | 2 + 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 drivers/iommu/iommufd/hwpt_noiommu.c diff --git a/drivers/iommu/iommufd/Makefile b/drivers/iommu/iommufd/Makefile index 71d692c9a8f4..2b1a020b14a6 100644 --- a/drivers/iommu/iommufd/Makefile +++ b/drivers/iommu/iommufd/Makefile @@ -10,6 +10,7 @@ iommufd-y :=3D \ vfio_compat.o \ viommu.o =20 +iommufd-$(CONFIG_VFIO_NOIOMMU) +=3D hwpt_noiommu.o iommufd-$(CONFIG_IOMMUFD_TEST) +=3D selftest.o =20 obj-$(CONFIG_IOMMUFD) +=3D iommufd.o diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/h= w_pagetable.c index fe789c2dc0c9..37316d77277d 100644 --- a/drivers/iommu/iommufd/hw_pagetable.c +++ b/drivers/iommu/iommufd/hw_pagetable.c @@ -8,6 +8,13 @@ #include "../iommu-priv.h" #include "iommufd_private.h" =20 +static const struct iommu_ops *get_iommu_ops(struct iommufd_device *idev) +{ + if (IS_ENABLED(CONFIG_VFIO_NOIOMMU) && !idev->igroup->group) + return &iommufd_noiommu_ops; + return dev_iommu_ops(idev->dev); +} + static void __iommufd_hwpt_destroy(struct iommufd_hw_pagetable *hwpt) { if (hwpt->domain) @@ -114,7 +121,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, str= uct iommufd_ioas *ioas, IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_FAULT_ID_VALID | IOMMU_HWPT_ALLOC_PASID; - const struct iommu_ops *ops =3D dev_iommu_ops(idev->dev); + const struct iommu_ops *ops =3D get_iommu_ops(idev); struct iommufd_hwpt_paging *hwpt_paging; struct iommufd_hw_pagetable *hwpt; int rc; @@ -229,7 +236,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, struct iommufd_device *idev, u32 flags, const struct iommu_user_data *user_data) { - const struct iommu_ops *ops =3D dev_iommu_ops(idev->dev); + const struct iommu_ops *ops =3D get_iommu_ops(idev); struct iommufd_hwpt_nested *hwpt_nested; struct iommufd_hw_pagetable *hwpt; int rc; diff --git a/drivers/iommu/iommufd/hwpt_noiommu.c b/drivers/iommu/iommufd/h= wpt_noiommu.c new file mode 100644 index 000000000000..0aa99f581ca3 --- /dev/null +++ b/drivers/iommu/iommufd/hwpt_noiommu.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES + */ +#include +#include +#include "iommufd_private.h" + +static const struct iommu_domain_ops noiommu_amdv1_ops; + +struct noiommu_domain { + union { + struct iommu_domain domain; + struct pt_iommu_amdv1 amdv1; + }; + spinlock_t lock; +}; +PT_IOMMU_CHECK_DOMAIN(struct noiommu_domain, amdv1.iommu, domain); + +static void noiommu_change_top(struct pt_iommu *iommu_table, + phys_addr_t top_paddr, unsigned int top_level) +{ +} + +static spinlock_t *noiommu_get_top_lock(struct pt_iommu *iommupt) +{ + struct noiommu_domain *domain =3D + container_of(iommupt, struct noiommu_domain, amdv1.iommu); + + return &domain->lock; +} + +static const struct pt_iommu_driver_ops noiommu_driver_ops =3D { + .get_top_lock =3D noiommu_get_top_lock, + .change_top =3D noiommu_change_top, +}; + +static struct iommu_domain * +noiommu_alloc_paging_flags(struct device *dev, u32 flags, + const struct iommu_user_data *user_data) +{ + struct pt_iommu_amdv1_cfg cfg =3D {}; + struct noiommu_domain *dom; + int rc; + + if (flags || user_data) + return ERR_PTR(-EOPNOTSUPP); + + cfg.common.hw_max_vasz_lg2 =3D 64; + cfg.common.hw_max_oasz_lg2 =3D 52; + cfg.starting_level =3D 2; + cfg.common.features =3D + (BIT(PT_FEAT_DYNAMIC_TOP) | BIT(PT_FEAT_AMDV1_ENCRYPT_TABLES) | + BIT(PT_FEAT_AMDV1_FORCE_COHERENCE)); + + dom =3D kzalloc(sizeof(*dom), GFP_KERNEL); + if (!dom) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&dom->lock); + dom->amdv1.iommu.nid =3D NUMA_NO_NODE; + dom->amdv1.iommu.driver_ops =3D &noiommu_driver_ops; + dom->domain.ops =3D &noiommu_amdv1_ops; + + /* Use mock page table which is based on AMDV1 */ + rc =3D pt_iommu_amdv1_init(&dom->amdv1, &cfg, GFP_KERNEL); + if (rc) { + kfree(dom); + return ERR_PTR(rc); + } + + return &dom->domain; +} + +static void noiommu_domain_free(struct iommu_domain *iommu_domain) +{ + struct noiommu_domain *domain =3D + container_of(iommu_domain, struct noiommu_domain, domain); + + pt_iommu_deinit(&domain->amdv1.iommu); + kfree(domain); +} + +static const struct iommu_domain_ops noiommu_amdv1_ops =3D { + IOMMU_PT_DOMAIN_OPS(amdv1), + .free =3D noiommu_domain_free, +}; + +struct iommu_ops iommufd_noiommu_ops =3D { + .domain_alloc_paging_flags =3D noiommu_alloc_paging_flags, +}; diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommuf= d/iommufd_private.h index 6ac1965199e9..9c18c5eb1899 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -464,6 +464,8 @@ static inline void iommufd_hw_pagetable_put(struct iomm= ufd_ctx *ictx, refcount_dec(&hwpt->obj.users); } =20 +extern struct iommu_ops iommufd_noiommu_ops; + struct iommufd_attach; =20 struct iommufd_group { --=20 2.34.1