mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 09:43:59 +08:00
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. Tested-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
ac4b80e5b9
commit
db6903010a
@ -104,6 +104,10 @@
|
||||
#define ARM_LPAE_TCR_TG0_64K 1
|
||||
#define ARM_LPAE_TCR_TG0_16K 2
|
||||
|
||||
#define ARM_LPAE_TCR_TG1_16K 1
|
||||
#define ARM_LPAE_TCR_TG1_4K 2
|
||||
#define ARM_LPAE_TCR_TG1_64K 3
|
||||
|
||||
#define ARM_LPAE_TCR_SH_NS 0
|
||||
#define ARM_LPAE_TCR_SH_OS 2
|
||||
#define ARM_LPAE_TCR_SH_IS 3
|
||||
@ -464,6 +468,7 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
|
||||
arm_lpae_iopte *ptep = data->pgd;
|
||||
int ret, lvl = data->start_level;
|
||||
arm_lpae_iopte prot;
|
||||
long iaext = (long)iova >> cfg->ias;
|
||||
|
||||
/* If no access, then nothing to do */
|
||||
if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
|
||||
@ -472,7 +477,9 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
|
||||
if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(iova >> data->iop.cfg.ias || paddr >> data->iop.cfg.oas))
|
||||
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1)
|
||||
iaext = ~iaext;
|
||||
if (WARN_ON(iaext || paddr >> cfg->oas))
|
||||
return -ERANGE;
|
||||
|
||||
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,
|
||||
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
|
||||
struct io_pgtable_cfg *cfg = &data->iop.cfg;
|
||||
arm_lpae_iopte *ptep = data->pgd;
|
||||
long iaext = (long)iova >> cfg->ias;
|
||||
|
||||
if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size))
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(iova >> data->iop.cfg.ias))
|
||||
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1)
|
||||
iaext = ~iaext;
|
||||
if (WARN_ON(iaext))
|
||||
return 0;
|
||||
|
||||
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)
|
||||
u64 reg;
|
||||
struct arm_lpae_io_pgtable *data;
|
||||
typeof(&cfg->arm_lpae_s1_cfg.tcr) tcr = &cfg->arm_lpae_s1_cfg.tcr;
|
||||
bool tg1;
|
||||
|
||||
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
|
||||
IO_PGTABLE_QUIRK_NON_STRICT))
|
||||
IO_PGTABLE_QUIRK_NON_STRICT |
|
||||
IO_PGTABLE_QUIRK_ARM_TTBR1))
|
||||
return NULL;
|
||||
|
||||
data = arm_lpae_alloc_pgtable(cfg);
|
||||
@ -798,15 +810,16 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
|
||||
tcr->orgn = ARM_LPAE_TCR_RGN_NC;
|
||||
}
|
||||
|
||||
tg1 = cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1;
|
||||
switch (ARM_LPAE_GRANULE(data)) {
|
||||
case SZ_4K:
|
||||
tcr->tg = ARM_LPAE_TCR_TG0_4K;
|
||||
tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_4K : ARM_LPAE_TCR_TG0_4K;
|
||||
break;
|
||||
case SZ_16K:
|
||||
tcr->tg = ARM_LPAE_TCR_TG0_16K;
|
||||
tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_16K : ARM_LPAE_TCR_TG0_16K;
|
||||
break;
|
||||
case SZ_64K:
|
||||
tcr->tg = ARM_LPAE_TCR_TG0_64K;
|
||||
tcr->tg = tg1 ? ARM_LPAE_TCR_TG1_64K : ARM_LPAE_TCR_TG0_64K;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -83,12 +83,16 @@ struct io_pgtable_cfg {
|
||||
* IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
|
||||
* on unmap, for DMA domains using the flush queue mechanism for
|
||||
* delayed invalidation.
|
||||
*
|
||||
* IO_PGTABLE_QUIRK_ARM_TTBR1: (ARM LPAE format) Configure the table
|
||||
* for use in the upper half of a split address space.
|
||||
*/
|
||||
#define IO_PGTABLE_QUIRK_ARM_NS BIT(0)
|
||||
#define IO_PGTABLE_QUIRK_NO_PERMS BIT(1)
|
||||
#define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2)
|
||||
#define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3)
|
||||
#define IO_PGTABLE_QUIRK_NON_STRICT BIT(4)
|
||||
#define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5)
|
||||
unsigned long quirks;
|
||||
unsigned long pgsize_bitmap;
|
||||
unsigned int ias;
|
||||
|
Loading…
Reference in New Issue
Block a user