[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] AMD-Vi: allocate root table on demand
commit 8709b10c7f667ee6c3b76a5ef6a469e096f27502 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Mon Mar 20 17:00:34 2017 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Mon Mar 20 17:00:34 2017 +0100 AMD-Vi: allocate root table on demand This was my originally intended fix for the AMD side of XSA-207: There's no need to unconditionally allocate the root table, and with that there's then also no way to leak it when a guest has no devices assigned. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> --- xen/drivers/passthrough/amd/iommu_map.c | 20 ++++++++++--- xen/drivers/passthrough/amd/pci_amd_iommu.c | 42 +++++++++++++-------------- xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 1 + 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index 67ba145..fd2327d 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -636,11 +636,10 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, { bool_t need_flush = 0; struct domain_iommu *hd = dom_iommu(d); + int rc; unsigned long pt_mfn[7]; unsigned int merge_level; - BUG_ON( !hd->arch.root_table ); - if ( iommu_use_hap_pt(d) ) return 0; @@ -648,6 +647,15 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, spin_lock(&hd->arch.mapping_lock); + rc = amd_iommu_alloc_root(hd); + if ( rc ) + { + spin_unlock(&hd->arch.mapping_lock); + AMD_IOMMU_DEBUG("Root table alloc failed, gfn = %lx\n", gfn); + domain_crash(d); + return rc; + } + /* Since HVM domain is initialized with 2 level IO page table, * we might need a deeper page table for lager gfn now */ if ( is_hvm_domain(d) ) @@ -717,8 +725,6 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn) unsigned long pt_mfn[7]; struct domain_iommu *hd = dom_iommu(d); - BUG_ON( !hd->arch.root_table ); - if ( iommu_use_hap_pt(d) ) return 0; @@ -726,6 +732,12 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn) spin_lock(&hd->arch.mapping_lock); + if ( !hd->arch.root_table ) + { + spin_unlock(&hd->arch.mapping_lock); + return 0; + } + /* Since HVM domain is initialized with 2 level IO page table, * we might need a deeper page table for lager gfn now */ if ( is_hvm_domain(d) ) diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index b2428f8..8c25110 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -222,23 +222,29 @@ int __init amd_iov_detect(void) return scan_pci_devices(); } -static int allocate_domain_resources(struct domain_iommu *hd) +int amd_iommu_alloc_root(struct domain_iommu *hd) { - /* allocate root table */ - spin_lock(&hd->arch.mapping_lock); - if ( !hd->arch.root_table ) + if ( unlikely(!hd->arch.root_table) ) { hd->arch.root_table = alloc_amd_iommu_pgtable(); if ( !hd->arch.root_table ) - { - spin_unlock(&hd->arch.mapping_lock); return -ENOMEM; - } } - spin_unlock(&hd->arch.mapping_lock); + return 0; } +static int __must_check allocate_domain_resources(struct domain_iommu *hd) +{ + int rc; + + spin_lock(&hd->arch.mapping_lock); + rc = amd_iommu_alloc_root(hd); + spin_unlock(&hd->arch.mapping_lock); + + return rc; +} + static int get_paging_mode(unsigned long entries) { int level = 1; @@ -259,14 +265,6 @@ static int amd_iommu_domain_init(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); - /* allocate page directroy */ - if ( allocate_domain_resources(hd) != 0 ) - { - if ( hd->arch.root_table ) - free_domheap_page(hd->arch.root_table); - return -ENOMEM; - } - /* For pv and dom0, stick with get_paging_mode(max_page) * For HVM dom0, use 2 level page table at first */ hd->arch.paging_mode = is_hvm_domain(d) ? @@ -280,6 +278,9 @@ static void __hwdom_init amd_iommu_hwdom_init(struct domain *d) unsigned long i; const struct amd_iommu *iommu; + if ( allocate_domain_resources(dom_iommu(d)) ) + BUG(); + if ( !iommu_passthrough && !need_iommu(d) ) { int rc = 0; @@ -363,7 +364,7 @@ static int reassign_device(struct domain *source, struct domain *target, u8 devfn, struct pci_dev *pdev) { struct amd_iommu *iommu; - int bdf; + int bdf, rc; struct domain_iommu *t = dom_iommu(target); bdf = PCI_BDF2(pdev->bus, pdev->devfn); @@ -385,10 +386,9 @@ static int reassign_device(struct domain *source, struct domain *target, pdev->domain = target; } - /* IO page tables might be destroyed after pci-detach the last device - * In this case, we have to re-allocate root table for next pci-attach.*/ - if ( t->arch.root_table == NULL ) - allocate_domain_resources(t); + rc = allocate_domain_resources(t); + if ( rc ) + return rc; amd_iommu_setup_domain_device(target, iommu, devfn, pdev); AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n", 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 1cf9c3d..99bc21c 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -56,6 +56,7 @@ int __must_check amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int flags); int __must_check amd_iommu_unmap_page(struct domain *d, unsigned long gfn); u64 amd_iommu_get_next_table_from_pte(u32 *entry); +int __must_check amd_iommu_alloc_root(struct domain_iommu *hd); int amd_iommu_reserve_domain_unity_map(struct domain *domain, u64 phys_addr, unsigned long size, int iw, int ir); -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |