diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index fdf089e28b..f3a6a5ed86 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -277,6 +277,20 @@ static void invalidate_interrupt_table(struct amd_iommu *iommu, u16 device_id) send_iommu_command(iommu, cmd); } +void invalidate_iommu_all(struct amd_iommu *iommu) +{ + u32 cmd[4], entry; + + cmd[3] = cmd[2] = cmd[0] = 0; + + set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_IOMMU_ALL, 0, + IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, + &entry); + cmd[1] = entry; + + send_iommu_command(iommu, cmd); +} + void amd_iommu_flush_iotlb(struct pci_dev *pdev, uint64_t gaddr, unsigned int order) { @@ -380,3 +394,11 @@ void amd_iommu_flush_intremap(struct amd_iommu *iommu, uint16_t bdf) invalidate_interrupt_table(iommu, bdf); flush_command_buffer(iommu); } + +void amd_iommu_flush_all_caches(struct amd_iommu *iommu) +{ + ASSERT( spin_is_locked(&iommu->lock) ); + + invalidate_iommu_all(iommu); + flush_command_buffer(iommu); +} diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 12fe3e40e4..404638d194 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -598,6 +598,9 @@ static void enable_iommu(struct amd_iommu *iommu) set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED); set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED); + if ( iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) ) + amd_iommu_flush_all_caches(iommu); + iommu->enabled = 1; spin_unlock_irqrestore(&iommu->lock, flags); @@ -970,6 +973,9 @@ void amd_iommu_resume(void) } /* flush all cache entries after iommu re-enabled */ - invalidate_all_devices(); - invalidate_all_domain_pages(); + if ( !iommu_has_feature(iommu, IOMMU_EXT_FEATURE_IASUP_SHIFT) ) + { + invalidate_all_devices(); + invalidate_all_domain_pages(); + } } diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h index c6bf6cd8ec..a9325cb724 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h @@ -192,6 +192,7 @@ #define IOMMU_CMD_INVALIDATE_IOMMU_PAGES 0x3 #define IOMMU_CMD_INVALIDATE_IOTLB_PAGES 0x4 #define IOMMU_CMD_INVALIDATE_INT_TABLE 0x5 +#define IOMMU_CMD_INVALIDATE_IOMMU_ALL 0x8 /* COMPLETION_WAIT command */ #define IOMMU_COMP_WAIT_DATA_BUFFER_SIZE 8 diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index 5a327bfad0..960e9ff783 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -78,6 +78,7 @@ void amd_iommu_flush_iotlb(struct pci_dev *pdev, uint64_t gaddr, unsigned int order); void amd_iommu_flush_device(struct amd_iommu *iommu, uint16_t bdf); void amd_iommu_flush_intremap(struct amd_iommu *iommu, uint16_t bdf); +void amd_iommu_flush_all_caches(struct amd_iommu *iommu); /* find iommu for bdf */ struct amd_iommu *find_iommu_for_device(int seg, int bdf);