]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-next/hugepages' of git://git.linaro.org/people/stevecapper/linux...
authorCatalin Marinas <catalin.marinas@arm.com>
Mon, 1 Jul 2013 10:20:58 +0000 (11:20 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 1 Jul 2013 10:20:58 +0000 (11:20 +0100)
* 'for-next/hugepages' of git://git.linaro.org/people/stevecapper/linux:
  ARM64: mm: THP support.
  ARM64: mm: Raise MAX_ORDER for 64KB pages and THP.
  ARM64: mm: HugeTLB support.
  ARM64: mm: Move PTE_PROT_NONE bit.
  ARM64: mm: Make PAGE_NONE pages read only and no-execute.
  ARM64: mm: Restore memblock limit when map_mem finished.
  mm: thp: Correct the HPAGE_PMD_ORDER check.
  x86: mm: Remove general hugetlb code from x86.
  mm: hugetlb: Copy general hugetlb code from x86 to mm.
  x86: mm: Remove x86 version of huge_pmd_share.
  mm: hugetlb: Copy huge_pmd_share from x86 to mm.

Conflicts:
arch/arm64/Kconfig
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h

1  2 
arch/arm64/Kconfig
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/mm/mmu.c

diff --combined arch/arm64/Kconfig
index 1fac4e5a1c4357996732cef141d9ecf66484396a,308a55636f76c1bde5d445d619dd52bafd20215e..4143d9b0d87af3e511a5324c6528a3150f2046a2
@@@ -7,7 -7,6 +7,7 @@@ config ARM6
        select ARM_AMBA
        select ARM_ARCH_TIMER
        select ARM_GIC
 +      select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        select COMMON_CLK
        select GENERIC_CLOCKEVENTS
@@@ -112,11 -111,6 +112,11 @@@ config ARCH_VEXPRES
          This enables support for the ARMv8 software model (Versatile
          Express).
  
 +config ARCH_XGENE
 +      bool "AppliedMicro X-Gene SOC Family"
 +      help
 +        This enables support for AppliedMicro X-Gene SOC Family
 +
  endmenu
  
  menu "Bus support"
@@@ -154,8 -148,6 +154,8 @@@ config NR_CPU
        int "Maximum number of CPUs (2-32)"
        range 2 32
        depends on SMP
 +      # These have to remain sorted largest to smallest
 +      default "8" if ARCH_XGENE
        default "4"
  
  source kernel/Kconfig.preempt
@@@ -188,18 -180,25 +188,35 @@@ config HW_PERF_EVENT
          Enable hardware performance counter support for perf events. If
          disabled, perf events will use software events only.
  
+ config SYS_SUPPORTS_HUGETLBFS
+       def_bool y
+ config ARCH_WANT_GENERAL_HUGETLB
+       def_bool y
+ config ARCH_WANT_HUGE_PMD_SHARE
+       def_bool y if !ARM64_64K_PAGES
+ config HAVE_ARCH_TRANSPARENT_HUGEPAGE
+       def_bool y
  source "mm/Kconfig"
  
 +config XEN_DOM0
 +      def_bool y
 +      depends on XEN
 +
 +config XEN
 +      bool "Xen guest support on ARM64 (EXPERIMENTAL)"
 +      depends on ARM64 && OF
 +      help
 +        Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64.
 +
+ config FORCE_MAX_ZONEORDER
+       int
+       default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+       default "11"
  endmenu
  
  menu "Boot options"
index 66367c6c6527b7e6307ed25952364ee3541d659f,63c9d0de05bb29c66b827297957f1fd232dfdcfe..e182a356c979d04e0f6cf811ecfa5b87c915657b
  /*
   * Hardware page table definitions.
   *
+  * Level 1 descriptor (PUD).
+  */
+ #define PUD_TABLE_BIT         (_AT(pgdval_t, 1) << 1)
+ /*
   * Level 2 descriptor (PMD).
   */
  #define PMD_TYPE_MASK         (_AT(pmdval_t, 3) << 0)
  #define PMD_TYPE_FAULT                (_AT(pmdval_t, 0) << 0)
  #define PMD_TYPE_TABLE                (_AT(pmdval_t, 3) << 0)
  #define PMD_TYPE_SECT         (_AT(pmdval_t, 1) << 0)
+ #define PMD_TABLE_BIT         (_AT(pmdval_t, 1) << 1)
  
  /*
   * Section
   */
- #define PMD_SECT_USER         (_AT(pteval_t, 1) << 6)         /* AP[1] */
+ #define PMD_SECT_VALID                (_AT(pmdval_t, 1) << 0)
+ #define PMD_SECT_PROT_NONE    (_AT(pmdval_t, 1) << 2)
+ #define PMD_SECT_USER         (_AT(pmdval_t, 1) << 6)         /* AP[1] */
+ #define PMD_SECT_RDONLY               (_AT(pmdval_t, 1) << 7)         /* AP[2] */
  #define PMD_SECT_S            (_AT(pmdval_t, 3) << 8)
  #define PMD_SECT_AF           (_AT(pmdval_t, 1) << 10)
  #define PMD_SECT_NG           (_AT(pmdval_t, 1) << 11)
@@@ -54,6 -64,7 +64,7 @@@
  #define PTE_TYPE_MASK         (_AT(pteval_t, 3) << 0)
  #define PTE_TYPE_FAULT                (_AT(pteval_t, 0) << 0)
  #define PTE_TYPE_PAGE         (_AT(pteval_t, 3) << 0)
+ #define PTE_TABLE_BIT         (_AT(pteval_t, 1) << 1)
  #define PTE_USER              (_AT(pteval_t, 1) << 6)         /* AP[1] */
  #define PTE_RDONLY            (_AT(pteval_t, 1) << 7)         /* AP[2] */
  #define PTE_SHARED            (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
  #define PTE_ATTRINDX(t)               (_AT(pteval_t, (t)) << 2)
  #define PTE_ATTRINDX_MASK     (_AT(pteval_t, 7) << 2)
  
 +/*
 + * 2nd stage PTE definitions
 + */
 +#define PTE_S2_RDONLY         (_AT(pteval_t, 1) << 6)   /* HAP[2:1] */
 +#define PTE_S2_RDWR           (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
 +
 +/*
 + * Memory Attribute override for Stage-2 (MemAttr[3:0])
 + */
 +#define PTE_S2_MEMATTR(t)     (_AT(pteval_t, (t)) << 2)
 +#define PTE_S2_MEMATTR_MASK   (_AT(pteval_t, 0xf) << 2)
 +
 +/*
 + * EL2/HYP PTE/PMD definitions
 + */
 +#define PMD_HYP                       PMD_SECT_USER
 +#define PTE_HYP                       PTE_USER
 +
  /*
   * 40-bit physical address supported.
   */
index 5588e8ad9762049be16ed87a41109570f91982da,720fc4a2be494f72c840d39623ec96d2fe928c59..065e58f01b1ed1dc68ed6c22ff3f2cfeed4a40f9
@@@ -25,8 -25,8 +25,8 @@@
   * Software defined PTE bits definition.
   */
  #define PTE_VALID             (_AT(pteval_t, 1) << 0)
- #define PTE_PROT_NONE         (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */
- #define PTE_FILE              (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
+ #define PTE_PROT_NONE         (_AT(pteval_t, 1) << 2) /* only when !PTE_VALID */
+ #define PTE_FILE              (_AT(pteval_t, 1) << 3) /* only when !pte_present() */
  #define PTE_DIRTY             (_AT(pteval_t, 1) << 55)
  #define PTE_SPECIAL           (_AT(pteval_t, 1) << 56)
  
@@@ -66,7 -66,7 +66,7 @@@ extern pgprot_t pgprot_default
  
  #define _MOD_PROT(p, b)               __pgprot_modify(p, 0, b)
  
- #define PAGE_NONE             __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE)
+ #define PAGE_NONE             __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
  #define PAGE_SHARED           _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
  #define PAGE_SHARED_EXEC      _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
  #define PAGE_COPY             _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
  #define PAGE_KERNEL           _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
  #define PAGE_KERNEL_EXEC      _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
  
- #define __PAGE_NONE           __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE)
 +#define PAGE_HYP              _MOD_PROT(pgprot_default, PTE_HYP)
 +#define PAGE_HYP_DEVICE               __pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
 +
 +#define PAGE_S2                       __pgprot_modify(pgprot_default, PTE_S2_MEMATTR_MASK, PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
 +#define PAGE_S2_DEVICE                __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN)
 +
+ #define __PAGE_NONE           __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
  #define __PAGE_SHARED         __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
  #define __PAGE_SHARED_EXEC    __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
  #define __PAGE_COPY           __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
@@@ -125,7 -119,7 +125,7 @@@ extern struct page *empty_zero_page
  #define pte_none(pte)         (!pte_val(pte))
  #define pte_clear(mm,addr,ptep)       set_pte(ptep, __pte(0))
  #define pte_page(pte)         (pfn_to_page(pte_pfn(pte)))
 -#define pte_offset_kernel(dir,addr)   (pmd_page_vaddr(*(dir)) + __pte_index(addr))
 +#define pte_offset_kernel(dir,addr)   (pmd_page_vaddr(*(dir)) + pte_index(addr))
  
  #define pte_offset_map(dir,addr)      pte_offset_kernel((dir), (addr))
  #define pte_offset_map_nested(dir,addr)       pte_offset_kernel((dir), (addr))
@@@ -179,11 -173,75 +179,75 @@@ static inline void set_pte_at(struct mm
  /*
   * Huge pte definitions.
   */
- #define pte_huge(pte)         ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
- #define pte_mkhuge(pte)               (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
+ #define pte_huge(pte)         (!(pte_val(pte) & PTE_TABLE_BIT))
+ #define pte_mkhuge(pte)               (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
+ /*
+  * Hugetlb definitions.
+  */
+ #define HUGE_MAX_HSTATE               2
+ #define HPAGE_SHIFT           PMD_SHIFT
+ #define HPAGE_SIZE            (_AC(1, UL) << HPAGE_SHIFT)
+ #define HPAGE_MASK            (~(HPAGE_SIZE - 1))
+ #define HUGETLB_PAGE_ORDER    (HPAGE_SHIFT - PAGE_SHIFT)
  
  #define __HAVE_ARCH_PTE_SPECIAL
  
+ /*
+  * Software PMD bits for THP
+  */
+ #define PMD_SECT_DIRTY                (_AT(pmdval_t, 1) << 55)
+ #define PMD_SECT_SPLITTING    (_AT(pmdval_t, 1) << 57)
+ /*
+  * THP definitions.
+  */
+ #define pmd_young(pmd)                (pmd_val(pmd) & PMD_SECT_AF)
+ #define __HAVE_ARCH_PMD_WRITE
+ #define pmd_write(pmd)                (!(pmd_val(pmd) & PMD_SECT_RDONLY))
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ #define pmd_trans_huge(pmd)   (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
+ #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+ #endif
+ #define PMD_BIT_FUNC(fn,op) \
+ static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+ PMD_BIT_FUNC(wrprotect,       |= PMD_SECT_RDONLY);
+ PMD_BIT_FUNC(mkold,   &= ~PMD_SECT_AF);
+ PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
+ PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
+ PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
+ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
+ PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+ #define pmd_mkhuge(pmd)               (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
+ #define pmd_pfn(pmd)          (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
+ #define pfn_pmd(pfn,prot)     (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+ #define mk_pmd(page,prot)     pfn_pmd(page_to_pfn(page),prot)
+ #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
+ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+ {
+       const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
+                             PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
+                             PMD_SECT_VALID;
+       pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
+       return pmd;
+ }
+ #define set_pmd_at(mm, addr, pmdp, pmd)       set_pmd(pmdp, pmd)
+ static inline int has_transparent_hugepage(void)
+ {
+       return 1;
+ }
  /*
   * Mark the prot value as uncacheable and unbufferable.
   */
@@@ -203,12 -261,6 +267,12 @@@ extern pgprot_t phys_mem_access_prot(st
  
  #define pmd_bad(pmd)          (!(pmd_val(pmd) & 2))
  
 +#define pmd_table(pmd)                ((pmd_val(pmd) & PMD_TYPE_MASK) == \
 +                               PMD_TYPE_TABLE)
 +#define pmd_sect(pmd)         ((pmd_val(pmd) & PMD_TYPE_MASK) == \
 +                               PMD_TYPE_SECT)
 +
 +
  static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
  {
        *pmdp = pmd;
@@@ -275,7 -327,7 +339,7 @@@ static inline pmd_t *pmd_offset(pud_t *
  #endif
  
  /* Find an entry in the third-level page table.. */
 -#define __pte_index(addr)     (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 +#define pte_index(addr)               (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
  
  static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  {
@@@ -293,12 -345,12 +357,12 @@@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]
  
  /*
   * Encode and decode a swap entry:
-  *    bits 0-1:       present (must be zero)
-  *    bit  2:         PTE_FILE
-  *    bits 3-8:       swap type
+  *    bits 0, 2:      present (must both be zero)
+  *    bit  3:         PTE_FILE
+  *    bits 4-8:       swap type
   *    bits 9-63:      swap offset
   */
- #define __SWP_TYPE_SHIFT      3
+ #define __SWP_TYPE_SHIFT      4
  #define __SWP_TYPE_BITS               6
  #define __SWP_TYPE_MASK               ((1 << __SWP_TYPE_BITS) - 1)
  #define __SWP_OFFSET_SHIFT    (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
  
  /*
   * Encode and decode a file entry:
-  *    bits 0-1:       present (must be zero)
-  *    bit  2:         PTE_FILE
-  *    bits 3-63:      file offset / PAGE_SIZE
+  *    bits 0, 2:      present (must both be zero)
+  *    bit  3:         PTE_FILE
+  *    bits 4-63:      file offset / PAGE_SIZE
   */
  #define pte_file(pte)         (pte_val(pte) & PTE_FILE)
- #define pte_to_pgoff(x)               (pte_val(x) >> 3)
- #define pgoff_to_pte(x)               __pte(((x) << 3) | PTE_FILE)
+ #define pte_to_pgoff(x)               (pte_val(x) >> 4)
+ #define pgoff_to_pte(x)               __pte(((x) << 4) | PTE_FILE)
  
- #define PTE_FILE_MAX_BITS     61
+ #define PTE_FILE_MAX_BITS     60
  
  extern int kern_addr_valid(unsigned long addr);
  
diff --combined arch/arm64/mm/mmu.c
index 80a369eab637cb2abed1fa3ba653c971747f288e,9fa027b39156e9326f6305d2a9ba9b2ea2cc2433..a8d1059b91b2d916f1baf60f137ac81279c9a038
@@@ -297,6 -297,16 +297,16 @@@ static void __init map_mem(void
  {
        struct memblock_region *reg;
  
+       /*
+        * Temporarily limit the memblock range. We need to do this as
+        * create_mapping requires puds, pmds and ptes to be allocated from
+        * memory addressable from the initial direct kernel mapping.
+        *
+        * The initial direct kernel mapping, located at swapper_pg_dir,
+        * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (aligned).
+        */
+       memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
        /* map all the memory banks */
        for_each_memblock(memory, reg) {
                phys_addr_t start = reg->base;
  
                create_mapping(start, __phys_to_virt(start), end - start);
        }
+       /* Limit no longer required. */
+       memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
  }
  
  /*
@@@ -317,12 -330,6 +330,6 @@@ void __init paging_init(void
  {
        void *zero_page;
  
-       /*
-        * Maximum PGDIR_SIZE addressable via the initial direct kernel
-        * mapping in swapper_pg_dir.
-        */
-       memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
        init_mem_pgprot();
        map_mem();
  
        bootmem_init();
  
        empty_zero_page = virt_to_page(zero_page);
 -      __flush_dcache_page(empty_zero_page);
  
        /*
         * TTBR0 is only used for the identity mapping at this stage. Make it