ARC: mm: Introduce explicit super page size support
authorVineet Gupta <vgupta@synopsys.com>
Wed, 10 Feb 2016 01:22:07 +0000 (06:52 +0530)
committerVineet Gupta <vgupta@synopsys.com>
Fri, 12 Feb 2016 06:40:25 +0000 (12:10 +0530)
MMUv4 supports 2 concurrent page sizes: Normal and Super [4K to 16M]

So far Linux supported a single super page size for a given Normal page,
depending on the software page walking address split.
e.g. we had 11:8:13 address split for 8K page, which meant super page
was 2 ^(8+13) = 2M (given that THP size has to be PMD_SHIFT)

Now we turn this around, by allowing multiple Super Pages in Kconfig
(currently 2M and 16M only) and forcing page walker address split to
PGDIR_SHIFT and PAGE_SHIFT

For configs without Super page, things are same as before and
PGDIR_SHIFT can be hacked to get non default address split

The motivation for this change is a customer who needs 16M super page
and a 8K Normal page combo.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
arch/arc/Kconfig
arch/arc/include/asm/pgtable.h

index bb15e80..63979c7 100644 (file)
@@ -341,6 +341,19 @@ config ARC_PAGE_SIZE_4K
 
 endchoice
 
+choice
+       prompt "MMU Super Page Size"
+       depends on ISA_ARCV2 && TRANSPARENT_HUGEPAGE
+       default ARC_HUGEPAGE_2M
+
+config ARC_HUGEPAGE_2M
+       bool "2MB"
+
+config ARC_HUGEPAGE_16M
+       bool "16MB"
+
+endchoice
+
 if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
@@ -569,6 +582,12 @@ endmenu
 endmenu         # "ARC Architecture Configuration"
 
 source "mm/Kconfig"
+
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       default "12" if ARC_HUGEPAGE_16M
+       default "11"
+
 source "net/Kconfig"
 source "drivers/Kconfig"
 source "fs/Kconfig"
index 57af2f0..d426d42 100644 (file)
 #define __S111  PAGE_U_X_W_R
 
 /****************************************************************
- * Page Table Lookup split
+ * 2 tier (PGD:PTE) software page walker
  *
- * We implement 2 tier paging and since this is all software, we are free
- * to customize the span of a PGD / PTE entry to suit us
- *
- *                     32 bit virtual address
+ * [31]                    32 bit virtual address              [0]
  * -------------------------------------------------------
- * | BITS_FOR_PGD    |  BITS_FOR_PTE    |  BITS_IN_PAGE  |
+ * |               | <------------ PGDIR_SHIFT ----------> |
+ * |              |                                     |
+ * | BITS_FOR_PGD  |  BITS_FOR_PTE  | <-- PAGE_SHIFT --> |
  * -------------------------------------------------------
  *       |                  |                |
  *       |                  |                --> off in page frame
- *       |                 |
  *       |                  ---> index into Page Table
- *       |
  *       ----> index into Page Directory
+ *
+ * In a single page size configuration, only PAGE_SHIFT is fixed
+ * So both PGD and PTE sizing can be tweaked
+ *  e.g. 8K page (PAGE_SHIFT 13) can have
+ *  - PGDIR_SHIFT 21  -> 11:8:13 address split
+ *  - PGDIR_SHIFT 24  -> 8:11:13 address split
+ *
+ * If Super Page is configured, PGDIR_SHIFT becomes fixed too,
+ * so the sizing flexibility is gone.
  */
 
-#define BITS_IN_PAGE   PAGE_SHIFT
-
-/* Optimal Sizing of Pg Tbl - based on MMU page size */
-#if defined(CONFIG_ARC_PAGE_SIZE_8K)
-#define BITS_FOR_PTE   8               /* 11:8:13 */
-#elif defined(CONFIG_ARC_PAGE_SIZE_16K)
-#define BITS_FOR_PTE   8               /* 10:8:14 */
-#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
-#define BITS_FOR_PTE   9               /* 11:9:12 */
+#if defined(CONFIG_ARC_HUGEPAGE_16M)
+#define PGDIR_SHIFT    24
+#elif defined(CONFIG_ARC_HUGEPAGE_2M)
+#define PGDIR_SHIFT    21
+#else
+/*
+ * Only Normal page support so "hackable" (see comment above)
+ * Default value provides 11:8:13 (8K), 11:9:12 (4K)
+ */
+#define PGDIR_SHIFT    21
 #endif
 
-#define BITS_FOR_PGD   (32 - BITS_FOR_PTE - BITS_IN_PAGE)
+#define BITS_FOR_PTE   (PGDIR_SHIFT - PAGE_SHIFT)
+#define BITS_FOR_PGD   (32 - PGDIR_SHIFT)
 
-#define PGDIR_SHIFT    (32 - BITS_FOR_PGD)
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)    /* vaddr span, not PDG sz */
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))