iommu/amd: Correctly encode huge pages in iommu page tables
authorJoerg Roedel <jroedel@suse.de>
Wed, 1 Apr 2015 12:58:52 +0000 (14:58 +0200)
committerJiri Slaby <jslaby@suse.cz>
Wed, 10 Jun 2015 11:31:35 +0000 (13:31 +0200)
commit d4b036648402bb4ef6d4a0df51375a2fb705b6cc upstream.

When a default page-size for given level should be mapped,
the level encoding must be 0 rather than 7. This fixes an
issue seen on IOMMUv2 hardware, where this encoding is
enforced.

Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
drivers/iommu/amd_iommu.c

index db84a3c1254a4b1b9ab281cc7e12c5194a078439..27f9b8d433a305f7cbf1831a14a6bf246791f9ec 100644 (file)
@@ -1444,19 +1444,20 @@ static int iommu_map_page(struct protection_domain *dom,
        u64 __pte, *pte;
        int i, count;
 
+       BUG_ON(!IS_ALIGNED(bus_addr, page_size));
+       BUG_ON(!IS_ALIGNED(phys_addr, page_size));
+
        if (!(prot & IOMMU_PROT_MASK))
                return -EINVAL;
 
-       bus_addr  = PAGE_ALIGN(bus_addr);
-       phys_addr = PAGE_ALIGN(phys_addr);
-       count     = PAGE_SIZE_PTE_COUNT(page_size);
-       pte       = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL);
+       count = PAGE_SIZE_PTE_COUNT(page_size);
+       pte   = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL);
 
        for (i = 0; i < count; ++i)
                if (IOMMU_PTE_PRESENT(pte[i]))
                        return -EBUSY;
 
-       if (page_size > PAGE_SIZE) {
+       if (count > 1) {
                __pte = PAGE_SIZE_PTE(phys_addr, page_size);
                __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC;
        } else