From: Keir Fraser Date: Wed, 3 Dec 2008 15:56:33 +0000 (+0000) Subject: AMD IOMMU: Invalidate all pages on domain destruction X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14040^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=1c8299d8466c5bc4c59d748a7e5d9121f67ec432;p=xen.git AMD IOMMU: Invalidate all pages on domain destruction Attached patch adds support to invalidate all pages associated with the same domain ID on domain destruction. Signed-off-by: Wei Wang --- diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index a41fe60890..3f4808d31d 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -580,3 +580,47 @@ out: spin_unlock_irqrestore(&hd->mapping_lock, flags); return 0; } + +void invalidate_all_iommu_pages(struct domain *d) +{ + u32 cmd[4], entry; + unsigned long flags; + struct amd_iommu *iommu; + int domain_id = d->domain_id; + u64 addr_lo = 0x7FFFFFFFFFFFF000ULL & DMA_32BIT_MASK; + u64 addr_hi = 0x7FFFFFFFFFFFF000ULL >> 32; + + set_field_in_reg_u32(domain_id, 0, + IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK, + IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry); + set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_IOMMU_PAGES, entry, + IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, + &entry); + cmd[1] = entry; + + set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0, + IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK, + IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry); + set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, + IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK, + IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry); + set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, entry, + IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK, + IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry); + cmd[2] = entry; + + set_field_in_reg_u32((u32)addr_hi, 0, + IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK, + IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry); + cmd[3] = entry; + + cmd[0] = 0; + + for_each_amd_iommu ( iommu ) + { + spin_lock_irqsave(&iommu->lock, flags); + send_iommu_command(iommu, cmd); + flush_command_buffer(iommu); + spin_unlock_irqrestore(&iommu->lock, flags); + } +} diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 8e982455cb..310911e15e 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -389,6 +389,7 @@ static void deallocate_iommu_page_tables(struct domain *d) static void amd_iommu_domain_destroy(struct domain *d) { deallocate_iommu_page_tables(d); + invalidate_all_iommu_pages(d); } static int amd_iommu_return_device( 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 e9e47990c0..929c5fd3f5 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -63,6 +63,7 @@ void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry); int amd_iommu_reserve_domain_unity_map(struct domain *domain, unsigned long phys_addr, unsigned long size, int iw, int ir); int amd_iommu_sync_p2m(struct domain *d); +void invalidate_all_iommu_pages(struct domain *d); /* device table functions */ void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u64 intremap_ptr,