|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/3] AMD/IOMMU: don't needlessly trigger errors/crashes when unmapping a page
On Wed, 6 Nov 2019 at 15:20, Jan Beulich <jbeulich@xxxxxxxx> wrote:
>
> Unmapping a page which has never been mapped should be a no-op (note how
> it already is in case there was no root page table allocated). There's
> in particular no need to grow the number of page table levels in use,
> and there's also no need to allocate intermediate page tables except
> when needing to split a large page.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Reviewed-by: Paul Durrant <paul@xxxxxxx>
>
> --- a/xen/drivers/passthrough/amd/iommu_map.c
> +++ b/xen/drivers/passthrough/amd/iommu_map.c
> @@ -176,7 +176,7 @@ void iommu_dte_set_guest_cr3(struct amd_
> * page tables.
> */
> static int iommu_pde_from_dfn(struct domain *d, unsigned long dfn,
> - unsigned long pt_mfn[])
> + unsigned long pt_mfn[], bool map)
> {
> struct amd_iommu_pte *pde, *next_table_vaddr;
> unsigned long next_table_mfn;
> @@ -189,6 +189,13 @@ static int iommu_pde_from_dfn(struct dom
>
> BUG_ON( table == NULL || level < 1 || level > 6 );
>
> + /*
> + * A frame number past what the current page tables can represent can't
> + * possibly have a mapping.
> + */
> + if ( dfn >> (PTE_PER_TABLE_SHIFT * level) )
> + return 0;
> +
> next_table_mfn = mfn_x(page_to_mfn(table));
>
> if ( level == 1 )
> @@ -246,6 +253,9 @@ static int iommu_pde_from_dfn(struct dom
> /* Install lower level page table for non-present entries */
> else if ( !pde->pr )
> {
> + if ( !map )
> + return 0;
> +
> if ( next_table_mfn == 0 )
> {
> table = alloc_amd_iommu_pgtable();
> @@ -404,7 +414,7 @@ int amd_iommu_map_page(struct domain *d,
> }
> }
>
> - if ( iommu_pde_from_dfn(d, dfn_x(dfn), pt_mfn) || (pt_mfn[1] == 0) )
> + if ( iommu_pde_from_dfn(d, dfn_x(dfn), pt_mfn, true) || (pt_mfn[1] == 0)
> )
> {
> spin_unlock(&hd->arch.mapping_lock);
> AMD_IOMMU_DEBUG("Invalid IO pagetable entry dfn = %"PRI_dfn"\n",
> @@ -439,24 +449,7 @@ int amd_iommu_unmap_page(struct domain *
> return 0;
> }
>
> - /* Since HVM domain is initialized with 2 level IO page table,
> - * we might need a deeper page table for lager dfn now */
> - if ( is_hvm_domain(d) )
> - {
> - int rc = update_paging_mode(d, dfn_x(dfn));
> -
> - if ( rc )
> - {
> - spin_unlock(&hd->arch.mapping_lock);
> - AMD_IOMMU_DEBUG("Update page mode failed dfn = %"PRI_dfn"\n",
> - dfn_x(dfn));
> - if ( rc != -EADDRNOTAVAIL )
> - domain_crash(d);
> - return rc;
> - }
> - }
> -
> - if ( iommu_pde_from_dfn(d, dfn_x(dfn), pt_mfn) || (pt_mfn[1] == 0) )
> + if ( iommu_pde_from_dfn(d, dfn_x(dfn), pt_mfn, false) )
> {
> spin_unlock(&hd->arch.mapping_lock);
> AMD_IOMMU_DEBUG("Invalid IO pagetable entry dfn = %"PRI_dfn"\n",
> @@ -465,8 +458,11 @@ int amd_iommu_unmap_page(struct domain *
> return -EFAULT;
> }
>
> - /* mark PTE as 'page not present' */
> - *flush_flags |= clear_iommu_pte_present(pt_mfn[1], dfn_x(dfn));
> + if ( pt_mfn[1] )
> + {
> + /* Mark PTE as 'page not present'. */
> + *flush_flags |= clear_iommu_pte_present(pt_mfn[1], dfn_x(dfn));
> + }
>
> spin_unlock(&hd->arch.mapping_lock);
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |