hv: Use domain/device specific invalidation for DMAR translation caches

ACRN uses global invalidation for all DMAR translation caches. Whenever
a UOS is shutdown or rebooted, it ends up clearing entries in translation
caches belonging to other VMs/domains. This patch adds support for
domain/device level invalidation for DMA translation caches and index
based invalidation for Interrupt Remapping Cache.

Tracked-On: #2738
Signed-off-by: Sainath Grandhi sainath.grandhi@intel.com
Acked-by: Eddie Dong eddie.dong@intel.com
This commit is contained in:
Sainath Grandhi 2019-03-19 12:38:58 -07:00 committed by ACRN System Integration
parent 5c04687967
commit b1cc18810e
2 changed files with 14 additions and 13 deletions

View File

@ -98,9 +98,6 @@ static inline uint64_t dmar_set_bitslice(uint64_t var, uint64_t mask, uint32_t p
#define DMAR_IR_ENABLE_EIM_SHIFT 11UL
#define DMAR_IR_ENABLE_EIM (1UL << DMAR_IR_ENABLE_EIM_SHIFT)
#define DMAR_IECI_INDEXED 1U
#define DMAR_IEC_GLOBAL_INVL 0U
enum dmar_cirg_type {
DMAR_CIRG_RESERVED = 0,
DMAR_CIRG_GLOBAL,
@ -634,7 +631,7 @@ static void dmar_invalid_context_cache(struct dmar_drhd_rt *dmar_unit,
invalidate_desc.lo_64 |= DMA_CONTEXT_DOMAIN_INVL | dma_ccmd_did(did);
break;
case DMAR_CIRG_DEVICE:
invalidate_desc.lo_64 |= DMA_CCMD_DEVICE_INVL | dma_ccmd_did(did) | dma_ccmd_sid(sid) | dma_ccmd_fm(fm);
invalidate_desc.lo_64 |= DMA_CONTEXT_DEVICE_INVL | dma_ccmd_did(did) | dma_ccmd_sid(sid) | dma_ccmd_fm(fm);
break;
default:
invalidate_desc.lo_64 = 0UL;
@ -992,6 +989,7 @@ static void dmar_enable(struct dmar_drhd_rt *dmar_unit)
dev_dbg(ACRN_DBG_IOMMU, "enable dmar uint [0x%x]", dmar_unit->drhd->reg_base_addr);
dmar_invalid_context_cache_global(dmar_unit);
dmar_invalid_iotlb_global(dmar_unit);
dmar_invalid_iec_global(dmar_unit);
dmar_enable_translation(dmar_unit);
}
@ -1009,6 +1007,7 @@ static void dmar_suspend(struct dmar_drhd_rt *dmar_unit)
dmar_invalid_context_cache_global(dmar_unit);
dmar_invalid_iotlb_global(dmar_unit);
dmar_invalid_iec_global(dmar_unit);
dmar_disable(dmar_unit);
@ -1149,6 +1148,7 @@ static int32_t remove_iommu_device(const struct iommu_domain *domain, uint16_t s
struct dmar_entry *context;
struct dmar_entry *root_entry;
struct dmar_entry *context_entry;
union pci_bdf sid;
int32_t ret = 0;
dmar_unit = device_to_dmaru(segment, bus, devfun);
@ -1184,8 +1184,11 @@ static int32_t remove_iommu_device(const struct iommu_domain *domain, uint16_t s
context_entry->hi_64 = 0UL;
iommu_flush_cache(dmar_unit, context_entry, sizeof(struct dmar_entry));
dmar_invalid_context_cache_global(dmar_unit);
dmar_invalid_iotlb_global(dmar_unit);
sid.bits.b = bus;
sid.bits.d = pci_slot(devfun);
sid.bits.f = pci_func(devfun);
dmar_invalid_context_cache(dmar_unit, vmid_to_domainid(domain->vm_id), sid.value, 0U, DMAR_CIRG_DEVICE);
dmar_invalid_iotlb(dmar_unit, vmid_to_domainid(domain->vm_id), 0UL, 0U, false, DMAR_IIRG_DOMAIN);
}
}
}
@ -1407,7 +1410,7 @@ int32_t dmar_assign_irte(struct intr_source intr_src, union dmar_ir_entry irte,
ir_entry->entry.lo_64 = irte.entry.lo_64;
iommu_flush_cache(dmar_unit, ir_entry, sizeof(union dmar_ir_entry));
dmar_invalid_iec_global(dmar_unit);
dmar_invalid_iec(dmar_unit, index, 0U, false);
}
return ret;
}
@ -1438,6 +1441,6 @@ void dmar_free_irte(struct intr_source intr_src, uint16_t index)
ir_entry->bits.present = 0x0UL;
iommu_flush_cache(dmar_unit, ir_entry, sizeof(union dmar_ir_entry));
dmar_invalid_iec_global(dmar_unit);
dmar_invalid_iec(dmar_unit, index, 0U, false);
}
}

View File

@ -300,11 +300,6 @@ static inline uint8_t iommu_ecap_pds(uint64_t ecap)
#define DMA_GSTS_CFIS (1U << 23U)
/* CCMD_REG */
#define DMA_CCMD_ICC (1UL << 63U)
#define DMA_CCMD_ICC_32 (1U << 31U)
#define DMA_CCMD_GLOBAL_INVL (1UL << 61U)
#define DMA_CCMD_DOMAIN_INVL (2UL << 61U)
#define DMA_CCMD_DEVICE_INVL (3UL << 61U)
#define DMA_CONTEXT_GLOBAL_INVL (1UL << 4U)
#define DMA_CONTEXT_DOMAIN_INVL (2UL << 4U)
#define DMA_CONTEXT_DEVICE_INVL (3UL << 4U)
@ -357,6 +352,9 @@ static inline uint8_t dma_iotlb_invl_addr_am(uint8_t am)
return (am & 0x3fU);
}
/* IEC_REG */
#define DMAR_IECI_INDEXED (((uint64_t)1UL) << 4U)
#define DMAR_IEC_GLOBAL_INVL (((uint64_t)0UL) << 4U)
static inline uint64_t dma_iec_index(uint16_t index, uint8_t index_mask)
{
return ((((uint64_t)index & 0xFFFFU) << 32U) | (((uint64_t)index_mask & 0x1FU) << 27U));