From b1cc18810eedcfe669e01c1780a7abd95a999bd6 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Tue, 19 Mar 2019 12:38:58 -0700 Subject: [PATCH] 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 --- hypervisor/arch/x86/vtd.c | 19 +++++++++++-------- hypervisor/include/arch/x86/vtd.h | 8 +++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c index 09e384252..9c283fd7c 100644 --- a/hypervisor/arch/x86/vtd.c +++ b/hypervisor/arch/x86/vtd.c @@ -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); } } diff --git a/hypervisor/include/arch/x86/vtd.h b/hypervisor/include/arch/x86/vtd.h index 3ed2e0fe5..993b806d4 100644 --- a/hypervisor/include/arch/x86/vtd.h +++ b/hypervisor/include/arch/x86/vtd.h @@ -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));