xref: /linux/arch/nios2/mm/init.c (revision 6aacab308a5dfd222b2d23662bbae60c11007cfb)
1 /*
2  * Copyright (C) 2013 Altera Corporation
3  * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
4  * Copyright (C) 2009 Wind River Systems Inc
5  *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
6  * Copyright (C) 2004 Microtronix Datacom Ltd
7  *
8  * based on arch/m68k/mm/init.c
9  *
10  * This file is subject to the terms and conditions of the GNU General Public
11  * License. See the file "COPYING" in the main directory of this archive
12  * for more details.
13  */
14 
15 #include <linux/signal.h>
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 #include <linux/types.h>
21 #include <linux/ptrace.h>
22 #include <linux/mman.h>
23 #include <linux/mm.h>
24 #include <linux/init.h>
25 #include <linux/pagemap.h>
26 #include <linux/memblock.h>
27 #include <linux/slab.h>
28 #include <linux/binfmts.h>
29 #include <linux/execmem.h>
30 
31 #include <asm/setup.h>
32 #include <asm/page.h>
33 #include <asm/sections.h>
34 #include <asm/tlb.h>
35 #include <asm/mmu_context.h>
36 #include <asm/cpuinfo.h>
37 #include <asm/processor.h>
38 
39 pgd_t *pgd_current;
40 
41 void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
42 {
43 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
44 }
45 
46 /*
47  * paging_init() continues the virtual memory environment setup which
48  * was begun by the code in arch/head.S.
49  * The parameters are pointers to where to stick the starting and ending
50  * addresses of available kernel virtual memory.
51  */
52 void __init paging_init(void)
53 {
54 	pagetable_init();
55 	pgd_current = swapper_pg_dir;
56 
57 	flush_dcache_range((unsigned long)empty_zero_page,
58 			(unsigned long)empty_zero_page + PAGE_SIZE);
59 }
60 
61 void __init mmu_init(void)
62 {
63 	flush_tlb_all();
64 }
65 
66 pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
67 pte_t invalid_pte_table[PTRS_PER_PTE] __aligned(PAGE_SIZE);
68 static struct page *kuser_page[1];
69 static struct vm_special_mapping vdso_mapping = {
70 	.name = "[vdso]",
71 	.pages = kuser_page,
72 };
73 
74 static int alloc_kuser_page(void)
75 {
76 	extern char __kuser_helper_start[], __kuser_helper_end[];
77 	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
78 	unsigned long vpage;
79 
80 	vpage = get_zeroed_page(GFP_ATOMIC);
81 	if (!vpage)
82 		return -ENOMEM;
83 
84 	/* Copy kuser helpers */
85 	memcpy((void *)vpage, __kuser_helper_start, kuser_sz);
86 
87 	flush_icache_range(vpage, vpage + KUSER_SIZE);
88 	kuser_page[0] = virt_to_page(vpage);
89 
90 	return 0;
91 }
92 arch_initcall(alloc_kuser_page);
93 
94 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
95 {
96 	struct mm_struct *mm = current->mm;
97 	struct vm_area_struct *vma;
98 
99 	mmap_write_lock(mm);
100 
101 	/* Map kuser helpers to user space address */
102 	vma = _install_special_mapping(mm, KUSER_BASE, KUSER_SIZE,
103 				      VM_READ | VM_EXEC | VM_MAYREAD |
104 				      VM_MAYEXEC, &vdso_mapping);
105 
106 	mmap_write_unlock(mm);
107 
108 	return IS_ERR(vma) ? PTR_ERR(vma) : 0;
109 }
110 
111 const char *arch_vma_name(struct vm_area_struct *vma)
112 {
113 	return (vma->vm_start == KUSER_BASE) ? "[kuser]" : NULL;
114 }
115 
116 static const pgprot_t protection_map[16] = {
117 	[VM_NONE]					= MKP(0, 0, 0),
118 	[VM_READ]					= MKP(0, 0, 1),
119 	[VM_WRITE]					= MKP(0, 0, 0),
120 	[VM_WRITE | VM_READ]				= MKP(0, 0, 1),
121 	[VM_EXEC]					= MKP(1, 0, 0),
122 	[VM_EXEC | VM_READ]				= MKP(1, 0, 1),
123 	[VM_EXEC | VM_WRITE]				= MKP(1, 0, 0),
124 	[VM_EXEC | VM_WRITE | VM_READ]			= MKP(1, 0, 1),
125 	[VM_SHARED]					= MKP(0, 0, 0),
126 	[VM_SHARED | VM_READ]				= MKP(0, 0, 1),
127 	[VM_SHARED | VM_WRITE]				= MKP(0, 1, 0),
128 	[VM_SHARED | VM_WRITE | VM_READ]		= MKP(0, 1, 1),
129 	[VM_SHARED | VM_EXEC]				= MKP(1, 0, 0),
130 	[VM_SHARED | VM_EXEC | VM_READ]			= MKP(1, 0, 1),
131 	[VM_SHARED | VM_EXEC | VM_WRITE]		= MKP(1, 1, 0),
132 	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= MKP(1, 1, 1)
133 };
134 DECLARE_VM_GET_PAGE_PROT
135 
136 #ifdef CONFIG_EXECMEM
137 static struct execmem_info execmem_info __ro_after_init;
138 
139 struct execmem_info __init *execmem_arch_setup(void)
140 {
141 	execmem_info = (struct execmem_info){
142 		.ranges = {
143 			[EXECMEM_DEFAULT] = {
144 				.start	= MODULES_VADDR,
145 				.end	= MODULES_END,
146 				.pgprot	= PAGE_KERNEL_EXEC,
147 				.alignment = 1,
148 			},
149 		},
150 	};
151 
152 	return &execmem_info;
153 }
154 #endif /* CONFIG_EXECMEM */
155