1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2013 Altera Corporation
3*4882a593Smuzhiyun * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
4*4882a593Smuzhiyun * Copyright (C) 2009 Wind River Systems Inc
5*4882a593Smuzhiyun * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
6*4882a593Smuzhiyun * Copyright (C) 2004 Microtronix Datacom Ltd
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * based on arch/m68k/mm/init.c
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
11*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive
12*4882a593Smuzhiyun * for more details.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/signal.h>
16*4882a593Smuzhiyun #include <linux/sched.h>
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/errno.h>
19*4882a593Smuzhiyun #include <linux/string.h>
20*4882a593Smuzhiyun #include <linux/types.h>
21*4882a593Smuzhiyun #include <linux/ptrace.h>
22*4882a593Smuzhiyun #include <linux/mman.h>
23*4882a593Smuzhiyun #include <linux/mm.h>
24*4882a593Smuzhiyun #include <linux/init.h>
25*4882a593Smuzhiyun #include <linux/pagemap.h>
26*4882a593Smuzhiyun #include <linux/memblock.h>
27*4882a593Smuzhiyun #include <linux/slab.h>
28*4882a593Smuzhiyun #include <linux/binfmts.h>
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <asm/setup.h>
31*4882a593Smuzhiyun #include <asm/page.h>
32*4882a593Smuzhiyun #include <asm/sections.h>
33*4882a593Smuzhiyun #include <asm/tlb.h>
34*4882a593Smuzhiyun #include <asm/mmu_context.h>
35*4882a593Smuzhiyun #include <asm/cpuinfo.h>
36*4882a593Smuzhiyun #include <asm/processor.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun pgd_t *pgd_current;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*
41*4882a593Smuzhiyun * paging_init() continues the virtual memory environment setup which
42*4882a593Smuzhiyun * was begun by the code in arch/head.S.
43*4882a593Smuzhiyun * The parameters are pointers to where to stick the starting and ending
44*4882a593Smuzhiyun * addresses of available kernel virtual memory.
45*4882a593Smuzhiyun */
paging_init(void)46*4882a593Smuzhiyun void __init paging_init(void)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun pagetable_init();
51*4882a593Smuzhiyun pgd_current = swapper_pg_dir;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun max_zone_pfn[ZONE_NORMAL] = max_mapnr;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* pass the memory from the bootmem allocator to the main allocator */
56*4882a593Smuzhiyun free_area_init(max_zone_pfn);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun flush_dcache_range((unsigned long)empty_zero_page,
59*4882a593Smuzhiyun (unsigned long)empty_zero_page + PAGE_SIZE);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
mem_init(void)62*4882a593Smuzhiyun void __init mem_init(void)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun unsigned long end_mem = memory_end; /* this must not include
65*4882a593Smuzhiyun kernel stack at top */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun pr_debug("mem_init: start=%lx, end=%lx\n", memory_start, memory_end);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun end_mem &= PAGE_MASK;
70*4882a593Smuzhiyun high_memory = __va(end_mem);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* this will put all memory onto the freelists */
73*4882a593Smuzhiyun memblock_free_all();
74*4882a593Smuzhiyun mem_init_print_info(NULL);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
mmu_init(void)77*4882a593Smuzhiyun void __init mmu_init(void)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun flush_tlb_all();
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #define __page_aligned(order) __aligned(PAGE_SIZE << (order))
83*4882a593Smuzhiyun pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
84*4882a593Smuzhiyun pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
85*4882a593Smuzhiyun static struct page *kuser_page[1];
86*4882a593Smuzhiyun
alloc_kuser_page(void)87*4882a593Smuzhiyun static int alloc_kuser_page(void)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun extern char __kuser_helper_start[], __kuser_helper_end[];
90*4882a593Smuzhiyun int kuser_sz = __kuser_helper_end - __kuser_helper_start;
91*4882a593Smuzhiyun unsigned long vpage;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun vpage = get_zeroed_page(GFP_ATOMIC);
94*4882a593Smuzhiyun if (!vpage)
95*4882a593Smuzhiyun return -ENOMEM;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* Copy kuser helpers */
98*4882a593Smuzhiyun memcpy((void *)vpage, __kuser_helper_start, kuser_sz);
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun flush_icache_range(vpage, vpage + KUSER_SIZE);
101*4882a593Smuzhiyun kuser_page[0] = virt_to_page(vpage);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun arch_initcall(alloc_kuser_page);
106*4882a593Smuzhiyun
arch_setup_additional_pages(struct linux_binprm * bprm,int uses_interp)107*4882a593Smuzhiyun int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct mm_struct *mm = current->mm;
110*4882a593Smuzhiyun int ret;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun mmap_write_lock(mm);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* Map kuser helpers to user space address */
115*4882a593Smuzhiyun ret = install_special_mapping(mm, KUSER_BASE, KUSER_SIZE,
116*4882a593Smuzhiyun VM_READ | VM_EXEC | VM_MAYREAD |
117*4882a593Smuzhiyun VM_MAYEXEC, kuser_page);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun mmap_write_unlock(mm);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun return ret;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
arch_vma_name(struct vm_area_struct * vma)124*4882a593Smuzhiyun const char *arch_vma_name(struct vm_area_struct *vma)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun return (vma->vm_start == KUSER_BASE) ? "[kuser]" : NULL;
127*4882a593Smuzhiyun }
128