aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2013-07-01 06:20:58 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2013-07-01 06:20:58 -0400
commitaa729dccb5e8dfbc78e2e235b8754d6acccee731 (patch)
treef6123726a25957481e2528b9b6b0d0cfd992a5fb /arch/arm64/mm
parentee877b5321c4dfee9dc9f2a12b19ddcd33149f6a (diff)
parentaf07484863e0c20796081e57093886c22dc16705 (diff)
Merge branch 'for-next/hugepages' of git://git.linaro.org/people/stevecapper/linux into upstream-hugepages
* '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
Diffstat (limited to 'arch/arm64/mm')
-rw-r--r--arch/arm64/mm/Makefile1
-rw-r--r--arch/arm64/mm/fault.c19
-rw-r--r--arch/arm64/mm/hugetlbpage.c70
-rw-r--r--arch/arm64/mm/mmu.c19
4 files changed, 88 insertions, 21 deletions
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index 3140a2abcdc2..b51d36401d83 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -2,3 +2,4 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
2 cache.o copypage.o flush.o \ 2 cache.o copypage.o flush.o \
3 ioremap.o mmap.o pgd.o mmu.o \ 3 ioremap.o mmap.o pgd.o mmu.o \
4 context.o tlb.o proc.o 4 context.o tlb.o proc.o
5obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 1426468b77f3..0ecac8980aae 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -365,17 +365,6 @@ static int __kprobes do_translation_fault(unsigned long addr,
365} 365}
366 366
367/* 367/*
368 * Some section permission faults need to be handled gracefully. They can
369 * happen due to a __{get,put}_user during an oops.
370 */
371static int do_sect_fault(unsigned long addr, unsigned int esr,
372 struct pt_regs *regs)
373{
374 do_bad_area(addr, esr, regs);
375 return 0;
376}
377
378/*
379 * This abort handler always returns "fault". 368 * This abort handler always returns "fault".
380 */ 369 */
381static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) 370static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
@@ -398,12 +387,12 @@ static struct fault_info {
398 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, 387 { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
399 { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, 388 { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
400 { do_bad, SIGBUS, 0, "reserved access flag fault" }, 389 { do_bad, SIGBUS, 0, "reserved access flag fault" },
401 { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, 390 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
402 { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, 391 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
403 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, 392 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
404 { do_bad, SIGBUS, 0, "reserved permission fault" }, 393 { do_bad, SIGBUS, 0, "reserved permission fault" },
405 { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, 394 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
406 { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, 395 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
407 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, 396 { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
408 { do_bad, SIGBUS, 0, "synchronous external abort" }, 397 { do_bad, SIGBUS, 0, "synchronous external abort" },
409 { do_bad, SIGBUS, 0, "asynchronous external abort" }, 398 { do_bad, SIGBUS, 0, "asynchronous external abort" },
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
new file mode 100644
index 000000000000..2fc8258bab2d
--- /dev/null
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -0,0 +1,70 @@
1/*
2 * arch/arm64/mm/hugetlbpage.c
3 *
4 * Copyright (C) 2013 Linaro Ltd.
5 *
6 * Based on arch/x86/mm/hugetlbpage.c.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/init.h>
23#include <linux/fs.h>
24#include <linux/mm.h>
25#include <linux/hugetlb.h>
26#include <linux/pagemap.h>
27#include <linux/err.h>
28#include <linux/sysctl.h>
29#include <asm/mman.h>
30#include <asm/tlb.h>
31#include <asm/tlbflush.h>
32#include <asm/pgalloc.h>
33
34#ifndef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
35int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
36{
37 return 0;
38}
39#endif
40
41struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
42 int write)
43{
44 return ERR_PTR(-EINVAL);
45}
46
47int pmd_huge(pmd_t pmd)
48{
49 return !(pmd_val(pmd) & PMD_TABLE_BIT);
50}
51
52int pud_huge(pud_t pud)
53{
54 return !(pud_val(pud) & PUD_TABLE_BIT);
55}
56
57static __init int setup_hugepagesz(char *opt)
58{
59 unsigned long ps = memparse(opt, &opt);
60 if (ps == PMD_SIZE) {
61 hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
62 } else if (ps == PUD_SIZE) {
63 hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
64 } else {
65 pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
66 return 0;
67 }
68 return 1;
69}
70__setup("hugepagesz=", setup_hugepagesz);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 80a369eab637..a8d1059b91b2 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -297,6 +297,16 @@ static void __init map_mem(void)
297{ 297{
298 struct memblock_region *reg; 298 struct memblock_region *reg;
299 299
300 /*
301 * Temporarily limit the memblock range. We need to do this as
302 * create_mapping requires puds, pmds and ptes to be allocated from
303 * memory addressable from the initial direct kernel mapping.
304 *
305 * The initial direct kernel mapping, located at swapper_pg_dir,
306 * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (aligned).
307 */
308 memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
309
300 /* map all the memory banks */ 310 /* map all the memory banks */
301 for_each_memblock(memory, reg) { 311 for_each_memblock(memory, reg) {
302 phys_addr_t start = reg->base; 312 phys_addr_t start = reg->base;
@@ -307,6 +317,9 @@ static void __init map_mem(void)
307 317
308 create_mapping(start, __phys_to_virt(start), end - start); 318 create_mapping(start, __phys_to_virt(start), end - start);
309 } 319 }
320
321 /* Limit no longer required. */
322 memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
310} 323}
311 324
312/* 325/*
@@ -317,12 +330,6 @@ void __init paging_init(void)
317{ 330{
318 void *zero_page; 331 void *zero_page;
319 332
320 /*
321 * Maximum PGDIR_SIZE addressable via the initial direct kernel
322 * mapping in swapper_pg_dir.
323 */
324 memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
325
326 init_mem_pgprot(); 333 init_mem_pgprot();
327 map_mem(); 334 map_mem();
328 335