iommu/io-pgtable: Rationalise quirk handling
authorRobin Murphy <robin.murphy@arm.com>
Fri, 12 Feb 2016 17:09:46 +0000 (17:09 +0000)
committerWill Deacon <will.deacon@arm.com>
Wed, 17 Feb 2016 14:15:09 +0000 (14:15 +0000)
As the number of io-pgtable implementations grows beyond 1, it's time
to rationalise the quirks mechanism before things have a chance to
start getting really ugly and out-of-hand.

To that end:
- Indicate exactly which quirks each format can/does support.
- Fail creating a table if a caller wants unsupported quirks.
- Properly document where each quirk applies and why.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/io-pgtable.h

index d39a021a4f6d20607cf417126e228ba546d7b4fc..9fcceb135f518a26bbb354088578ae596ecab237 100644 (file)
@@ -623,6 +623,11 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
        if (cfg->ias > ARM_V7S_ADDR_BITS || cfg->oas > ARM_V7S_ADDR_BITS)
                return NULL;
 
+       if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
+                           IO_PGTABLE_QUIRK_NO_PERMS |
+                           IO_PGTABLE_QUIRK_TLBI_ON_MAP))
+               return NULL;
+
        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return NULL;
index b2bbc842757950d9261788ab3866206553e4fb40..f433b516098a131d9e0b21d385b7697be44e8bec 100644 (file)
@@ -659,8 +659,12 @@ static struct io_pgtable *
 arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
 {
        u64 reg;
-       struct arm_lpae_io_pgtable *data = arm_lpae_alloc_pgtable(cfg);
+       struct arm_lpae_io_pgtable *data;
+
+       if (cfg->quirks & ~IO_PGTABLE_QUIRK_ARM_NS)
+               return NULL;
 
+       data = arm_lpae_alloc_pgtable(cfg);
        if (!data)
                return NULL;
 
@@ -743,8 +747,13 @@ static struct io_pgtable *
 arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
 {
        u64 reg, sl;
-       struct arm_lpae_io_pgtable *data = arm_lpae_alloc_pgtable(cfg);
+       struct arm_lpae_io_pgtable *data;
+
+       /* The NS quirk doesn't apply at stage 2 */
+       if (cfg->quirks)
+               return NULL;
 
+       data = arm_lpae_alloc_pgtable(cfg);
        if (!data)
                return NULL;
 
index 4faee7d23ee9709e72883263181c872ab04259ed..d4f502742e3b4af6948a7256de5f338a9a2a1547 100644 (file)
@@ -47,10 +47,24 @@ struct iommu_gather_ops {
  *                 page table walker.
  */
 struct io_pgtable_cfg {
-       #define IO_PGTABLE_QUIRK_ARM_NS         BIT(0) /* Set NS bit in PTEs */
-       #define IO_PGTABLE_QUIRK_NO_PERMS       BIT(1) /* No AP/XN bits */
-       #define IO_PGTABLE_QUIRK_TLBI_ON_MAP    BIT(2) /* TLB Inv. on map */
-       int                             quirks;
+       /*
+        * IO_PGTABLE_QUIRK_ARM_NS: (ARM formats) Set NS and NSTABLE bits in
+        *      stage 1 PTEs, for hardware which insists on validating them
+        *      even in non-secure state where they should normally be ignored.
+        *
+        * IO_PGTABLE_QUIRK_NO_PERMS: Ignore the IOMMU_READ, IOMMU_WRITE and
+        *      IOMMU_NOEXEC flags and map everything with full access, for
+        *      hardware which does not implement the permissions of a given
+        *      format, and/or requires some format-specific default value.
+        *
+        * IO_PGTABLE_QUIRK_TLBI_ON_MAP: If the format forbids caching invalid
+        *      (unmapped) entries but the hardware might do so anyway, perform
+        *      TLB maintenance when mapping as well as when unmapping.
+        */
+       #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)
+       unsigned long                   quirks;
        unsigned long                   pgsize_bitmap;
        unsigned int                    ias;
        unsigned int                    oas;