• David Woodhouse's avatar
    iommu/vt-d: Clean up and fix page table clear/free behaviour · ea8ea460
    David Woodhouse authored
    There is a race condition between the existing clear/free code and the
    hardware. The IOMMU is actually permitted to cache the intermediate
    levels of the page tables, and doesn't need to walk the table from the
    very top of the PGD each time. So the existing back-to-back calls to
    dma_pte_clear_range() and dma_pte_free_pagetable() can lead to a
    use-after-free where the IOMMU reads from a freed page table.
    
    When freeing page tables we actually need to do the IOTLB flush, with
    the 'invalidation hint' bit clear to indicate that it's not just a
    leaf-node flush, after unlinking each page table page from the next level
    up but before actually freeing it.
    
    So in the rewritten domain_unmap() we just return a list of pages (using
    pg->freelist to make a list of them), and then the caller is expected to
    do the appropriate IOTLB flush (or tear down the domain completely,
    whatever), before finally calling dma_free_pagelist() to free the pages.
    
    As an added bonus, we no longer need to flush the CPU's data cache for
    pages which are about to be *removed* from the page table hierarchy anyway,
    in the non-cache-coherent case. This drastically improves the performance
    of large unmaps.
    
    As a side-effect of all these changes, this also fixes the fact that
    intel_iommu_unmap() was neglecting to free the page tables for the range
    in question after clearing them.
    Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
    ea8ea460
intel-iommu.c 115 KB