From 9c46139de889bc77571fe5ee7f000927d4aff24e Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Tue, 22 Nov 2011 13:27:19 +0000 Subject: [PATCH] amd iommu: Support INVALIDATE_IOMMU_ALL command. It is one of the new architectural commands supported by iommu v2. It instructs iommu to clear all address translation and interrupt remapping caches for all devices and all domains. Signed-off-by: Wei Wang Committed-by: Keir Fraser --- xen/drivers/passthrough/amd/iommu_cmd.c | 22 +++++++++++++++++++ xen/drivers/passthrough/amd/iommu_init.c | 10 +++++++-- xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 1 + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) 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); -- 2.30.2