From 6985c9f4e39f0f8e9aec317750c2f8002affb5fb Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Tue, 22 Jun 2021 12:05:36 -0700 Subject: [PATCH] ANDROID: iommu/io-pgtable-arm: Add IOMMU_SYS_CACHE/_NWA Add IOMMU_SYS_CACHE and IOMMU_SYS_CACHE_NWA for device mappings. IOMMU_SYS_CACHE, used by itself, allows device accesses to be cached in the system cache (if present). IOMMU_SYS_CACHE_NWA, used by itself, allows device accesses to be cached in the system cache with a no-write allocate policy. On systems in which devices can also snoop the CPU caches (i.e. IO-coherency is present), IOMMU_SYS_CACHE_NWA and IOMMU_SYS_CACHE can be combined with IOMMU_CACHE (with IOMMU_SYS_CACHE + IOMMU_CACHE being a no-op). Bug: 189339242 Change-Id: Ic91616a148f39fead008a5b87a54ffd781fee734 Signed-off-by: Patrick Daly Signed-off-by: Georgi Djakov Signed-off-by: Chris Goldsworthy --- drivers/iommu/io-pgtable-arm.c | 20 +++++++++++++++++++- include/linux/iommu.h | 12 ++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 0ba817e86346..078e8d12861b 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -118,10 +118,14 @@ #define ARM_LPAE_MAIR_ATTR_NC 0x44 #define ARM_LPAE_MAIR_ATTR_INC_OWBRWA 0xf4 #define ARM_LPAE_MAIR_ATTR_WBRWA 0xff +#define ARM_LPAE_MAIR_ATTR_INC_OWBRANWA 0xe4ULL +#define ARM_LPAE_MAIR_ATTR_IWBRWA_OWBRANWA 0xefULL #define ARM_LPAE_MAIR_ATTR_IDX_NC 0 #define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1 #define ARM_LPAE_MAIR_ATTR_IDX_DEV 2 #define ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE 3 +#define ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE_NWA 4 +#define ARM_LPAE_MAIR_ATTR_IDX_ICACHE_OCACHE_NWA 5 #define ARM_MALI_LPAE_TTBR_ADRMODE_TABLE (3u << 0) #define ARM_MALI_LPAE_TTBR_READ_INNER BIT(2) @@ -433,9 +437,19 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data, if (prot & IOMMU_MMIO) pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV << ARM_LPAE_PTE_ATTRINDX_SHIFT); + else if ((prot & IOMMU_CACHE) && (prot & IOMMU_SYS_CACHE_NWA)) + pte |= (ARM_LPAE_MAIR_ATTR_IDX_ICACHE_OCACHE_NWA + << ARM_LPAE_PTE_ATTRINDX_SHIFT); + /* IOMMU_CACHE + IOMMU_SYS_CACHE equivalent to IOMMU_CACHE */ else if (prot & IOMMU_CACHE) pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE << ARM_LPAE_PTE_ATTRINDX_SHIFT); + else if (prot & IOMMU_SYS_CACHE) + pte |= (ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE + << ARM_LPAE_PTE_ATTRINDX_SHIFT); + else if (prot & IOMMU_SYS_CACHE_NWA) + pte |= (ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE_NWA + << ARM_LPAE_PTE_ATTRINDX_SHIFT); } /* @@ -891,7 +905,11 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) (ARM_LPAE_MAIR_ATTR_DEVICE << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV)) | (ARM_LPAE_MAIR_ATTR_INC_OWBRWA - << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE)); + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE)) | + (ARM_LPAE_MAIR_ATTR_INC_OWBRANWA + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE_NWA)) | + (ARM_LPAE_MAIR_ATTR_IWBRWA_OWBRANWA + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_ICACHE_OCACHE_NWA)); cfg->arm_lpae_s1_cfg.mair = reg; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7d2648058e43..9ff1310db24b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -31,6 +31,18 @@ * if the IOMMU page table format is equivalent. */ #define IOMMU_PRIV (1 << 5) +/* + * Allow caching in a transparent outer level of cache, also known as + * the last-level or system cache, with a read/write allocation policy. + * Does not depend on IOMMU_CACHE. Incompatible with IOMMU_SYS_CACHE_NWA. + */ +#define IOMMU_SYS_CACHE (1 << 6) +/* + * Allow caching in a transparent outer level of cache, also known as + * the last-level or system cache, with a read allocation policy. + * Does not depend on IOMMU_CACHE. Incompatible with IOMMU_SYS_CACHE. + */ +#define IOMMU_SYS_CACHE_NWA (1 << 7) struct iommu_ops; struct iommu_group;