mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
iommu/tegra-smmu: Fix page tables in > 4 GiB memory
Page tables that reside in physical memory beyond the 4 GiB boundary are currently not working properly. The reason is that when the physical address for page directory entries is read, it gets truncated at 32 bits and can cause crashes when passing that address to the DMA API. Fix this by first casting the PDE value to a dma_addr_t and then using the page frame number mask for the SMMU instance to mask out the invalid bits, which are typically used for mapping attributes, etc. Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
e31e592954
commit
96d3ab802e
@ -159,9 +159,9 @@ static bool smmu_dma_addr_valid(struct tegra_smmu *smmu, dma_addr_t addr)
|
||||
return (addr & smmu->pfn_mask) == addr;
|
||||
}
|
||||
|
||||
static dma_addr_t smmu_pde_to_dma(u32 pde)
|
||||
static dma_addr_t smmu_pde_to_dma(struct tegra_smmu *smmu, u32 pde)
|
||||
{
|
||||
return pde << 12;
|
||||
return (dma_addr_t)(pde & smmu->pfn_mask) << 12;
|
||||
}
|
||||
|
||||
static void smmu_flush_ptc_all(struct tegra_smmu *smmu)
|
||||
@ -554,6 +554,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova,
|
||||
dma_addr_t *dmap)
|
||||
{
|
||||
unsigned int pd_index = iova_pd_index(iova);
|
||||
struct tegra_smmu *smmu = as->smmu;
|
||||
struct page *pt_page;
|
||||
u32 *pd;
|
||||
|
||||
@ -562,7 +563,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova,
|
||||
return NULL;
|
||||
|
||||
pd = page_address(as->pd);
|
||||
*dmap = smmu_pde_to_dma(pd[pd_index]);
|
||||
*dmap = smmu_pde_to_dma(smmu, pd[pd_index]);
|
||||
|
||||
return tegra_smmu_pte_offset(pt_page, iova);
|
||||
}
|
||||
@ -604,7 +605,7 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova,
|
||||
} else {
|
||||
u32 *pd = page_address(as->pd);
|
||||
|
||||
*dmap = smmu_pde_to_dma(pd[pde]);
|
||||
*dmap = smmu_pde_to_dma(smmu, pd[pde]);
|
||||
}
|
||||
|
||||
return tegra_smmu_pte_offset(as->pts[pde], iova);
|
||||
@ -629,7 +630,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova)
|
||||
if (--as->count[pde] == 0) {
|
||||
struct tegra_smmu *smmu = as->smmu;
|
||||
u32 *pd = page_address(as->pd);
|
||||
dma_addr_t pte_dma = smmu_pde_to_dma(pd[pde]);
|
||||
dma_addr_t pte_dma = smmu_pde_to_dma(smmu, pd[pde]);
|
||||
|
||||
tegra_smmu_set_pde(as, iova, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user