diff options
author | Chintan Pandya <cpandya@codeaurora.org> | 2014-04-05 00:54:52 +0530 |
---|---|---|
committer | Chintan Pandya <cpandya@codeaurora.org> | 2014-04-21 16:49:46 +0530 |
commit | 0be30916e61c6c22a23cc73e7d02b6f97009d52f (patch) | |
tree | c428f073aad8420708d2994f3390d97359bfd77b /drivers | |
parent | 052f216126c911852836193152befd11727c62ad (diff) |
iommu: msm: Verify page table corruption when page fault happens
Page faults often leads to doubt of either page table corruption
in DDR or the malfunctioning of the IOMMU. To rule out that, we
can walk through the page tables and get actual translation with
the faulty VA. If physical address from the page table is expected,
we can doubt IOMMU malfunctioning, or otherwise, page table
corruption.
Change-Id: Icef69e7a50ce3110fc83ca75b4a984057336b5bb
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/msm_iommu-v1.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c index 9691770ee38d..3ff30e5c3aeb 100644 --- a/drivers/iommu/msm_iommu-v1.c +++ b/drivers/iommu/msm_iommu-v1.c @@ -1299,6 +1299,9 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id) unsigned int fsr; int ret; + phys_addr_t pagetable_phys; + u64 faulty_iova = 0; + mutex_lock(&msm_iommu_lock); BUG_ON(!pdev); @@ -1333,11 +1336,14 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id) if (!ctx_drvdata->attached_domain) { pr_err("Bad domain in interrupt handler\n"); ret = -ENOSYS; - } else + } else { + faulty_iova = + GET_FAR(drvdata->cb_base, ctx_drvdata->num); ret = report_iommu_fault(ctx_drvdata->attached_domain, &ctx_drvdata->pdev->dev, - GET_FAR(drvdata->cb_base, ctx_drvdata->num), 0); + faulty_iova, 0); + } if (ret == -ENOSYS) { pr_err("Unexpected IOMMU page fault!\n"); pr_err("name = %s\n", drvdata->name); @@ -1346,6 +1352,14 @@ irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id) pr_err("Interesting registers:\n"); __print_ctx_regs(drvdata->cb_base, ctx_drvdata->num, fsr); + + if (ctx_drvdata->attached_domain) { + pagetable_phys = msm_iommu_iova_to_phys_soft( + ctx_drvdata->attached_domain, + faulty_iova); + pr_err("Page table in DDR shows PA = %x\n", + (unsigned int) pagetable_phys); + } } if (ret != -EBUSY) |