lkml.org 
[lkml]   [2013]   [Jul]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[33/85] iommu/amd: Only unmap large pages from the first pte
    3.2.49-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Alex Williamson <alex.williamson@redhat.com>

    commit 60d0ca3cfd199b6612bbbbf4999a3470dad38bb1 upstream.

    If we use a large mapping, the expectation is that only unmaps from
    the first pte in the superpage are supported. Unmaps from offsets
    into the superpage should fail (ie. return zero sized unmap). In the
    current code, unmapping from an offset clears the size of the full
    mapping starting from an offset. For instance, if we map a 16k
    physically contiguous range at IOVA 0x0 with a large page, then
    attempt to unmap 4k at offset 12k, 4 ptes are cleared (12k - 28k) and
    the unmap returns 16k unmapped. This potentially incorrectly clears
    valid mappings and confuses drivers like VFIO that use the unmap size
    to release pinned pages.

    Fix by refusing to unmap from offsets into the page.

    Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
    Signed-off-by: Joerg Roedel <joro@8bytes.org>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/iommu/amd_iommu.c | 6 +++++-
    1 file changed, 5 insertions(+), 1 deletion(-)

    --- a/drivers/iommu/amd_iommu.c
    +++ b/drivers/iommu/amd_iommu.c
    @@ -1076,6 +1076,10 @@ static unsigned long iommu_unmap_page(st

    /* Large PTE found which maps this address */
    unmap_size = PTE_PAGE_SIZE(*pte);
    +
    + /* Only unmap from the first pte in the page */
    + if ((unmap_size - 1) & bus_addr)
    + break;
    count = PAGE_SIZE_PTE_COUNT(unmap_size);
    for (i = 0; i < count; i++)
    pte[i] = 0ULL;
    @@ -1085,7 +1089,7 @@ static unsigned long iommu_unmap_page(st
    unmapped += unmap_size;
    }

    - BUG_ON(!is_power_of_2(unmapped));
    + BUG_ON(unmapped && !is_power_of_2(unmapped));

    return unmapped;
    }


    \
     
     \ /
      Last update: 2013-07-24 16:21    [W:4.301 / U:1.776 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site