]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
iommu/vt-d: Make first level IOVA canonical
authorLu Baolu <baolu.lu@linux.intel.com>
Thu, 2 Jan 2020 00:18:19 +0000 (08:18 +0800)
committerJoerg Roedel <jroedel@suse.de>
Tue, 7 Jan 2020 13:05:58 +0000 (14:05 +0100)
First-level translation restricts the input-address to a canonical
address (i.e., address bits 63:N have the same value as address
bit [N-1], where N is 48-bits with 4-level paging and 57-bits with
5-level paging). (section 3.6 in the spec)

This makes first level IOVA canonical by using IOVA with bit [N-1]
always cleared.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel-iommu.c

index 54db6bc0b2810fca7efd821c04cb02d715e83fbb..1ebf5ed460cf696d83b0426be49045e67b53e2fd 100644 (file)
@@ -3505,8 +3505,21 @@ static unsigned long intel_alloc_iova(struct device *dev,
 {
        unsigned long iova_pfn;
 
-       /* Restrict dma_mask to the width that the iommu can handle */
-       dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
+       /*
+        * Restrict dma_mask to the width that the iommu can handle.
+        * First-level translation restricts the input-address to a
+        * canonical address (i.e., address bits 63:N have the same
+        * value as address bit [N-1], where N is 48-bits with 4-level
+        * paging and 57-bits with 5-level paging). Hence, skip bit
+        * [N-1].
+        */
+       if (domain_use_first_level(domain))
+               dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw - 1),
+                                dma_mask);
+       else
+               dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw),
+                                dma_mask);
+
        /* Ensure we reserve the whole size-aligned region */
        nrpages = __roundup_pow_of_two(nrpages);