Now that we can correctly extract top-level indices without relying on the remaining upper bits being zero, the only remaining impediments to using a given table for TTBR1 are the address validation on map/unmap and the awkward TCR translation granule format. Add a quirk so that we can do the right thing at those points.
Unified · Split
| @@ -104,6 +104,10 @@ · 103 unmodified lines | |||
| 104 | #define ARM_LPAE_TCR_TG0_64K 1 | 104 | #define ARM_LPAE_TCR_TG0_64K 1 |
| 105 | #define ARM_LPAE_TCR_TG0_16K 2 | 105 | #define ARM_LPAE_TCR_TG0_16K 2 |
| 106 | 106 | ||
| 107 | #define ARM_LPAE_TCR_TG1_16K 1 | ||
| 108 | #define ARM_LPAE_TCR_TG1_4K 2 | ||
| 109 | #define ARM_LPAE_TCR_TG1_64K 3 | ||
| 110 | |||
| 107 | #define ARM_LPAE_TCR_SH_NS 0 | 111 | #define ARM_LPAE_TCR_SH_NS 0 |
| 108 | #define ARM_LPAE_TCR_SH_OS 2 | 112 | #define ARM_LPAE_TCR_SH_OS 2 |
| 109 | #define ARM_LPAE_TCR_SH_IS 3 | 113 | #define ARM_LPAE_TCR_SH_IS 3 |
| @@ -464,6 +468,7 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · 354 unmodified lines | |||
| 464 | arm_lpae_iopte *ptep = data->pgd; | 468 | arm_lpae_iopte *ptep = data->pgd; |
| 465 | int ret, lvl = data->start_level; | 469 | int ret, lvl = data->start_level; |
| 466 | arm_lpae_iopte prot; | 470 | arm_lpae_iopte prot; |
| 471 | long iaext = (long)iova >> cfg->ias; | ||
| 467 | 472 | ||
| 468 | /* If no access, then nothing to do */ | 473 | /* If no access, then nothing to do */ |
| 469 | if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE))) | 474 | if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE))) |
| @@ -472,7 +477,9 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · 2 unmodified lines | |||
| 472 | if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size)) | 477 | if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size)) |
| 473 | return -EINVAL; | 478 | return -EINVAL; |
| 474 | 479 | ||
| 475 | if (WARN_ON(iova >> data->iop.cfg.ias || paddr >> data->iop.cfg.oas)) | 480 | if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1) |
| 481 | iaext = ~iaext; | ||
| 482 | if (WARN_ON(iaext || paddr >> cfg->oas)) | ||
| 476 | return -ERANGE; | 483 | return -ERANGE; |
| 477 | 484 | ||
| 478 | prot = arm_lpae_prot_to_pte(data, iommu_prot); | 485 | prot = arm_lpae_prot_to_pte(data, iommu_prot); |
| @@ -638,11 +645,14 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, · 159 unmodified lines | |||
| 638 | struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops); | 645 | struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops); |
| 639 | struct io_pgtable_cfg *cfg = &data->iop.cfg; | 646 | struct io_pgtable_cfg *cfg = &data->iop.cfg; |
| 640 | arm_lpae_iopte *ptep = data->pgd; | 647 | arm_lpae_iopte *ptep = data->pgd; |
| 648 | long iaext = (long)iova >> cfg->ias; | ||
| 641 | 649 | ||
| 642 | if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size)) | 650 | if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size)) |
| 643 | return 0; | 651 | return 0; |
| 644 | 652 | ||
| 645 | if (WARN_ON(iova >> data->iop.cfg.ias)) | 653 | if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1) |
| 654 | iaext = ~iaext; | ||
| 655 | if (WARN_ON(iaext)) | ||
| 646 | return 0; | 656 | return 0; |
| 647 | 657 | ||
| 648 | return __arm_lpae_unmap(data, gather, iova, size, data->start_level, ptep); | 658 | return __arm_lpae_unmap(data, gather, iova, size, data->start_level, ptep); |
| @@ -778,9 +788,11 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) · 129 unmodified lines | |||
| 778 | u64 reg; | 788 | u64 reg; |
| 779 | struct arm_lpae_io_pgtable *data; | 789 | struct arm_lpae_io_pgtable *data; |
| 780 | typeof(&cfg->arm_lpae_s1_cfg.tcr) tcr = &cfg->arm_lpae_s1_cfg.tcr; | 790 | typeof(&cfg->arm_lpae_s1_cfg.tcr) tcr = &cfg->arm_lpae_s1_cfg.tcr; |
| 791 | bool tg1; | ||
| 781 | 792 | ||
| 782 | if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS | | 793 | if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS | |
| 783 | IO_PGTABLE_QUIRK_NON_STRICT)) | 794 | IO_PGTABLE_QUIRK_NON_STRICT | |
| 795 | IO_PGTABLE_QUIRK_ARM_TTBR1)) | ||
| 784 | return NULL; | 796 | return NULL; |
| 785 | 797 | ||
| 786 | data = arm_lpae_alloc_pgtable(cfg); | 798 | data = arm_lpae_alloc_pgtable(cfg); |
| @@ -798,15 +810,16 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) · 11 unmodified lines | |||
| 798 | tcr->orgn = ARM_LPAE_TCR_RGN_NC; | 810 | tcr->orgn = ARM_LPAE_TCR_RGN_NC; |
| 799 | } | 811 | } |
| 800 | 812 | ||
| 813 | tg1 = cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1; | ||
| 801 | switch (ARM_LPAE_GRANULE(data)) { | 814 | switch (ARM_LPAE_GRANULE(data)) { |
| 802 | case SZ_4K: | 815 | case SZ_4K: |
| 803 | tcr->tg = ARM_LPAE_TCR_TG0_4K; | 816 | tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_4K : ARM_LPAE_TCR_TG0_4K; |
| 804 | break; | 817 | break; |
| 805 | case SZ_16K: | 818 | case SZ_16K: |
| 806 | tcr->tg = ARM_LPAE_TCR_TG0_16K; | 819 | tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_16K : ARM_LPAE_TCR_TG0_16K; |
| 807 | break; | 820 | break; |
| 808 | case SZ_64K: | 821 | case SZ_64K: |
| 809 | tcr->tg = ARM_LPAE_TCR_TG0_64K; | 822 | tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_64K : ARM_LPAE_TCR_TG0_64K; |
| 810 | break; | 823 | break; |
| 811 | } | 824 | } |
| 812 | 825 | ||
| @@ -83,12 +83,16 @@ struct io_pgtable_cfg { · 82 unmodified lines | |||
| 83 | * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs | 83 | * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs |
| 84 | * on unmap, for DMA domains using the flush queue mechanism for | 84 | * on unmap, for DMA domains using the flush queue mechanism for |
| 85 | * delayed invalidation. | 85 | * delayed invalidation. |
| 86 | * | ||
| 87 | * IO_PGTABLE_QUIRK_ARM_TTBR1: (ARM LPAE format) Configure the table | ||
| 88 | * for use in the upper half of a split address space. | ||
| 86 | */ | 89 | */ |
| 87 | #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) | 90 | #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) |
| 88 | #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) | 91 | #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) |
| 89 | #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) | 92 | #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) |
| 90 | #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3) | 93 | #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3) |
| 91 | #define IO_PGTABLE_QUIRK_NON_STRICT BIT(4) | 94 | #define IO_PGTABLE_QUIRK_NON_STRICT BIT(4) |
| 95 | #define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5) | ||
| 92 | unsigned long quirks; | 96 | unsigned long quirks; |
| 93 | unsigned long pgsize_bitmap; | 97 | unsigned long pgsize_bitmap; |
| 94 | unsigned int ias; | 98 | unsigned int ias; |