xtensa: add alternative kernel memory layouts
authorMax Filippov <jcmvbkbc@gmail.com>
Mon, 11 Apr 2016 18:14:17 +0000 (21:14 +0300)
committerMax Filippov <jcmvbkbc@gmail.com>
Sun, 24 Jul 2016 03:33:58 +0000 (06:33 +0300)
MMUv3 is able to support low memory bigger than 128MB.
Implement 256MB and 512MB KSEG layouts:

- add Kconfig selector for KSEG layout;
- add KSEG base address, size and alignment definitions to
  arch/xtensa/include/asm/kmem_layout.h;
- use new definitions in TLB initialization;
- add build time memory map consistency checks.

See Documentation/xtensa/mmu.txt for the details of new memory layouts.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Documentation/xtensa/mmu.txt
arch/xtensa/Kconfig
arch/xtensa/include/asm/fixmap.h
arch/xtensa/include/asm/highmem.h
arch/xtensa/include/asm/initialize_mmu.h
arch/xtensa/include/asm/kmem_layout.h
arch/xtensa/include/asm/page.h
arch/xtensa/include/uapi/asm/types.h
arch/xtensa/mm/init.c

index 0312fe6..867c0f8 100644 (file)
@@ -62,3 +62,127 @@ limitations apply:
 
 6. The IO area covers the entire 256MB segment of parent-bus-address; the
    "ranges" triplet length field is ignored
+
+
+MMUv3 address space layouts.
+============================
+
+Default MMUv2-compatible layout.
+
+                      Symbol                   VADDR       Size
++------------------+
+| Userspace        |                           0x00000000  TASK_SIZE
++------------------+                           0x40000000
++------------------+
+| Page table       |                           0x80000000
++------------------+                           0x80400000
++------------------+
+| KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
+|                  |                                       (4MB * DCACHE_N_COLORS)
++------------------+
+| Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+|                  |                                       NR_CPUS *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
++------------------+  FIXADDR_TOP              0xbffff000
++------------------+
+| VMALLOC area     |  VMALLOC_START            0xc0000000  128MB - 64KB
++------------------+  VMALLOC_END
+| Cache aliasing   |  TLBTEMP_BASE_1           0xc7ff0000  DCACHE_WAY_SIZE
+| remap area 1     |
++------------------+
+| Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+| remap area 2     |
++------------------+
++------------------+
+| Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xd0000000  128MB
++------------------+
+| Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xd8000000  128MB
++------------------+
+| Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
++------------------+
+| Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
++------------------+
+
+
+256MB cached + 256MB uncached layout.
+
+                      Symbol                   VADDR       Size
++------------------+
+| Userspace        |                           0x00000000  TASK_SIZE
++------------------+                           0x40000000
++------------------+
+| Page table       |                           0x80000000
++------------------+                           0x80400000
++------------------+
+| KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
+|                  |                                       (4MB * DCACHE_N_COLORS)
++------------------+
+| Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+|                  |                                       NR_CPUS *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
++------------------+  FIXADDR_TOP              0x9ffff000
++------------------+
+| VMALLOC area     |  VMALLOC_START            0xa0000000  128MB - 64KB
++------------------+  VMALLOC_END
+| Cache aliasing   |  TLBTEMP_BASE_1           0xa7ff0000  DCACHE_WAY_SIZE
+| remap area 1     |
++------------------+
+| Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+| remap area 2     |
++------------------+
++------------------+
+| Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xb0000000  256MB
++------------------+
+| Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  256MB
++------------------+
++------------------+
+| Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
++------------------+
+| Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
++------------------+
+
+
+512MB cached + 512MB uncached layout.
+
+                      Symbol                   VADDR       Size
++------------------+
+| Userspace        |                           0x00000000  TASK_SIZE
++------------------+                           0x40000000
++------------------+
+| Page table       |                           0x80000000
++------------------+                           0x80400000
++------------------+
+| KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
+|                  |                                       (4MB * DCACHE_N_COLORS)
++------------------+
+| Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+|                  |                                       NR_CPUS *
+|                  |                                       DCACHE_N_COLORS *
+|                  |                                       PAGE_SIZE
++------------------+  FIXADDR_TOP              0x8ffff000
++------------------+
+| VMALLOC area     |  VMALLOC_START            0x90000000  128MB - 64KB
++------------------+  VMALLOC_END
+| Cache aliasing   |  TLBTEMP_BASE_1           0x97ff0000  DCACHE_WAY_SIZE
+| remap area 1     |
++------------------+
+| Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+| remap area 2     |
++------------------+
++------------------+
+| Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xa0000000  512MB
++------------------+
+| Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  512MB
++------------------+
+| Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
++------------------+
+| Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
++------------------+
index 64336f6..c17496b 100644 (file)
@@ -236,6 +236,50 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 
          If in doubt, say Y.
 
+config KSEG_PADDR
+       hex "Physical address of the KSEG mapping"
+       depends on INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX && MMU
+       default 0x00000000
+       help
+         This is the physical address where KSEG is mapped. Please refer to
+         the chosen KSEG layout help for the required address alignment.
+         Unpacked kernel image (including vectors) must be located completely
+         within KSEG.
+         Physical memory below this address is not available to linux.
+
+         If unsure, leave the default value here.
+
+choice
+       prompt "KSEG layout"
+       depends on MMU
+       default XTENSA_KSEG_MMU_V2
+
+config XTENSA_KSEG_MMU_V2
+       bool "MMUv2: 128MB cached + 128MB uncached"
+       help
+         MMUv2 compatible kernel memory map: TLB way 5 maps 128MB starting
+         at KSEG_PADDR to 0xd0000000 with cache and to 0xd8000000
+         without cache.
+         KSEG_PADDR must be aligned to 128MB.
+
+config XTENSA_KSEG_256M
+       bool "256MB cached + 256MB uncached"
+       depends on INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+       help
+         TLB way 6 maps 256MB starting at KSEG_PADDR to 0xb0000000
+         with cache and to 0xc0000000 without cache.
+         KSEG_PADDR must be aligned to 256MB.
+
+config XTENSA_KSEG_512M
+       bool "512MB cached + 512MB uncached"
+       depends on INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+       help
+         TLB way 6 maps 512MB starting at KSEG_PADDR to 0xa0000000
+         with cache and to 0xc0000000 without cache.
+         KSEG_PADDR must be aligned to 256MB.
+
+endchoice
+
 config HIGHMEM
        bool "High Memory Support"
        depends on MMU
index 62b507d..0d30403 100644 (file)
@@ -59,6 +59,11 @@ enum fixed_addresses {
  */
 static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 {
+       /* Check if this memory layout is broken because fixmap overlaps page
+        * table.
+        */
+       BUILD_BUG_ON(FIXADDR_START <
+                    XCHAL_PAGE_TABLE_VADDR + XCHAL_PAGE_TABLE_SIZE);
        BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
        return __fix_to_virt(idx);
 }
index 01cef6b..6e070db 100644 (file)
@@ -68,6 +68,11 @@ void kunmap_high(struct page *page);
 
 static inline void *kmap(struct page *page)
 {
+       /* Check if this memory layout is broken because PKMAP overlaps
+        * page table.
+        */
+       BUILD_BUG_ON(PKMAP_BASE <
+                    XCHAL_PAGE_TABLE_VADDR + XCHAL_PAGE_TABLE_SIZE);
        BUG_ON(in_interrupt());
        if (!PageHighMem(page))
                return page_address(page);
index 7a1e075..46d4bef 100644 (file)
        add     a5, a5, a4
        bne     a5, a2, 3b
 
-       /* Step 4: Setup MMU with the old V2 mappings. */
+       /* Step 4: Setup MMU with the requested static mappings. */
+
        movi    a6, 0x01000000
        wsr     a6, ITLBCFG
        wsr     a6, DTLBCFG
        isync
 
-       movi    a5, 0xd0000005
-       movi    a4, CA_WRITEBACK
+       movi    a5, XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_TLB_WAY
+       movi    a4, XCHAL_KSEG_PADDR + CA_WRITEBACK
+       wdtlb   a4, a5
+       witlb   a4, a5
+
+       movi    a5, XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_TLB_WAY
+       movi    a4, XCHAL_KSEG_PADDR + CA_BYPASS
        wdtlb   a4, a5
        witlb   a4, a5
 
-       movi    a5, 0xd8000005
-       movi    a4, CA_BYPASS
+#ifdef CONFIG_XTENSA_KSEG_512M
+       movi    a5, XCHAL_KSEG_CACHED_VADDR + 0x10000000 + XCHAL_KSEG_TLB_WAY
+       movi    a4, XCHAL_KSEG_PADDR + 0x10000000 + CA_WRITEBACK
        wdtlb   a4, a5
        witlb   a4, a5
 
+       movi    a5, XCHAL_KSEG_BYPASS_VADDR + 0x10000000 + XCHAL_KSEG_TLB_WAY
+       movi    a4, XCHAL_KSEG_PADDR + 0x10000000 + CA_BYPASS
+       wdtlb   a4, a5
+       witlb   a4, a5
+#endif
+
        movi    a5, XCHAL_KIO_CACHED_VADDR + 6
        movi    a4, XCHAL_KIO_DEFAULT_PADDR + CA_WRITEBACK
        wdtlb   a4, a5
index 4eb43b6..bfce7ee 100644 (file)
 
 #include <asm/types.h>
 
+#ifdef CONFIG_MMU
+
 /*
  * Fixed TLB translations in the processor.
  */
 
+#define XCHAL_PAGE_TABLE_VADDR __XTENSA_UL_CONST(0x80000000)
+#define XCHAL_PAGE_TABLE_SIZE  __XTENSA_UL_CONST(0x00400000)
+
+#if defined(CONFIG_XTENSA_KSEG_MMU_V2)
+
 #define XCHAL_KSEG_CACHED_VADDR        __XTENSA_UL_CONST(0xd0000000)
 #define XCHAL_KSEG_BYPASS_VADDR        __XTENSA_UL_CONST(0xd8000000)
 #define XCHAL_KSEG_SIZE                __XTENSA_UL_CONST(0x08000000)
+#define XCHAL_KSEG_ALIGNMENT   __XTENSA_UL_CONST(0x08000000)
+#define XCHAL_KSEG_TLB_WAY     5
+
+#elif defined(CONFIG_XTENSA_KSEG_256M)
+
+#define XCHAL_KSEG_CACHED_VADDR        __XTENSA_UL_CONST(0xb0000000)
+#define XCHAL_KSEG_BYPASS_VADDR        __XTENSA_UL_CONST(0xc0000000)
+#define XCHAL_KSEG_SIZE                __XTENSA_UL_CONST(0x10000000)
+#define XCHAL_KSEG_ALIGNMENT   __XTENSA_UL_CONST(0x10000000)
+#define XCHAL_KSEG_TLB_WAY     6
+
+#elif defined(CONFIG_XTENSA_KSEG_512M)
+
+#define XCHAL_KSEG_CACHED_VADDR        __XTENSA_UL_CONST(0xa0000000)
+#define XCHAL_KSEG_BYPASS_VADDR        __XTENSA_UL_CONST(0xc0000000)
+#define XCHAL_KSEG_SIZE                __XTENSA_UL_CONST(0x20000000)
+#define XCHAL_KSEG_ALIGNMENT   __XTENSA_UL_CONST(0x10000000)
+#define XCHAL_KSEG_TLB_WAY     6
+
+#else
+#error Unsupported KSEG configuration
+#endif
+
+#ifdef CONFIG_KSEG_PADDR
+#define XCHAL_KSEG_PADDR        __XTENSA_UL_CONST(CONFIG_KSEG_PADDR)
+#else
 #define XCHAL_KSEG_PADDR       __XTENSA_UL_CONST(0x00000000)
+#endif
+
+#if XCHAL_KSEG_PADDR & (XCHAL_KSEG_ALIGNMENT - 1)
+#error XCHAL_KSEG_PADDR is not properly aligned to XCHAL_KSEG_ALIGNMENT
+#endif
+
+#else
+
+#define XCHAL_KSEG_CACHED_VADDR        __XTENSA_UL_CONST(0xd0000000)
+#define XCHAL_KSEG_BYPASS_VADDR        __XTENSA_UL_CONST(0xd8000000)
+#define XCHAL_KSEG_SIZE                __XTENSA_UL_CONST(0x08000000)
+
+#endif
 
 #endif
index fd12a19..8a02438 100644 (file)
 
 #ifdef CONFIG_MMU
 #define PAGE_OFFSET    XCHAL_KSEG_CACHED_VADDR
-#define MAX_MEM_PFN    XCHAL_KSEG_SIZE
+#define MAX_LOW_PFN    (PHYS_PFN(XCHAL_KSEG_PADDR) + \
+                        PHYS_PFN(XCHAL_KSEG_SIZE))
 #else
 #define PAGE_OFFSET    __XTENSA_UL_CONST(0)
-#define MAX_MEM_PFN    (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE)
+#define MAX_LOW_PFN    (PHYS_PFN(PLATFORM_DEFAULT_MEM_START) + \
+                        PHYS_PFN(PLATFORM_DEFAULT_MEM_SIZE))
 #endif
 
 #define PGTABLE_START  0x80000000
index 87ec7ae..2efc921 100644 (file)
@@ -18,7 +18,8 @@
 # define __XTENSA_UL_CONST(x)  x
 #else
 # define __XTENSA_UL(x)                ((unsigned long)(x))
-# define __XTENSA_UL_CONST(x)  x##UL
+# define ___XTENSA_UL_CONST(x) x##UL
+# define __XTENSA_UL_CONST(x)  ___XTENSA_UL_CONST(x)
 #endif
 
 #ifndef __ASSEMBLY__
index 4d7142b..302fa72 100644 (file)
@@ -266,8 +266,7 @@ void __init bootmem_init(void)
        if (min_low_pfn > max_pfn)
                panic("No memory found!\n");
 
-       max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ?
-               max_pfn : MAX_MEM_PFN >> PAGE_SHIFT;
+       max_low_pfn = min(max_pfn, MAX_LOW_PFN);
 
        /* Find an area to use for the bootmem bitmap. */