mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-22 09:17:58 +00:00
hv: vtd: export iommu_flush_cache
VT-d shares the EPT tables as the second level translation tables. For the IOMMUs that don't support page-walk coherecy, cpu cache should be flushed for the IOMMU EPT entries that are modified. For the current implementation, EPT tables for translating from GPA to HPA for EPT/IOMMU are not modified after VM is created, so cpu cache invlidation is done once per VM before starting execution of VM. However, this may be changed, runtime EPT modification is possible. When cpu cache of EPT entries is invalidated when modification, there is no need invalidate cpu cache globally per VM. This patch exports iommu_flush_cache for EPT entry cache invlidation operations. - IOMMUs share the same copy of EPT table, cpu cache should be flushed if any of the IOMMU active doesn't support page-walk coherency. - In the context of ACRN, GPA to HPA mapping relationship is not changed after VM created, skip flushing iotlb to avoid potential performance penalty. Tracked-On: #4120 Signed-off-by: Binbin Wu <binbin.wu@intel.com> Reviewed-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
@@ -284,16 +284,18 @@ static inline void dmar_wait_completion(const struct dmar_drhd_rt *dmar_unit, ui
|
||||
}
|
||||
}
|
||||
|
||||
/* flush cache when root table, context table updated */
|
||||
static void iommu_flush_cache(const struct dmar_drhd_rt *dmar_unit,
|
||||
void *p, uint32_t size)
|
||||
/* Flush CPU cache when root table, context table or second-level translation teable updated
|
||||
* In the context of ACRN, GPA to HPA mapping relationship is not changed after VM created,
|
||||
* skip flushing iotlb to avoid performance penalty.
|
||||
*/
|
||||
void iommu_flush_cache(const void *p, uint32_t size)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* if vtd support page-walk coherency, no need to flush cacheline */
|
||||
if (iommu_ecap_c(dmar_unit->ecap) == 0U) {
|
||||
if (!iommu_page_walk_coherent) {
|
||||
for (i = 0U; i < size; i += CACHE_LINE_SIZE) {
|
||||
clflush((char *)p + i);
|
||||
clflush((const char *)p + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1077,7 +1079,7 @@ static int32_t add_iommu_device(struct iommu_domain *domain, uint16_t segment, u
|
||||
|
||||
root_entry->hi_64 = 0UL;
|
||||
root_entry->lo_64 = lo_64;
|
||||
iommu_flush_cache(dmar_unit, root_entry, sizeof(struct dmar_entry));
|
||||
iommu_flush_cache(root_entry, sizeof(struct dmar_entry));
|
||||
} else {
|
||||
context_table_addr = dmar_get_bitslice(root_entry->lo_64,
|
||||
ROOT_ENTRY_LOWER_CTP_MASK, ROOT_ENTRY_LOWER_CTP_POS);
|
||||
@@ -1132,7 +1134,7 @@ static int32_t add_iommu_device(struct iommu_domain *domain, uint16_t segment, u
|
||||
|
||||
context_entry->hi_64 = hi_64;
|
||||
context_entry->lo_64 = lo_64;
|
||||
iommu_flush_cache(dmar_unit, context_entry, sizeof(struct dmar_entry));
|
||||
iommu_flush_cache(context_entry, sizeof(struct dmar_entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1181,7 +1183,7 @@ static int32_t remove_iommu_device(const struct iommu_domain *domain, uint16_t s
|
||||
/* clear the present bit first */
|
||||
context_entry->lo_64 = 0UL;
|
||||
context_entry->hi_64 = 0UL;
|
||||
iommu_flush_cache(dmar_unit, context_entry, sizeof(struct dmar_entry));
|
||||
iommu_flush_cache(context_entry, sizeof(struct dmar_entry));
|
||||
|
||||
sid.bits.b = bus;
|
||||
sid.bits.d = pci_slot(devfun);
|
||||
@@ -1370,7 +1372,7 @@ int32_t dmar_assign_irte(struct intr_source intr_src, union dmar_ir_entry irte,
|
||||
ir_entry->entry.hi_64 = irte.entry.hi_64;
|
||||
ir_entry->entry.lo_64 = irte.entry.lo_64;
|
||||
|
||||
iommu_flush_cache(dmar_unit, ir_entry, sizeof(union dmar_ir_entry));
|
||||
iommu_flush_cache(ir_entry, sizeof(union dmar_ir_entry));
|
||||
dmar_invalid_iec(dmar_unit, index, 0U, false);
|
||||
}
|
||||
return ret;
|
||||
@@ -1401,7 +1403,7 @@ void dmar_free_irte(struct intr_source intr_src, uint16_t index)
|
||||
ir_entry = ir_table + index;
|
||||
ir_entry->bits.present = 0x0UL;
|
||||
|
||||
iommu_flush_cache(dmar_unit, ir_entry, sizeof(union dmar_ir_entry));
|
||||
iommu_flush_cache(ir_entry, sizeof(union dmar_ir_entry));
|
||||
dmar_invalid_iec(dmar_unit, index, 0U, false);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user