aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSteve Capper <steve.capper@linaro.org>2013-04-19 11:23:57 -0400
committerSteve Capper <steve.capper@linaro.org>2013-06-14 04:52:41 -0400
commitaf07484863e0c20796081e57093886c22dc16705 (patch)
treec9891c1048f860413c7cfd79e2b7a686c8be0263 /arch
parentd03bb1455f3a2804539ed27047fd3b073fdeb3e0 (diff)
ARM64: mm: THP support.
Bring Transparent HugePage support to ARM. The size of a transparent huge page depends on the normal page size. A transparent huge page is always represented as a pmd. If PAGE_SIZE is 4KB, THPs are 2MB. If PAGE_SIZE is 64KB, THPs are 512MB. Signed-off-by: Steve Capper <steve.capper@linaro.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/Kconfig3
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h4
-rw-r--r--arch/arm64/include/asm/pgtable.h55
-rw-r--r--arch/arm64/include/asm/tlb.h6
-rw-r--r--arch/arm64/include/asm/tlbflush.h2
5 files changed, 70 insertions, 0 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 10607d63b945..308a55636f76 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -189,6 +189,9 @@ config ARCH_WANT_GENERAL_HUGETLB
189config ARCH_WANT_HUGE_PMD_SHARE 189config ARCH_WANT_HUGE_PMD_SHARE
190 def_bool y if !ARM64_64K_PAGES 190 def_bool y if !ARM64_64K_PAGES
191 191
192config HAVE_ARCH_TRANSPARENT_HUGEPAGE
193 def_bool y
194
192source "mm/Kconfig" 195source "mm/Kconfig"
193 196
194config FORCE_MAX_ZONEORDER 197config FORCE_MAX_ZONEORDER
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index e6e0a0d4cf9a..63c9d0de05bb 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -42,6 +42,10 @@
42/* 42/*
43 * Section 43 * Section
44 */ 44 */
45#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
46#define PMD_SECT_PROT_NONE (_AT(pmdval_t, 1) << 2)
47#define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */
48#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
45#define PMD_SECT_S (_AT(pmdval_t, 3) << 8) 49#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
46#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) 50#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
47#define PMD_SECT_NG (_AT(pmdval_t, 1) << 11) 51#define PMD_SECT_NG (_AT(pmdval_t, 1) << 11)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 21771330f809..720fc4a2be49 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -188,6 +188,61 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
188#define __HAVE_ARCH_PTE_SPECIAL 188#define __HAVE_ARCH_PTE_SPECIAL
189 189
190/* 190/*
191 * Software PMD bits for THP
192 */
193
194#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
195#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57)
196
197/*
198 * THP definitions.
199 */
200#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
201
202#define __HAVE_ARCH_PMD_WRITE
203#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
204
205#ifdef CONFIG_TRANSPARENT_HUGEPAGE
206#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
207#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
208#endif
209
210#define PMD_BIT_FUNC(fn,op) \
211static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
212
213PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
214PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
215PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
216PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
217PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
218PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
219PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
220
221#define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
222
223#define pmd_pfn(pmd) (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
224#define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
225#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
226
227#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
228
229static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
230{
231 const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
232 PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
233 PMD_SECT_VALID;
234 pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
235 return pmd;
236}
237
238#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd)
239
240static inline int has_transparent_hugepage(void)
241{
242 return 1;
243}
244
245/*
191 * Mark the prot value as uncacheable and unbufferable. 246 * Mark the prot value as uncacheable and unbufferable.
192 */ 247 */
193#define pgprot_noncached(prot) \ 248#define pgprot_noncached(prot) \
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 654f0968030b..46b3beb4b773 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -187,4 +187,10 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
187 187
188#define tlb_migrate_finish(mm) do { } while (0) 188#define tlb_migrate_finish(mm) do { } while (0)
189 189
190static inline void
191tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
192{
193 tlb_add_flush(tlb, addr);
194}
195
190#endif 196#endif
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 122d6320f745..8b482035cfc2 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -117,6 +117,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
117 dsb(); 117 dsb();
118} 118}
119 119
120#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
121
120#endif 122#endif
121 123
122#endif 124#endif