diff options
| author | Robin Murphy <robin.murphy@arm.com> | 2018-03-26 08:35:14 -0400 |
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2018-03-27 09:12:06 -0400 |
| commit | 6619c9138533597dc0ff52155d263f14e8578ca2 (patch) | |
| tree | dc5c5dad0a9696b3e0c0ae8a4e2811a3e62859c0 /drivers/iommu | |
| parent | 6c89928ff7a0f7b4ebc2ac1acab9f99d5f50ed75 (diff) | |
iommu/arm-smmu-v3: Support 52-bit physical address
Implement SMMUv3.1 support for 52-bit physical addresses. Since a 52-bit
OAS implies 64KB translation granule support, permitting level 1 block
entries there is simple, and the rest is just extending address fields.
Tested-by: Nate Watterson <nwatters@codeaurora.org>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu')
| -rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index ae6049bddd73..b73a5950eb65 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
| @@ -91,6 +91,7 @@ | |||
| 91 | #define IDR5_OAS_42_BIT 3 | 91 | #define IDR5_OAS_42_BIT 3 |
| 92 | #define IDR5_OAS_44_BIT 4 | 92 | #define IDR5_OAS_44_BIT 4 |
| 93 | #define IDR5_OAS_48_BIT 5 | 93 | #define IDR5_OAS_48_BIT 5 |
| 94 | #define IDR5_OAS_52_BIT 6 | ||
| 94 | 95 | ||
| 95 | #define ARM_SMMU_CR0 0x20 | 96 | #define ARM_SMMU_CR0 0x20 |
| 96 | #define CR0_CMDQEN (1 << 3) | 97 | #define CR0_CMDQEN (1 << 3) |
| @@ -147,7 +148,7 @@ | |||
| 147 | 148 | ||
| 148 | #define ARM_SMMU_STRTAB_BASE 0x80 | 149 | #define ARM_SMMU_STRTAB_BASE 0x80 |
| 149 | #define STRTAB_BASE_RA (1UL << 62) | 150 | #define STRTAB_BASE_RA (1UL << 62) |
| 150 | #define STRTAB_BASE_ADDR_MASK GENMASK_ULL(47, 6) | 151 | #define STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6) |
| 151 | 152 | ||
| 152 | #define ARM_SMMU_STRTAB_BASE_CFG 0x88 | 153 | #define ARM_SMMU_STRTAB_BASE_CFG 0x88 |
| 153 | #define STRTAB_BASE_CFG_FMT GENMASK(17, 16) | 154 | #define STRTAB_BASE_CFG_FMT GENMASK(17, 16) |
| @@ -175,7 +176,7 @@ | |||
| 175 | #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc | 176 | #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc |
| 176 | 177 | ||
| 177 | /* Common MSI config fields */ | 178 | /* Common MSI config fields */ |
| 178 | #define MSI_CFG0_ADDR_MASK GENMASK_ULL(47, 2) | 179 | #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) |
| 179 | #define MSI_CFG2_SH GENMASK(5, 4) | 180 | #define MSI_CFG2_SH GENMASK(5, 4) |
| 180 | #define MSI_CFG2_MEMATTR GENMASK(3, 0) | 181 | #define MSI_CFG2_MEMATTR GENMASK(3, 0) |
| 181 | 182 | ||
| @@ -194,7 +195,7 @@ | |||
| 194 | Q_IDX(q, p) * (q)->ent_dwords) | 195 | Q_IDX(q, p) * (q)->ent_dwords) |
| 195 | 196 | ||
| 196 | #define Q_BASE_RWA (1UL << 62) | 197 | #define Q_BASE_RWA (1UL << 62) |
| 197 | #define Q_BASE_ADDR_MASK GENMASK_ULL(47, 5) | 198 | #define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) |
| 198 | #define Q_BASE_LOG2SIZE GENMASK(4, 0) | 199 | #define Q_BASE_LOG2SIZE GENMASK(4, 0) |
| 199 | 200 | ||
| 200 | /* | 201 | /* |
| @@ -209,7 +210,7 @@ | |||
| 209 | 210 | ||
| 210 | #define STRTAB_L1_DESC_DWORDS 1 | 211 | #define STRTAB_L1_DESC_DWORDS 1 |
| 211 | #define STRTAB_L1_DESC_SPAN GENMASK_ULL(4, 0) | 212 | #define STRTAB_L1_DESC_SPAN GENMASK_ULL(4, 0) |
| 212 | #define STRTAB_L1_DESC_L2PTR_MASK GENMASK_ULL(47, 6) | 213 | #define STRTAB_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 6) |
| 213 | 214 | ||
| 214 | #define STRTAB_STE_DWORDS 8 | 215 | #define STRTAB_STE_DWORDS 8 |
| 215 | #define STRTAB_STE_0_V (1UL << 0) | 216 | #define STRTAB_STE_0_V (1UL << 0) |
| @@ -221,7 +222,7 @@ | |||
| 221 | 222 | ||
| 222 | #define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) | 223 | #define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) |
| 223 | #define STRTAB_STE_0_S1FMT_LINEAR 0 | 224 | #define STRTAB_STE_0_S1FMT_LINEAR 0 |
| 224 | #define STRTAB_STE_0_S1CTXPTR_MASK GENMASK_ULL(47, 6) | 225 | #define STRTAB_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6) |
| 225 | #define STRTAB_STE_0_S1CDMAX GENMASK_ULL(63, 59) | 226 | #define STRTAB_STE_0_S1CDMAX GENMASK_ULL(63, 59) |
| 226 | 227 | ||
| 227 | #define STRTAB_STE_1_S1C_CACHE_NC 0UL | 228 | #define STRTAB_STE_1_S1C_CACHE_NC 0UL |
| @@ -253,7 +254,7 @@ | |||
| 253 | #define STRTAB_STE_2_S2PTW (1UL << 54) | 254 | #define STRTAB_STE_2_S2PTW (1UL << 54) |
| 254 | #define STRTAB_STE_2_S2R (1UL << 58) | 255 | #define STRTAB_STE_2_S2R (1UL << 58) |
| 255 | 256 | ||
| 256 | #define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(47, 4) | 257 | #define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4) |
| 257 | 258 | ||
| 258 | /* Context descriptor (stage-1 only) */ | 259 | /* Context descriptor (stage-1 only) */ |
| 259 | #define CTXDESC_CD_DWORDS 8 | 260 | #define CTXDESC_CD_DWORDS 8 |
| @@ -287,7 +288,7 @@ | |||
| 287 | #define CTXDESC_CD_0_ASET (1UL << 47) | 288 | #define CTXDESC_CD_0_ASET (1UL << 47) |
| 288 | #define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48) | 289 | #define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48) |
| 289 | 290 | ||
| 290 | #define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(47, 4) | 291 | #define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4) |
| 291 | 292 | ||
| 292 | /* Convert between AArch64 (CPU) TCR format and SMMU CD format */ | 293 | /* Convert between AArch64 (CPU) TCR format and SMMU CD format */ |
| 293 | #define ARM_SMMU_TCR2CD(tcr, fld) FIELD_PREP(CTXDESC_CD_0_TCR_##fld, \ | 294 | #define ARM_SMMU_TCR2CD(tcr, fld) FIELD_PREP(CTXDESC_CD_0_TCR_##fld, \ |
| @@ -317,7 +318,7 @@ | |||
| 317 | #define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48) | 318 | #define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48) |
| 318 | #define CMDQ_TLBI_1_LEAF (1UL << 0) | 319 | #define CMDQ_TLBI_1_LEAF (1UL << 0) |
| 319 | #define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) | 320 | #define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) |
| 320 | #define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(47, 12) | 321 | #define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12) |
| 321 | 322 | ||
| 322 | #define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) | 323 | #define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) |
| 323 | #define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) | 324 | #define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) |
| @@ -331,7 +332,7 @@ | |||
| 331 | #define CMDQ_SYNC_0_MSH GENMASK_ULL(23, 22) | 332 | #define CMDQ_SYNC_0_MSH GENMASK_ULL(23, 22) |
| 332 | #define CMDQ_SYNC_0_MSIATTR GENMASK_ULL(27, 24) | 333 | #define CMDQ_SYNC_0_MSIATTR GENMASK_ULL(27, 24) |
| 333 | #define CMDQ_SYNC_0_MSIDATA GENMASK_ULL(63, 32) | 334 | #define CMDQ_SYNC_0_MSIDATA GENMASK_ULL(63, 32) |
| 334 | #define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(47, 2) | 335 | #define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2) |
| 335 | 336 | ||
| 336 | /* Event queue */ | 337 | /* Event queue */ |
| 337 | #define EVTQ_ENT_DWORDS 4 | 338 | #define EVTQ_ENT_DWORDS 4 |
| @@ -1622,7 +1623,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain) | |||
| 1622 | return -ENOMEM; | 1623 | return -ENOMEM; |
| 1623 | 1624 | ||
| 1624 | domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; | 1625 | domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; |
| 1625 | domain->geometry.aperture_end = (1UL << ias) - 1; | 1626 | domain->geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1; |
| 1626 | domain->geometry.force_aperture = true; | 1627 | domain->geometry.force_aperture = true; |
| 1627 | 1628 | ||
| 1628 | ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); | 1629 | ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg); |
| @@ -2644,11 +2645,6 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) | |||
| 2644 | if (reg & IDR5_GRAN4K) | 2645 | if (reg & IDR5_GRAN4K) |
| 2645 | smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; | 2646 | smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; |
| 2646 | 2647 | ||
| 2647 | if (arm_smmu_ops.pgsize_bitmap == -1UL) | ||
| 2648 | arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; | ||
| 2649 | else | ||
| 2650 | arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap; | ||
| 2651 | |||
| 2652 | /* Output address size */ | 2648 | /* Output address size */ |
| 2653 | switch (FIELD_GET(IDR5_OAS, reg)) { | 2649 | switch (FIELD_GET(IDR5_OAS, reg)) { |
| 2654 | case IDR5_OAS_32_BIT: | 2650 | case IDR5_OAS_32_BIT: |
| @@ -2666,6 +2662,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) | |||
| 2666 | case IDR5_OAS_44_BIT: | 2662 | case IDR5_OAS_44_BIT: |
| 2667 | smmu->oas = 44; | 2663 | smmu->oas = 44; |
| 2668 | break; | 2664 | break; |
| 2665 | case IDR5_OAS_52_BIT: | ||
| 2666 | smmu->oas = 52; | ||
| 2667 | smmu->pgsize_bitmap |= 1ULL << 42; /* 4TB */ | ||
| 2668 | break; | ||
| 2669 | default: | 2669 | default: |
| 2670 | dev_info(smmu->dev, | 2670 | dev_info(smmu->dev, |
| 2671 | "unknown output address size. Truncating to 48-bit\n"); | 2671 | "unknown output address size. Truncating to 48-bit\n"); |
| @@ -2674,6 +2674,11 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) | |||
| 2674 | smmu->oas = 48; | 2674 | smmu->oas = 48; |
| 2675 | } | 2675 | } |
| 2676 | 2676 | ||
| 2677 | if (arm_smmu_ops.pgsize_bitmap == -1UL) | ||
| 2678 | arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; | ||
| 2679 | else | ||
| 2680 | arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap; | ||
| 2681 | |||
| 2677 | /* Set the DMA mask for our table walker */ | 2682 | /* Set the DMA mask for our table walker */ |
| 2678 | if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(smmu->oas))) | 2683 | if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(smmu->oas))) |
| 2679 | dev_warn(smmu->dev, | 2684 | dev_warn(smmu->dev, |
