xref: /linux/arch/alpha/mm/init.c (revision 59e6295fac26b8e85c1ea859cdd89fa1e47519d7)
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 *
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
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
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
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 
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  */
224 void __init paging_init(void)
225 {
226 	memset(absolute_pointer(ZERO_PGE), 0, PAGE_SIZE);
227 }
228 
229 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
230 void
231 srm_paging_stop (void)
232 {
233 	/* Move the vptb back to where the SRM console expects it.  */
234 	swapper_pg_dir[1] = swapper_pg_dir[1023];
235 	tbia();
236 	wrvptptr(0x200000000UL);
237 	hwrpb->vptb = 0x200000000UL;
238 	hwrpb_update_checksum(hwrpb);
239 
240 	/* Reload the page tables that the console had in use.  */
241 	load_PCB(&original_pcb);
242 	tbia();
243 }
244 #endif
245 
246 static const pgprot_t protection_map[16] = {
247 	[VM_NONE]					= _PAGE_P(_PAGE_FOE | _PAGE_FOW |
248 								  _PAGE_FOR),
249 	[VM_READ]					= _PAGE_P(_PAGE_FOE | _PAGE_FOW),
250 	[VM_WRITE]					= _PAGE_P(_PAGE_FOE),
251 	[VM_WRITE | VM_READ]				= _PAGE_P(_PAGE_FOE),
252 	[VM_EXEC]					= _PAGE_P(_PAGE_FOW | _PAGE_FOR),
253 	[VM_EXEC | VM_READ]				= _PAGE_P(_PAGE_FOW),
254 	[VM_EXEC | VM_WRITE]				= _PAGE_P(0),
255 	[VM_EXEC | VM_WRITE | VM_READ]			= _PAGE_P(0),
256 	[VM_SHARED]					= _PAGE_S(_PAGE_FOE | _PAGE_FOW |
257 								  _PAGE_FOR),
258 	[VM_SHARED | VM_READ]				= _PAGE_S(_PAGE_FOE | _PAGE_FOW),
259 	[VM_SHARED | VM_WRITE]				= _PAGE_S(_PAGE_FOE),
260 	[VM_SHARED | VM_WRITE | VM_READ]		= _PAGE_S(_PAGE_FOE),
261 	[VM_SHARED | VM_EXEC]				= _PAGE_S(_PAGE_FOW | _PAGE_FOR),
262 	[VM_SHARED | VM_EXEC | VM_READ]			= _PAGE_S(_PAGE_FOW),
263 	[VM_SHARED | VM_EXEC | VM_WRITE]		= _PAGE_S(0),
264 	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= _PAGE_S(0)
265 };
266 DECLARE_VM_GET_PAGE_PROT
267