1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * linux/arch/alpha/mm/init.c
4 *
5 * Copyright (C) 1995 Linus Torvalds
6 */
7
8 /* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
9
10 #include <linux/pagemap.h>
11 #include <linux/signal.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/types.h>
17 #include <linux/ptrace.h>
18 #include <linux/mman.h>
19 #include <linux/mm.h>
20 #include <linux/swap.h>
21 #include <linux/init.h>
22 #include <linux/memblock.h> /* max_low_pfn */
23 #include <linux/vmalloc.h>
24 #include <linux/gfp.h>
25
26 #include <linux/uaccess.h>
27 #include <asm/pgalloc.h>
28 #include <asm/hwrpb.h>
29 #include <asm/dma.h>
30 #include <asm/mmu_context.h>
31 #include <asm/console.h>
32 #include <asm/tlb.h>
33 #include <asm/setup.h>
34 #include <asm/sections.h>
35
36 #include "../kernel/proto.h"
37
38 static struct pcb_struct original_pcb;
39
40 pgd_t *
pgd_alloc(struct mm_struct * mm)41 pgd_alloc(struct mm_struct *mm)
42 {
43 pgd_t *ret, *init;
44
45 ret = __pgd_alloc(mm, 0);
46 init = pgd_offset(&init_mm, 0UL);
47 if (ret) {
48 #ifdef CONFIG_ALPHA_LARGE_VMALLOC
49 memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
50 (PTRS_PER_PGD - USER_PTRS_PER_PGD - 1)*sizeof(pgd_t));
51 #else
52 pgd_val(ret[PTRS_PER_PGD-2]) = pgd_val(init[PTRS_PER_PGD-2]);
53 #endif
54
55 /* The last PGD entry is the VPTB self-map. */
56 pgd_val(ret[PTRS_PER_PGD-1])
57 = pte_val(mk_pte(virt_to_page(ret), PAGE_KERNEL));
58 }
59 return ret;
60 }
61
62
63 static inline unsigned long
load_PCB(struct pcb_struct * pcb)64 load_PCB(struct pcb_struct *pcb)
65 {
66 pcb->ksp = (unsigned long)current_stack_pointer;
67 return __reload_thread(pcb);
68 }
69
70 /* Set up initial PCB, VPTB, and other such nicities. */
71
72 static inline void
switch_to_system_map(void)73 switch_to_system_map(void)
74 {
75 unsigned long newptbr;
76 unsigned long original_pcb_ptr;
77
78 /* Initialize the kernel's page tables. Linux puts the vptb in
79 the last slot of the L1 page table. */
80 memset(swapper_pg_dir, 0, PAGE_SIZE);
81 newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
82 pgd_val(swapper_pg_dir[1023]) =
83 (newptbr << 32) | pgprot_val(PAGE_KERNEL);
84
85 /* Set the vptb. This is often done by the bootloader, but
86 shouldn't be required. */
87 if (hwrpb->vptb != 0xfffffffe00000000UL) {
88 wrvptptr(0xfffffffe00000000UL);
89 hwrpb->vptb = 0xfffffffe00000000UL;
90 hwrpb_update_checksum(hwrpb);
91 }
92
93 /* Also set up the real kernel PCB while we're at it. */
94 init_thread_info.pcb.ptbr = newptbr;
95 init_thread_info.pcb.flags = 1; /* set FEN, clear everything else */
96 original_pcb_ptr = load_PCB(&init_thread_info.pcb);
97 tbia();
98
99 /* Save off the contents of the original PCB so that we can
100 restore the original console's page tables for a clean reboot.
101
102 Note that the PCB is supposed to be a physical address, but
103 since KSEG values also happen to work, folks get confused.
104 Check this here. */
105
106 if (original_pcb_ptr < PAGE_OFFSET) {
107 original_pcb_ptr = (unsigned long)
108 phys_to_virt(original_pcb_ptr);
109 }
110 original_pcb = *(struct pcb_struct *) original_pcb_ptr;
111 }
112
113 int callback_init_done;
114
115 void * __init
callback_init(void * kernel_end)116 callback_init(void * kernel_end)
117 {
118 struct crb_struct * crb;
119 pgd_t *pgd;
120 p4d_t *p4d;
121 pud_t *pud;
122 pmd_t *pmd;
123 void *two_pages;
124
125 /* Starting at the HWRPB, locate the CRB. */
126 crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
127
128 if (alpha_using_srm) {
129 /* Tell the console whither it is to be remapped. */
130 if (srm_fixup(VMALLOC_START, (unsigned long)hwrpb))
131 __halt(); /* "We're boned." --Bender */
132
133 /* Edit the procedure descriptors for DISPATCH and FIXUP. */
134 crb->dispatch_va = (struct procdesc_struct *)
135 (VMALLOC_START + (unsigned long)crb->dispatch_va
136 - crb->map[0].va);
137 crb->fixup_va = (struct procdesc_struct *)
138 (VMALLOC_START + (unsigned long)crb->fixup_va
139 - crb->map[0].va);
140 }
141
142 switch_to_system_map();
143
144 /* Allocate one PGD and one PMD. In the case of SRM, we'll need
145 these to actually remap the console. There is an assumption
146 here that only one of each is needed, and this allows for 8MB.
147 On systems with larger consoles, additional pages will be
148 allocated as needed during the mapping process.
149
150 In the case of not SRM, but not CONFIG_ALPHA_LARGE_VMALLOC,
151 we need to allocate the PGD we use for vmalloc before we start
152 forking other tasks. */
153
154 two_pages = (void *)
155 (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
156 kernel_end = two_pages + 2*PAGE_SIZE;
157 memset(two_pages, 0, 2*PAGE_SIZE);
158
159 pgd = pgd_offset_k(VMALLOC_START);
160 p4d = p4d_offset(pgd, VMALLOC_START);
161 pud = pud_offset(p4d, VMALLOC_START);
162 pud_set(pud, (pmd_t *)two_pages);
163 pmd = pmd_offset(pud, VMALLOC_START);
164 pmd_set(pmd, (pte_t *)(two_pages + PAGE_SIZE));
165
166 if (alpha_using_srm) {
167 static struct vm_struct console_remap_vm;
168 unsigned long nr_pages = 0;
169 unsigned long vaddr;
170 unsigned long i, j;
171
172 /* calculate needed size */
173 for (i = 0; i < crb->map_entries; ++i)
174 nr_pages += crb->map[i].count;
175
176 /* register the vm area */
177 console_remap_vm.flags = VM_ALLOC;
178 console_remap_vm.size = nr_pages << PAGE_SHIFT;
179 vm_area_register_early(&console_remap_vm, PAGE_SIZE);
180
181 vaddr = (unsigned long)console_remap_vm.addr;
182
183 /* Set up the third level PTEs and update the virtual
184 addresses of the CRB entries. */
185 for (i = 0; i < crb->map_entries; ++i) {
186 unsigned long pfn = crb->map[i].pa >> PAGE_SHIFT;
187 crb->map[i].va = vaddr;
188 for (j = 0; j < crb->map[i].count; ++j) {
189 /* Newer consoles (especially on larger
190 systems) may require more pages of
191 PTEs. Grab additional pages as needed. */
192 if (pmd != pmd_offset(pud, vaddr)) {
193 memset(kernel_end, 0, PAGE_SIZE);
194 pmd = pmd_offset(pud, vaddr);
195 pmd_set(pmd, (pte_t *)kernel_end);
196 kernel_end += PAGE_SIZE;
197 }
198 set_pte(pte_offset_kernel(pmd, vaddr),
199 pfn_pte(pfn, PAGE_KERNEL));
200 pfn++;
201 vaddr += PAGE_SIZE;
202 }
203 }
204 }
205
206 callback_init_done = 1;
207 return kernel_end;
208 }
209
arch_zone_limits_init(unsigned long * max_zone_pfn)210 void __init arch_zone_limits_init(unsigned long *max_zone_pfn)
211 {
212 unsigned long dma_pfn;
213
214 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
215 max_pfn = max_low_pfn;
216
217 max_zone_pfn[ZONE_DMA] = dma_pfn;
218 max_zone_pfn[ZONE_NORMAL] = max_pfn;
219 }
220
221 /*
222 * paging_init() initializes the kernel's ZERO_PGE.
223 */
paging_init(void)224 void __init paging_init(void)
225 {
226 memset(absolute_pointer(ZERO_PGE), 0, PAGE_SIZE);
227 }
228
arch_mm_preinit(void)229 void __init arch_mm_preinit(void)
230 {
231 early_memtest(memblock_start_of_DRAM(), PFN_PHYS(max_low_pfn));
232 }
233
234 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
235 void
srm_paging_stop(void)236 srm_paging_stop (void)
237 {
238 /* Move the vptb back to where the SRM console expects it. */
239 swapper_pg_dir[1] = swapper_pg_dir[1023];
240 tbia();
241 wrvptptr(0x200000000UL);
242 hwrpb->vptb = 0x200000000UL;
243 hwrpb_update_checksum(hwrpb);
244
245 /* Reload the page tables that the console had in use. */
246 load_PCB(&original_pcb);
247 tbia();
248 }
249 #endif
250
251 static const pgprot_t protection_map[16] = {
252 [VM_NONE] = _PAGE_P(_PAGE_FOE | _PAGE_FOW |
253 _PAGE_FOR),
254 [VM_READ] = _PAGE_P(_PAGE_FOE | _PAGE_FOW),
255 [VM_WRITE] = _PAGE_P(_PAGE_FOE),
256 [VM_WRITE | VM_READ] = _PAGE_P(_PAGE_FOE),
257 [VM_EXEC] = _PAGE_P(_PAGE_FOW | _PAGE_FOR),
258 [VM_EXEC | VM_READ] = _PAGE_P(_PAGE_FOW),
259 [VM_EXEC | VM_WRITE] = _PAGE_P(0),
260 [VM_EXEC | VM_WRITE | VM_READ] = _PAGE_P(0),
261 [VM_SHARED] = _PAGE_S(_PAGE_FOE | _PAGE_FOW |
262 _PAGE_FOR),
263 [VM_SHARED | VM_READ] = _PAGE_S(_PAGE_FOE | _PAGE_FOW),
264 [VM_SHARED | VM_WRITE] = _PAGE_S(_PAGE_FOE),
265 [VM_SHARED | VM_WRITE | VM_READ] = _PAGE_S(_PAGE_FOE),
266 [VM_SHARED | VM_EXEC] = _PAGE_S(_PAGE_FOW | _PAGE_FOR),
267 [VM_SHARED | VM_EXEC | VM_READ] = _PAGE_S(_PAGE_FOW),
268 [VM_SHARED | VM_EXEC | VM_WRITE] = _PAGE_S(0),
269 [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = _PAGE_S(0)
270 };
271 DECLARE_VM_GET_PAGE_PROT
272