iommu: arm-smmu: Program TTBR1 to a zero page
It was observed that address translation was occurring on TTBR1 even
with TCR.EPD1 set. Program TTBR1 to a valid zero page to get a S1
fault instead of a S2 fault.
Change-Id: I06dcd1a0b9f6636812ff8d25528ce1c37663ea5c
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 981172d..6fbade9 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -207,6 +207,7 @@
unsigned long bits_per_level;
void *pgd;
+ void *pgd_ttbr1;
};
typedef u64 arm_lpae_iopte;
@@ -665,6 +666,8 @@
struct arm_lpae_io_pgtable *data = io_pgtable_to_data(iop);
__arm_lpae_free_pgtable(data, ARM_LPAE_START_LVL(data), data->pgd);
+ __arm_lpae_free_pgtable(data, ARM_LPAE_START_LVL(data),
+ data->pgd_ttbr1);
kfree(data);
}
@@ -1089,14 +1092,22 @@
if (!data->pgd)
goto out_free_data;
+ data->pgd_ttbr1 = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL,
+ cfg, cookie);
+ if (!data->pgd_ttbr1)
+ goto out_free_pgd;
+
/* Ensure the empty pgd is visible before any actual TTBR write */
wmb();
/* TTBRs */
cfg->arm_lpae_s1_cfg.ttbr[0] = virt_to_phys(data->pgd);
- cfg->arm_lpae_s1_cfg.ttbr[1] = 0;
+ cfg->arm_lpae_s1_cfg.ttbr[1] = virt_to_phys(data->pgd_ttbr1);
return &data->iop;
+out_free_pgd:
+ __arm_lpae_free_pages(data->pgd, data->pgd_size, cfg, cookie);
+
out_free_data:
kfree(data);
return NULL;