From: Zhenzhong Duan <zhenzhong.duan@intel.com>
To: qemu-devel@nongnu.org
Cc: alex.williamson@redhat.com, clg@redhat.com,
eric.auger@redhat.com, mst@redhat.com, jasowang@redhat.com,
peterx@redhat.com, ddutile@redhat.com, jgg@nvidia.com,
nicolinc@nvidia.com, shameerali.kolothum.thodi@huawei.com,
joao.m.martins@oracle.com, clement.mathieu--drif@eviden.com,
kevin.tian@intel.com, yi.l.liu@intel.com, chao.p.peng@intel.com,
Yi Sun <yi.y.sun@linux.intel.com>,
Zhenzhong Duan <zhenzhong.duan@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Richard Henderson <richard.henderson@linaro.org>,
Eduardo Habkost <eduardo@habkost.net>,
Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Subject: [PATCH v2 16/19] intel_iommu: Propagate PASID-based iotlb invalidation to host
Date: Fri, 20 Jun 2025 15:18:10 +0800 [thread overview]
Message-ID: <20250620071813.55571-17-zhenzhong.duan@intel.com> (raw)
In-Reply-To: <20250620071813.55571-1-zhenzhong.duan@intel.com>
From: Yi Liu <yi.l.liu@intel.com>
This traps the guest PASID-based iotlb invalidation request and propagate it
to host.
Intel VT-d 3.0 supports nested translation in PASID granular. Guest SVA support
could be implemented by configuring nested translation on specific PASID. This
is also known as dual stage DMA translation.
Under such configuration, guest owns the GVA->GPA translation which is
configured as stage-1 page table in host side for a specific pasid, and host
owns GPA->HPA translation. As guest owns stage-1 translation table, piotlb
invalidation should be propagated to host since host IOMMU will cache first
level page table related mappings during DMA address translation.
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
---
hw/i386/intel_iommu_internal.h | 6 ++
hw/i386/intel_iommu.c | 113 ++++++++++++++++++++++++++++++++-
2 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index b3e4aa23f1..07bfb97499 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -589,6 +589,12 @@ typedef struct VTDPASIDCacheInfo {
bool error_happened;
} VTDPASIDCacheInfo;
+typedef struct VTDPIOTLBInvInfo {
+ uint16_t domain_id;
+ uint32_t pasid;
+ struct iommu_hwpt_vtd_s1_invalidate *inv_data;
+} VTDPIOTLBInvInfo;
+
/* PASID Table Related Definitions */
#define VTD_PASID_DIR_BASE_ADDR_MASK (~0xfffULL)
#define VTD_PASID_TABLE_BASE_ADDR_MASK (~0xfffULL)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 621b07aa02..d1fa395274 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2639,12 +2639,105 @@ static int vtd_bind_guest_pasid(VTDAddressSpace *vtd_as,
return ret;
}
+
+/*
+ * Caller of this function should hold iommu_lock.
+ */
+static void vtd_invalidate_piotlb(VTDAddressSpace *vtd_as,
+ struct iommu_hwpt_vtd_s1_invalidate *cache)
+{
+ VTDHostIOMMUDevice *vtd_hiod;
+ HostIOMMUDeviceIOMMUFD *idev;
+ int devfn = vtd_as->devfn;
+ struct vtd_as_key key = {
+ .bus = vtd_as->bus,
+ .devfn = devfn,
+ };
+ IntelIOMMUState *s = vtd_as->iommu_state;
+ uint32_t entry_num = 1; /* Only implement one request for simplicity */
+ Error *err;
+
+ vtd_hiod = g_hash_table_lookup(s->vtd_host_iommu_dev, &key);
+ if (!vtd_hiod || !vtd_hiod->hiod) {
+ return;
+ }
+ idev = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
+
+ if (!iommufd_backend_invalidate_cache(idev->iommufd, vtd_hiod->s1_hwpt,
+ IOMMU_HWPT_INVALIDATE_DATA_VTD_S1,
+ sizeof(*cache), &entry_num, cache,
+ &err)) {
+ error_report_err(err);
+ }
+}
+
+/*
+ * This function is a loop function for the s->vtd_address_spaces
+ * list with VTDPIOTLBInvInfo as execution filter. It propagates
+ * the piotlb invalidation to host. Caller of this function
+ * should hold iommu_lock.
+ */
+static void vtd_flush_pasid_iotlb(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ VTDPIOTLBInvInfo *piotlb_info = user_data;
+ VTDAddressSpace *vtd_as = value;
+ VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;
+ uint32_t pasid;
+ uint16_t did;
+
+ /* Replay only fill pasid entry cache for passthrough device */
+ if (!pc_entry->cache_filled ||
+ !vtd_pe_pgtt_is_flt(&pc_entry->pasid_entry)) {
+ return;
+ }
+
+ if (vtd_as_to_iommu_pasid_locked(vtd_as, &pasid)) {
+ return;
+ }
+
+ did = vtd_pe_get_did(&pc_entry->pasid_entry);
+
+ if (piotlb_info->domain_id == did && piotlb_info->pasid == pasid) {
+ vtd_invalidate_piotlb(vtd_as, piotlb_info->inv_data);
+ }
+}
+
+static void vtd_flush_pasid_iotlb_all(IntelIOMMUState *s,
+ uint16_t domain_id, uint32_t pasid,
+ hwaddr addr, uint64_t npages, bool ih)
+{
+ struct iommu_hwpt_vtd_s1_invalidate cache_info = { 0 };
+ VTDPIOTLBInvInfo piotlb_info;
+
+ cache_info.addr = addr;
+ cache_info.npages = npages;
+ cache_info.flags = ih ? IOMMU_VTD_INV_FLAGS_LEAF : 0;
+
+ piotlb_info.domain_id = domain_id;
+ piotlb_info.pasid = pasid;
+ piotlb_info.inv_data = &cache_info;
+
+ /*
+ * Here loops all the vtd_as instances in s->vtd_address_spaces
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+ g_hash_table_foreach(s->vtd_address_spaces,
+ vtd_flush_pasid_iotlb, &piotlb_info);
+}
#else
static int vtd_bind_guest_pasid(VTDAddressSpace *vtd_as,
VTDPASIDEntry *pe, VTDPASIDOp op)
{
return 0;
}
+
+static void vtd_flush_pasid_iotlb_all(IntelIOMMUState *s,
+ uint16_t domain_id, uint32_t pasid,
+ hwaddr addr, uint64_t npages, bool ih)
+{
+}
#endif
/* Do a context-cache device-selective invalidation.
@@ -3300,6 +3393,13 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
info.pasid = pasid;
vtd_iommu_lock(s);
+ /*
+ * Here loops all the vtd_as instances in s->vtd_as
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+ vtd_flush_pasid_iotlb_all(s, domain_id, pasid, 0, (uint64_t)-1, 0);
+
g_hash_table_foreach_remove(s->iotlb, vtd_hash_remove_by_pasid,
&info);
vtd_iommu_unlock(s);
@@ -3323,7 +3423,8 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
}
static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
- uint32_t pasid, hwaddr addr, uint8_t am)
+ uint32_t pasid, hwaddr addr, uint8_t am,
+ bool ih)
{
VTDIOTLBPageInvInfo info;
@@ -3333,6 +3434,13 @@ static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
info.mask = ~((1 << am) - 1);
vtd_iommu_lock(s);
+ /*
+ * Here loops all the vtd_as instances in s->vtd_as
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+ vtd_flush_pasid_iotlb_all(s, domain_id, pasid, addr, 1 << am, ih);
+
g_hash_table_foreach_remove(s->iotlb,
vtd_hash_remove_by_page_piotlb, &info);
vtd_iommu_unlock(s);
@@ -3366,7 +3474,8 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
case VTD_INV_DESC_PIOTLB_PSI_IN_PASID:
am = VTD_INV_DESC_PIOTLB_AM(inv_desc->val[1]);
addr = (hwaddr) VTD_INV_DESC_PIOTLB_ADDR(inv_desc->val[1]);
- vtd_piotlb_page_invalidate(s, domain_id, pasid, addr, am);
+ vtd_piotlb_page_invalidate(s, domain_id, pasid, addr, am,
+ VTD_INV_DESC_PIOTLB_IH(inv_desc->val[1]));
break;
default:
--
2.34.1
next prev parent reply other threads:[~2025-06-20 7:25 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-20 7:17 [PATCH v2 00/19] intel_iommu: Enable stage-1 translation for passthrough device Zhenzhong Duan
2025-06-20 7:17 ` [PATCH v2 01/19] intel_iommu: Rename vtd_ce_get_rid2pasid_entry to vtd_ce_get_pasid_entry Zhenzhong Duan
2025-06-20 7:17 ` [PATCH v2 02/19] hw/pci: Introduce pci_device_get_viommu_cap() Zhenzhong Duan
2025-06-20 7:53 ` Eric Auger
2025-06-23 2:20 ` Duan, Zhenzhong
2025-06-23 9:30 ` Eric Auger
2025-06-20 7:17 ` [PATCH v2 03/19] intel_iommu: Implement get_viommu_cap() callback Zhenzhong Duan
2025-06-20 8:10 ` Eric Auger
2025-06-23 2:20 ` Duan, Zhenzhong
2025-06-20 7:17 ` [PATCH v2 04/19] vfio/iommufd: Force creating nested parent domain Zhenzhong Duan
2025-06-20 8:08 ` Eric Auger
2025-06-23 2:33 ` Duan, Zhenzhong
2025-06-20 7:17 ` [PATCH v2 05/19] hw/pci: Export pci_device_get_iommu_bus_devfn() and return bool Zhenzhong Duan
2025-06-20 11:59 ` Eric Auger
2025-06-23 2:47 ` Duan, Zhenzhong
2025-06-23 9:31 ` Eric Auger
2025-06-20 7:18 ` [PATCH v2 06/19] intel_iommu: Introduce a new structure VTDHostIOMMUDevice Zhenzhong Duan
2025-06-20 7:18 ` [PATCH v2 07/19] intel_iommu: Check for compatibility with IOMMUFD backed device when x-flts=on Zhenzhong Duan
2025-06-20 12:05 ` Eric Auger
2025-06-23 2:44 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 08/19] intel_iommu: Fail passthrough device under PCI bridge if x-flts=on Zhenzhong Duan
2025-06-20 12:18 ` Eric Auger
2025-06-23 3:20 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 09/19] intel_iommu: Introduce two helpers vtd_as_from/to_iommu_pasid_locked Zhenzhong Duan
2025-06-20 12:46 ` Eric Auger
2025-06-24 2:48 ` Duan, Zhenzhong
2025-07-07 3:12 ` Duan, Zhenzhong
2025-07-07 16:54 ` Eric Auger
2025-07-08 2:35 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 10/19] intel_iommu: Handle PASID entry removing and updating Zhenzhong Duan
2025-06-20 15:44 ` Eric Auger
2025-06-24 3:34 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 11/19] intel_iommu: Handle PASID entry adding Zhenzhong Duan
2025-06-23 11:47 ` Eric Auger
2025-06-24 10:56 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 12/19] intel_iommu: Introduce a new pasid cache invalidation type FORCE_RESET Zhenzhong Duan
2025-06-23 11:55 ` Eric Auger
2025-06-26 8:28 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 13/19] intel_iommu: Stick to system MR for IOMMUFD backed host device when x-fls=on Zhenzhong Duan
2025-06-23 12:02 ` Eric Auger
2025-06-26 8:37 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 14/19] intel_iommu: Bind/unbind guest page table to host Zhenzhong Duan
2025-06-23 13:17 ` Eric Auger
2025-06-26 9:17 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 15/19] intel_iommu: Replay pasid binds after context cache invalidation Zhenzhong Duan
2025-06-23 13:25 ` Eric Auger
2025-06-26 9:27 ` Duan, Zhenzhong
2025-06-20 7:18 ` Zhenzhong Duan [this message]
2025-06-23 13:41 ` [PATCH v2 16/19] intel_iommu: Propagate PASID-based iotlb invalidation to host Eric Auger
2025-06-26 9:42 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 17/19] intel_iommu: Refresh pasid bind when either SRTP or TE bit is changed Zhenzhong Duan
2025-06-23 13:48 ` Eric Auger
2025-06-26 10:16 ` Duan, Zhenzhong
2025-06-20 7:18 ` [PATCH v2 18/19] Workaround for ERRATA_772415_SPR17 Zhenzhong Duan
2025-06-20 16:01 ` Eric Auger
2025-06-23 3:29 ` Duan, Zhenzhong
2025-06-23 9:33 ` Eric Auger
2025-06-20 7:18 ` [PATCH v2 19/19] intel_iommu: Enable host device when x-flts=on in scalable mode Zhenzhong Duan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250620071813.55571-17-zhenzhong.duan@intel.com \
--to=zhenzhong.duan@intel.com \
--cc=alex.williamson@redhat.com \
--cc=chao.p.peng@intel.com \
--cc=clement.mathieu--drif@eviden.com \
--cc=clg@redhat.com \
--cc=ddutile@redhat.com \
--cc=eduardo@habkost.net \
--cc=eric.auger@redhat.com \
--cc=jasowang@redhat.com \
--cc=jgg@nvidia.com \
--cc=joao.m.martins@oracle.com \
--cc=kevin.tian@intel.com \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=nicolinc@nvidia.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=yi.l.liu@intel.com \
--cc=yi.y.sun@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).