aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm
diff options
context:
space:
mode:
authorSteve Capper <steve.capper@linaro.org>2013-04-10 08:48:00 -0400
committerSteve Capper <steve.capper@linaro.org>2013-06-14 04:52:40 -0400
commit084bd29810a5689e423d2f085255a3200a03a06e (patch)
tree2c26ab58c8b95fb5c6f925044c3873979217da4a /arch/arm64/mm
parent59911ca4325dc7bd95e05c988fef3593b694e62c (diff)
ARM64: mm: HugeTLB support.
Add huge page support to ARM64, different huge page sizes are supported depending on the size of normal pages: PAGE_SIZE is 4KB: 2MB - (pmds) these can be allocated at any time. 1024MB - (puds) usually allocated on bootup with the command line with something like: hugepagesz=1G hugepages=6 PAGE_SIZE is 64KB: 512MB - (pmds) usually allocated on bootup via command line. Signed-off-by: Steve Capper <steve.capper@linaro.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
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
3 files changed, 75 insertions, 15 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);