static void vtd_address_space_refresh_all(IntelIOMMUState *s);
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
static void vtd_replay_pasid_bindings_all(IntelIOMMUState *s);
+static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,
+ gpointer user_data);
static void vtd_pasid_cache_reset_locked(IntelIOMMUState *s)
{
* VT-d emulation codes.
*/
vtd_iommu_replay_all(s);
+ /*
+ * Same for pasid cache invalidation, per VT-d spec 6.5.2.1, a global
+ * context cache invalidation should be followed by global PASID cache
+ * invalidation. In order to work with guest not following spec,
+ * handle global PASID cache invalidation here.
+ */
+ vtd_replay_pasid_bindings_all(s);
+}
+
+static void vtd_pasid_cache_devsi(VTDAddressSpace *vtd_as)
+{
+ IntelIOMMUState *s = vtd_as->iommu_state;
+ PCIBus *bus = vtd_as->bus;
+ uint8_t devfn = vtd_as->devfn;
+ struct vtd_as_key key = {
+ .bus = bus,
+ .devfn = devfn,
+ .pasid = vtd_as->pasid,
+ };
+ VTDPASIDCacheInfo pc_info;
+
+ if (!s->fsts || !s->root_scalable || !s->dmar_enabled) {
+ return;
+ }
+
+ trace_vtd_pasid_cache_devsi(pci_bus_num(bus),
+ VTD_PCI_SLOT(devfn), VTD_PCI_FUNC(devfn));
+
+ /* We fake to be global invalidation just to bypass all checks */
+ pc_info.type = VTD_INV_DESC_PASIDC_G_GLOBAL;
+ vtd_pasid_cache_sync_locked(&key, vtd_as, &pc_info);
}
/* Do a context-cache device-selective invalidation.
* happened.
*/
vtd_address_space_sync(vtd_as);
+ /*
+ * Per spec 6.5.2.1, context flush should be followed by PASID
+ * cache and iotlb flush. In order to work with a guest which does
+ * not follow spec and missed PASID cache flush, e.g., linux
+ * 6.7.0-rc2, we have vtd_pasid_cache_devsi() to invalidate PASID
+ * cache of passthrough device. Host iommu driver would flush
+ * piotlb when a pasid unbind is passed down to it.
+ */
+ vtd_pasid_cache_devsi(vtd_as);
}
}
}
vtd_inv_desc_pasid_cache_gsi(void) ""
vtd_inv_desc_pasid_cache_dsi(uint16_t domain) "Domain selective PC invalidation domain 0x%"PRIx16
vtd_inv_desc_pasid_cache_psi(uint16_t domain, uint32_t pasid) "PASID selective PC invalidation domain 0x%"PRIx16" pasid 0x%"PRIx32
+vtd_pasid_cache_devsi(uint8_t bus, uint8_t dev, uint8_t fn) "Dev selective PC invalidation dev: %02"PRIx8":%02"PRIx8".%02"PRIx8
vtd_re_not_present(uint8_t bus) "Root entry bus %"PRIu8" not present"
vtd_ce_not_present(uint8_t bus, uint8_t devfn) "Context entry bus %"PRIu8" devfn %"PRIu8" not present"
vtd_iotlb_page_hit(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t domain) "IOTLB page hit sid 0x%"PRIx16" iova 0x%"PRIx64" slpte 0x%"PRIx64" domain 0x%"PRIx16