aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-07-23 08:20:43 -0400
committerWill Deacon <will.deacon@arm.com>2014-09-02 05:04:43 -0400
commit4d09d99d543ec28b2280a1f62382697f47ea6366 (patch)
tree99a52a879b40a417e07f022d2b1019bd2dd4b91d /drivers/iommu/arm-smmu.c
parent70c9a7db93a152e975c4158b944c6b50579415c2 (diff)
iommu/arm-smmu: fix corner cases in address size calculations
Working out the usable address sizes for the SMMU is surprisingly tricky. We must take into account both the limitations of the hardware for VA, IPA and PA sizes but also any restrictions imposed by the Linux page table code, particularly when dealing with nested translation (where the IPA size is limited by the input address size at stage-2). This patch fixes a few corner cases in our address size handling so that we correctly deal with 40-bit addresses in TTBCR2 and restrict the IPA size differently depending on whether or not we have support for nested translation. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1d69f147c924..a83cc2a2a2ca 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -763,6 +763,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
763 reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT); 763 reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
764 break; 764 break;
765 case 39: 765 case 39:
766 case 40:
766 reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT); 767 reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
767 break; 768 break;
768 case 42: 769 case 42:
@@ -784,6 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
784 reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT); 785 reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT);
785 break; 786 break;
786 case 39: 787 case 39:
788 case 40:
787 reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT); 789 reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT);
788 break; 790 break;
789 case 42: 791 case 42:
@@ -1806,11 +1808,16 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1806 * Stage-1 output limited by stage-2 input size due to pgd 1808 * Stage-1 output limited by stage-2 input size due to pgd
1807 * allocation (PTRS_PER_PGD). 1809 * allocation (PTRS_PER_PGD).
1808 */ 1810 */
1811 if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
1809#ifdef CONFIG_64BIT 1812#ifdef CONFIG_64BIT
1810 smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); 1813 smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
1811#else 1814#else
1812 smmu->s1_output_size = min(32UL, size); 1815 smmu->s1_output_size = min(32UL, size);
1813#endif 1816#endif
1817 } else {
1818 smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT,
1819 size);
1820 }
1814 1821
1815 /* The stage-2 output mask is also applied for bypass */ 1822 /* The stage-2 output mask is also applied for bypass */
1816 size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); 1823 size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);