diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-04-01 08:58:52 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-04-02 07:31:08 -0400 |
commit | d4b036648402bb4ef6d4a0df51375a2fb705b6cc (patch) | |
tree | 9f464e5834439731cb8260f0883a65838a217c01 /drivers/iommu/amd_iommu.c | |
parent | b24b1b63a37d05d61601d643ef30f95dd2452048 (diff) |
iommu/amd: Correctly encode huge pages in iommu page tables
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>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 7a00e5d40eb6..aa710b095f1a 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -1390,13 +1390,14 @@ static int iommu_map_page(struct protection_domain *dom, | |||
1390 | u64 __pte, *pte; | 1390 | u64 __pte, *pte; |
1391 | int i, count; | 1391 | int i, count; |
1392 | 1392 | ||
1393 | BUG_ON(!IS_ALIGNED(bus_addr, page_size)); | ||
1394 | BUG_ON(!IS_ALIGNED(phys_addr, page_size)); | ||
1395 | |||
1393 | if (!(prot & IOMMU_PROT_MASK)) | 1396 | if (!(prot & IOMMU_PROT_MASK)) |
1394 | return -EINVAL; | 1397 | return -EINVAL; |
1395 | 1398 | ||
1396 | bus_addr = PAGE_ALIGN(bus_addr); | 1399 | count = PAGE_SIZE_PTE_COUNT(page_size); |
1397 | phys_addr = PAGE_ALIGN(phys_addr); | 1400 | pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL); |
1398 | count = PAGE_SIZE_PTE_COUNT(page_size); | ||
1399 | pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL); | ||
1400 | 1401 | ||
1401 | if (!pte) | 1402 | if (!pte) |
1402 | return -ENOMEM; | 1403 | return -ENOMEM; |
@@ -1405,7 +1406,7 @@ static int iommu_map_page(struct protection_domain *dom, | |||
1405 | if (IOMMU_PTE_PRESENT(pte[i])) | 1406 | if (IOMMU_PTE_PRESENT(pte[i])) |
1406 | return -EBUSY; | 1407 | return -EBUSY; |
1407 | 1408 | ||
1408 | if (page_size > PAGE_SIZE) { | 1409 | if (count > 1) { |
1409 | __pte = PAGE_SIZE_PTE(phys_addr, page_size); | 1410 | __pte = PAGE_SIZE_PTE(phys_addr, page_size); |
1410 | __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC; | 1411 | __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC; |
1411 | } else | 1412 | } else |