[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH rfcv1 14/23] intel_iommu: propagate PASID-based iotlb invalidatio
|
From: |
Zhenzhong Duan |
|
Subject: |
[PATCH rfcv1 14/23] intel_iommu: propagate PASID-based iotlb invalidation to host |
|
Date: |
Mon, 15 Jan 2024 18:37:26 +0800 |
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 | 7 +++
hw/i386/intel_iommu.c | 103 +++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 40361de207..ed0d5cd99b 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -560,6 +560,13 @@ struct VTDPASIDCacheInfo {
};
typedef struct VTDPASIDCacheInfo VTDPASIDCacheInfo;
+struct VTDPIOTLBInvInfo {
+ uint16_t domain_id;
+ uint32_t pasid;
+ struct iommu_hwpt_vtd_s1_invalidate *inv_data;
+};
+typedef struct VTDPIOTLBInvInfo 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 6aa44b80d6..2912fc6b88 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3786,15 +3786,118 @@ static bool vtd_process_pasid_desc(IntelIOMMUState *s,
return !pc_info.error_happened ? true : false;
}
+/**
+ * Caller of this function should hold iommu_lock.
+ */
+static void vtd_invalidate_piotlb(VTDPASIDAddressSpace *vtd_pasid_as,
+ struct iommu_hwpt_vtd_s1_invalidate *cache)
+{
+ VTDIOMMUFDDevice *vtd_idev;
+ VTDHwpt *hwpt = &vtd_pasid_as->hwpt;
+ int devfn = vtd_pasid_as->devfn;
+ struct vtd_as_key key = {
+ .bus = vtd_pasid_as->bus,
+ .devfn = devfn,
+ };
+ IntelIOMMUState *s = vtd_pasid_as->iommu_state;
+ uint32_t entry_num = 1; /* Only implement one request for simplicity */
+
+ if (!hwpt) {
+ return;
+ }
+
+ vtd_idev = g_hash_table_lookup(s->vtd_iommufd_dev, &key);
+ if (!vtd_idev || !vtd_idev->idev) {
+ return;
+ }
+ if (iommufd_backend_invalidate_cache(vtd_idev->idev->iommufd,
hwpt->hwpt_id,
+ IOMMU_HWPT_INVALIDATE_DATA_VTD_S1,
+ sizeof(*cache), &entry_num, cache)) {
+ error_report("Cache flush failed, entry_num %d", entry_num);
+ }
+}
+
+/**
+ * This function is a loop function for the s->vtd_pasid_as
+ * 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;
+ VTDPASIDAddressSpace *vtd_pasid_as = value;
+ VTDPASIDCacheEntry *pc_entry = &vtd_pasid_as->pasid_cache_entry;
+ uint16_t did;
+
+ if (!vtd_pe_pgtt_is_flt(&pc_entry->pasid_entry)) {
+ return;
+ }
+
+ did = vtd_pe_get_domain_id(&pc_entry->pasid_entry);
+
+ if ((piotlb_info->domain_id == did) &&
+ (piotlb_info->pasid == vtd_pasid_as->pasid)) {
+ vtd_invalidate_piotlb(vtd_pasid_as,
+ piotlb_info->inv_data);
+ }
+
+ /*
+ * TODO: needs to add QEMU piotlb flush when QEMU piotlb
+ * infrastructure is ready. For now, it is enough for passthru
+ * devices.
+ */
+}
+
static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
uint16_t domain_id, uint32_t pasid)
{
+ struct iommu_hwpt_vtd_s1_invalidate cache_info = { 0 };
+ VTDPIOTLBInvInfo piotlb_info;
+
+ cache_info.addr = 0;
+ cache_info.npages = (uint64_t)-1;
+
+ piotlb_info.domain_id = domain_id;
+ piotlb_info.pasid = pasid;
+ piotlb_info.inv_data = &cache_info;
+
+ vtd_iommu_lock(s);
+ /*
+ * Here loops all the vtd_pasid_as instances in s->vtd_pasid_as
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+ g_hash_table_foreach(s->vtd_pasid_as,
+ vtd_flush_pasid_iotlb, &piotlb_info);
+ vtd_iommu_unlock(s);
}
static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
uint32_t pasid, hwaddr addr, uint8_t am,
bool ih)
{
+ struct iommu_hwpt_vtd_s1_invalidate cache_info = { 0 };
+ VTDPIOTLBInvInfo piotlb_info;
+
+ cache_info.addr = addr;
+ cache_info.npages = 1 << am;
+ 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;
+
+ vtd_iommu_lock(s);
+ /*
+ * Here loops all the vtd_pasid_as instances in s->vtd_pasid_as
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+ g_hash_table_foreach(s->vtd_pasid_as,
+ vtd_flush_pasid_iotlb, &piotlb_info);
+ vtd_iommu_unlock(s);
}
static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
--
2.34.1
- [PATCH rfcv1 04/23] vfio: implement IOMMUFDDevice interface callbacks, (continued)
- [PATCH rfcv1 04/23] vfio: implement IOMMUFDDevice interface callbacks, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 05/23] intel_iommu: add a placeholder variable for scalable modern mode, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 06/23] intel_iommu: check and sync host IOMMU cap/ecap in scalable modern mode, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 07/23] intel_iommu: process PASID cache invalidation, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 08/23] intel_iommu: add PASID cache management infrastructure, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 09/23] vfio/iommufd_device: Add ioas_id in IOMMUFDDevice and pass to vIOMMU, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 10/23] intel_iommu: bind/unbind guest page table to host, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 11/23] intel_iommu: ERRATA_772415 workaround, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 12/23] intel_iommu: replay pasid binds after context cache invalidation, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 13/23] intel_iommu: process PASID-based iotlb invalidation, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 14/23] intel_iommu: propagate PASID-based iotlb invalidation to host,
Zhenzhong Duan <=
- [PATCH rfcv1 15/23] intel_iommu: process PASID-based Device-TLB invalidation, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 16/23] intel_iommu: rename slpte in iotlb_entry to pte, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 17/23] intel_iommu: implement firt level translation, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 18/23] intel_iommu: fix the fault reason report, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 21/23] intel_iommu: invalidate piotlb when flush pasid, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 20/23] intel_iommu: piotlb invalidation should notify unmap, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 19/23] intel_iommu: introduce pasid iotlb cache, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 22/23] intel_iommu: refresh pasid bind after pasid cache force reset, Zhenzhong Duan, 2024/01/15
- [PATCH rfcv1 23/23] intel_iommu: modify x-scalable-mode to be string option, Zhenzhong Duan, 2024/01/15