From 46c32eb000988c159b5924ac09b2bf9d13c29b13 Mon Sep 17 00:00:00 2001 From: Binbin Wu Date: Wed, 11 Apr 2018 17:19:41 +0800 Subject: [PATCH] vtd: fix memory coherency issue of vtd table Signed-off-by: Binbin Wu Reviewed-by: Jason Chen CJ Acked-by: Kevin Tian --- arch/x86/vtd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/x86/vtd.c b/arch/x86/vtd.c index 98b0c812c..cea4e56a3 100644 --- a/arch/x86/vtd.c +++ b/arch/x86/vtd.c @@ -252,6 +252,20 @@ static void iommu_write64(struct dmar_drhd_rt *dmar_uint, uint32_t offset, mmio_write_long(temp, dmar_uint->drhd->reg_base_addr + offset + 4); } +/* flush cache when root table, context table updated */ +static void iommu_flush_cache(struct dmar_drhd_rt *dmar_uint, + void *p, uint32_t size) +{ + uint32_t i; + + /* if vtd support page-walk coherency, no need to flush cacheline */ + if (iommu_ecap_c(dmar_uint->ecap)) + return; + + for (i = 0; i < size; i += CACHE_LINE_SIZE) + clflush((char *)p + i); +} + #if DBG_IOMMU static void dmar_uint_show_capability(struct dmar_drhd_rt *dmar_uint) { @@ -975,6 +989,8 @@ static int add_iommu_device(struct iommu_domain *domain, uint16_t segment, root_entry->upper = 0; root_entry->lower = lower; + iommu_flush_cache(dmar_uint, root_entry, + sizeof(struct dmar_root_entry)); } else { context_table_addr = DMAR_GET_BITSLICE(root_entry->lower, ROOT_ENTRY_LOWER_CTP); @@ -1028,6 +1044,8 @@ static int add_iommu_device(struct iommu_domain *domain, uint16_t segment, context_entry->upper = upper; context_entry->lower = lower; + iommu_flush_cache(dmar_uint, context_entry, + sizeof(struct dmar_context_entry)); return 0; } @@ -1072,6 +1090,8 @@ remove_iommu_device(struct iommu_domain *domain, uint16_t segment, /* clear the present bit first */ context_entry->lower = 0; context_entry->upper = 0; + iommu_flush_cache(dmar_uint, context_entry, + sizeof(struct dmar_context_entry)); /* if caching mode is present, need to invalidate translation cache */ /* if(cap_caching_mode(dmar_uint->cap)) { */