History

iommu/io-pgtable-arm: Prepare for TTBR1 usage

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.

Robin Murphy committed 7 years ago

Commit db690301 parent ac4b80e2 files · +23 −6Browse files

Unified · Split

2 files
  1. drivers/iommu/io-pgtable-arm.c +19 −6
  2. include/linux/io-pgtable.h +4 −0
drivers/iommu/io-pgtable-arm.c+19−6
@@ -104,6 +104,10 @@ · 103 unmodified lines
104#define ARM_LPAE_TCR_TG0_64K 1104#define ARM_LPAE_TCR_TG0_64K 1
105#define ARM_LPAE_TCR_TG0_16K 2105#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 0111#define ARM_LPAE_TCR_SH_NS 0
108#define ARM_LPAE_TCR_SH_OS 2112#define ARM_LPAE_TCR_SH_OS 2
109#define ARM_LPAE_TCR_SH_IS 3113#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
include/linux/io-pgtable.h+4−0
@@ -83,12 +83,16 @@ struct io_pgtable_cfg { · 82 unmodified lines
83 * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs83 * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
84 * on unmap, for DMA domains using the flush queue mechanism for84 * 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;