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 0312fe66475c2a8c985e86aa3250ee82b0fc8496..867c0f837e28f165323eeded477355b2dc823d2c 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 64336f666fb61ac0cd97b1e7afc92dda343d65fe..c17496bc37f01adbf65bcc0dcbac4010bb8e7ed2 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 62b507deea9da136cc26cf32388a5a3358efa251..0d30403b6c95977c6467cd130ac78889c406e240 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 01cef6b40829adb87460f9b2b8d141853ed4f45d..6e070db1022e69e55a229117839463057edc8a30 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 7a1e075969a353a54b1763d9d4069e98bb0af519..46d4bef61655cefa51fe4d2ef194827399d7e4a5 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 4eb43b65a34d999844970f0b16e4d480e21be9f7..bfce7ee8efd836ea632cb5990637fe7990a3a6af 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 fd12a1977ba876782f1ed59183554953c11d89a1..8a02438232c49cdf126435a64edf3591f5e5afaf 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 87ec7ae73cb1a1a3ca5390ef1ab9da4e35cd107c..2efc921506c4b277253e111f0fb45d1bab458369 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 4d7142beac7263cb6b7b3ee13ddb734b53828006..302fa72d0d5a58041e166e5f228612276a0e33dd 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. */