diff options
author | Lu Baolu <baolu.lu@linux.intel.com> | 2020-01-02 08:18:19 +0800 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2020-01-07 14:05:58 +0100 |
commit | cb8b892dcecf279004967daab7791deb921cbcbe (patch) | |
tree | f2469df64ed9ecf9f0b6309017c5772a82e8b992 /drivers/iommu/intel-iommu.c | |
parent | 33cd6e642d6a76c1d338ce25cba5fd79a5029011 (diff) | |
download | linux-cb8b892dcecf279004967daab7791deb921cbcbe.tar.gz linux-cb8b892dcecf279004967daab7791deb921cbcbe.tar.bz2 linux-cb8b892dcecf279004967daab7791deb921cbcbe.zip |
iommu/vt-d: Make first level IOVA canonical
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>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 54db6bc0b281..1ebf5ed460cf 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -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); |