mirror of https://gitee.com/openkylin/linux.git
iommu/io-pgtable-arm: Correct Mali attributes
Whilst Midgard's MEMATTR follows a similar principle to the VMSA MAIR,
the actual attribute values differ, so although it currently appears to
work to some degree, we probably shouldn't be using our standard stage 1
MAIR for that. Instead, generate a reasonable MEMATTR with attribute
values borrowed from the kbase driver; at this point we'll be overriding
or ignoring pretty much all of the LPAE config, so just implement these
Mali details in a dedicated allocator instead of pretending to subclass
the standard VMSA format.
Fixes: d08d42de64
("iommu: io-pgtable: Add ARM Mali midgard MMU page table format")
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
6db7bfb431
commit
52f325f4eb
|
@ -166,6 +166,9 @@
|
|||
#define ARM_MALI_LPAE_TTBR_READ_INNER BIT(2)
|
||||
#define ARM_MALI_LPAE_TTBR_SHARE_OUTER BIT(4)
|
||||
|
||||
#define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL
|
||||
#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL
|
||||
|
||||
/* IOPTE accessors */
|
||||
#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
|
||||
|
||||
|
@ -1015,27 +1018,51 @@ arm_32_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
|
|||
static struct io_pgtable *
|
||||
arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
|
||||
{
|
||||
struct io_pgtable *iop;
|
||||
struct arm_lpae_io_pgtable *data;
|
||||
|
||||
/* No quirks for Mali (hopefully) */
|
||||
if (cfg->quirks)
|
||||
return NULL;
|
||||
|
||||
if (cfg->ias != 48 || cfg->oas > 40)
|
||||
return NULL;
|
||||
|
||||
cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G);
|
||||
iop = arm_64_lpae_alloc_pgtable_s1(cfg, cookie);
|
||||
if (iop) {
|
||||
u64 mair, ttbr;
|
||||
|
||||
/* Copy values as union fields overlap */
|
||||
mair = cfg->arm_lpae_s1_cfg.mair[0];
|
||||
ttbr = cfg->arm_lpae_s1_cfg.ttbr[0];
|
||||
data = arm_lpae_alloc_pgtable(cfg);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
cfg->arm_mali_lpae_cfg.memattr = mair;
|
||||
cfg->arm_mali_lpae_cfg.transtab = ttbr |
|
||||
ARM_MALI_LPAE_TTBR_READ_INNER |
|
||||
ARM_MALI_LPAE_TTBR_ADRMODE_TABLE;
|
||||
}
|
||||
/*
|
||||
* MEMATTR: Mali has no actual notion of a non-cacheable type, so the
|
||||
* best we can do is mimic the out-of-tree driver and hope that the
|
||||
* "implementation-defined caching policy" is good enough. Similarly,
|
||||
* we'll use it for the sake of a valid attribute for our 'device'
|
||||
* index, although callers should never request that in practice.
|
||||
*/
|
||||
cfg->arm_mali_lpae_cfg.memattr =
|
||||
(ARM_MALI_LPAE_MEMATTR_IMP_DEF
|
||||
<< ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_NC)) |
|
||||
(ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC
|
||||
<< ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
|
||||
(ARM_MALI_LPAE_MEMATTR_IMP_DEF
|
||||
<< ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV));
|
||||
|
||||
return iop;
|
||||
data->pgd = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL, cfg);
|
||||
if (!data->pgd)
|
||||
goto out_free_data;
|
||||
|
||||
/* Ensure the empty pgd is visible before TRANSTAB can be written */
|
||||
wmb();
|
||||
|
||||
cfg->arm_mali_lpae_cfg.transtab = virt_to_phys(data->pgd) |
|
||||
ARM_MALI_LPAE_TTBR_READ_INNER |
|
||||
ARM_MALI_LPAE_TTBR_ADRMODE_TABLE;
|
||||
return &data->iop;
|
||||
|
||||
out_free_data:
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
|
||||
|
|
Loading…
Reference in New Issue