提交 4d09d99d 编写于 作者: W Will Deacon

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: NWill Deacon <will.deacon@arm.com>
上级 70c9a7db
...@@ -763,6 +763,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) ...@@ -763,6 +763,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT); reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
break; break;
case 39: case 39:
case 40:
reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT); reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
break; break;
case 42: case 42:
...@@ -784,6 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) ...@@ -784,6 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT); reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT);
break; break;
case 39: case 39:
case 40:
reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT); reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT);
break; break;
case 42: case 42:
...@@ -1806,11 +1808,16 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) ...@@ -1806,11 +1808,16 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
* Stage-1 output limited by stage-2 input size due to pgd * Stage-1 output limited by stage-2 input size due to pgd
* allocation (PTRS_PER_PGD). * allocation (PTRS_PER_PGD).
*/ */
if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
#else #else
smmu->s1_output_size = min(32UL, size); smmu->s1_output_size = min(32UL, size);
#endif #endif
} else {
smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT,
size);
}
/* The stage-2 output mask is also applied for bypass */ /* The stage-2 output mask is also applied for bypass */
size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册