|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Ping: [PATCH] AMD-Vi: allocate root table on demand
>>> On 03.03.17 at 15:29, <JBeulich@xxxxxxxx> wrote:
> 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>
>
> --- 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,
> {
> 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,13 @@ int amd_iommu_map_page(struct domain *d,
>
> spin_lock(&hd->arch.mapping_lock);
>
> + rc = amd_iommu_alloc_root(hd);
> + if ( rc )
> + {
> + spin_unlock(&hd->arch.mapping_lock);
> + 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 +723,6 @@ int amd_iommu_unmap_page(struct domain *
> 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 +730,12 @@ int amd_iommu_unmap_page(struct domain *
>
> 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) )
> --- 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
> {
> 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
> 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
> 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
> 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",
> --- 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(stru
> 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);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |