File: /usr/src/linux/arch/alpha/mm/init.c
1 /*
2 * linux/arch/alpha/mm/init.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7 /* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
8
9 #include <linux/config.h>
10 #include <linux/signal.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/types.h>
16 #include <linux/ptrace.h>
17 #include <linux/mman.h>
18 #include <linux/mm.h>
19 #include <linux/swap.h>
20 #include <linux/init.h>
21 #include <linux/bootmem.h> /* max_low_pfn */
22 #include <linux/vmalloc.h>
23 #ifdef CONFIG_BLK_DEV_INITRD
24 #include <linux/blk.h>
25 #endif
26
27 #include <asm/system.h>
28 #include <asm/uaccess.h>
29 #include <asm/pgtable.h>
30 #include <asm/pgalloc.h>
31 #include <asm/hwrpb.h>
32 #include <asm/dma.h>
33 #include <asm/mmu_context.h>
34 #include <asm/console.h>
35 #include <asm/tlb.h>
36
37 mmu_gather_t mmu_gathers[NR_CPUS];
38
39 unsigned long totalram_pages;
40
41 extern void die_if_kernel(char *,struct pt_regs *,long);
42
43 struct thread_struct original_pcb;
44
45 #ifndef CONFIG_SMP
46 struct pgtable_cache_struct quicklists;
47 #endif
48
49 pgd_t *
50 get_pgd_slow(void)
51 {
52 pgd_t *ret, *init;
53
54 ret = (pgd_t *)__get_free_page(GFP_KERNEL);
55 init = pgd_offset(&init_mm, 0UL);
56 if (ret) {
57 clear_page(ret);
58 #ifdef CONFIG_ALPHA_LARGE_VMALLOC
59 memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
60 (PTRS_PER_PGD - USER_PTRS_PER_PGD - 1)*sizeof(pgd_t));
61 #else
62 pgd_val(ret[PTRS_PER_PGD-2]) = pgd_val(init[PTRS_PER_PGD-2]);
63 #endif
64
65 /* The last PGD entry is the VPTB self-map. */
66 pgd_val(ret[PTRS_PER_PGD-1])
67 = pte_val(mk_pte(virt_to_page(ret), PAGE_KERNEL));
68 }
69 return ret;
70 }
71
72 int do_check_pgt_cache(int low, int high)
73 {
74 int freed = 0;
75 if(pgtable_cache_size > high) {
76 do {
77 if(pgd_quicklist) {
78 free_pgd_slow(get_pgd_fast());
79 freed++;
80 }
81 if(pmd_quicklist) {
82 pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
83 freed++;
84 }
85 if(pte_quicklist) {
86 pte_free_slow(pte_alloc_one_fast(NULL, 0));
87 freed++;
88 }
89 } while(pgtable_cache_size > low);
90 }
91 return freed;
92 }
93
94 /*
95 * BAD_PAGE is the page that is used for page faults when linux
96 * is out-of-memory. Older versions of linux just did a
97 * do_exit(), but using this instead means there is less risk
98 * for a process dying in kernel mode, possibly leaving an inode
99 * unused etc..
100 *
101 * BAD_PAGETABLE is the accompanying page-table: it is initialized
102 * to point to BAD_PAGE entries.
103 *
104 * ZERO_PAGE is a special page that is used for zero-initialized
105 * data and COW.
106 */
107 pmd_t *
108 __bad_pagetable(void)
109 {
110 memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
111 return (pmd_t *) EMPTY_PGT;
112 }
113
114 pte_t
115 __bad_page(void)
116 {
117 memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
118 return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED));
119 }
120
121 #ifndef CONFIG_DISCONTIGMEM
122 void
123 show_mem(void)
124 {
125 long i,free = 0,total = 0,reserved = 0;
126 long shared = 0, cached = 0;
127
128 printk("\nMem-info:\n");
129 show_free_areas();
130 printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
131 i = max_mapnr;
132 while (i-- > 0) {
133 total++;
134 if (PageReserved(mem_map+i))
135 reserved++;
136 else if (PageSwapCache(mem_map+i))
137 cached++;
138 else if (!page_count(mem_map+i))
139 free++;
140 else
141 shared += atomic_read(&mem_map[i].count) - 1;
142 }
143 printk("%ld pages of RAM\n",total);
144 printk("%ld free pages\n",free);
145 printk("%ld reserved pages\n",reserved);
146 printk("%ld pages shared\n",shared);
147 printk("%ld pages swap cached\n",cached);
148 printk("%ld pages in page table cache\n",pgtable_cache_size);
149 show_buffers();
150 }
151 #endif
152
153 static inline unsigned long
154 load_PCB(struct thread_struct * pcb)
155 {
156 register unsigned long sp __asm__("$30");
157 pcb->ksp = sp;
158 return __reload_thread(pcb);
159 }
160
161 /* Set up initial PCB, VPTB, and other such nicities. */
162
163 static inline void
164 switch_to_system_map(void)
165 {
166 unsigned long newptbr;
167 unsigned long original_pcb_ptr;
168
169 /* Initialize the kernel's page tables. Linux puts the vptb in
170 the last slot of the L1 page table. */
171 memset(swapper_pg_dir, 0, PAGE_SIZE);
172 newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
173 pgd_val(swapper_pg_dir[1023]) =
174 (newptbr << 32) | pgprot_val(PAGE_KERNEL);
175
176 /* Set the vptb. This is often done by the bootloader, but
177 shouldn't be required. */
178 if (hwrpb->vptb != 0xfffffffe00000000) {
179 wrvptptr(0xfffffffe00000000);
180 hwrpb->vptb = 0xfffffffe00000000;
181 hwrpb_update_checksum(hwrpb);
182 }
183
184 /* Also set up the real kernel PCB while we're at it. */
185 init_task.thread.ptbr = newptbr;
186 init_task.thread.pal_flags = 1; /* set FEN, clear everything else */
187 init_task.thread.flags = 0;
188 original_pcb_ptr = load_PCB(&init_task.thread);
189 tbia();
190
191 /* Save off the contents of the original PCB so that we can
192 restore the original console's page tables for a clean reboot.
193
194 Note that the PCB is supposed to be a physical address, but
195 since KSEG values also happen to work, folks get confused.
196 Check this here. */
197
198 if (original_pcb_ptr < PAGE_OFFSET) {
199 original_pcb_ptr = (unsigned long)
200 phys_to_virt(original_pcb_ptr);
201 }
202 original_pcb = *(struct thread_struct *) original_pcb_ptr;
203 }
204
205 int callback_init_done;
206
207 void * __init
208 callback_init(void * kernel_end)
209 {
210 struct crb_struct * crb;
211 pgd_t *pgd;
212 pmd_t *pmd;
213 void *two_pages;
214
215 /* Starting at the HWRPB, locate the CRB. */
216 crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
217
218 if (alpha_using_srm) {
219 /* Tell the console whither it is to be remapped. */
220 if (srm_fixup(VMALLOC_START, (unsigned long)hwrpb))
221 __halt(); /* "We're boned." --Bender */
222
223 /* Edit the procedure descriptors for DISPATCH and FIXUP. */
224 crb->dispatch_va = (struct procdesc_struct *)
225 (VMALLOC_START + (unsigned long)crb->dispatch_va
226 - crb->map[0].va);
227 crb->fixup_va = (struct procdesc_struct *)
228 (VMALLOC_START + (unsigned long)crb->fixup_va
229 - crb->map[0].va);
230 }
231
232 switch_to_system_map();
233
234 /* Allocate one PGD and one PMD. In the case of SRM, we'll need
235 these to actually remap the console. There is an assumption
236 here that only one of each is needed, and this allows for 8MB.
237 Currently (late 1999), big consoles are still under 4MB.
238
239 In the case of not SRM, but not CONFIG_ALPHA_LARGE_VMALLOC,
240 we need to allocate the PGD we use for vmalloc before we start
241 forking other tasks. */
242
243 two_pages = (void *)
244 (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
245 kernel_end = two_pages + 2*PAGE_SIZE;
246 memset(two_pages, 0, 2*PAGE_SIZE);
247
248 pgd = pgd_offset_k(VMALLOC_START);
249 pgd_set(pgd, (pmd_t *)two_pages);
250 pmd = pmd_offset(pgd, VMALLOC_START);
251 pmd_set(pmd, (pte_t *)(two_pages + PAGE_SIZE));
252
253 if (alpha_using_srm) {
254 static struct vm_struct console_remap_vm;
255 unsigned long vaddr = VMALLOC_START;
256 long i, j;
257
258 /* Set up the third level PTEs and update the virtual
259 addresses of the CRB entries. */
260 for (i = 0; i < crb->map_entries; ++i) {
261 unsigned long paddr = crb->map[i].pa;
262 crb->map[i].va = vaddr;
263 for (j = 0; j < crb->map[i].count; ++j) {
264 set_pte(pte_offset(pmd, vaddr),
265 mk_pte_phys(paddr, PAGE_KERNEL));
266 paddr += PAGE_SIZE;
267 vaddr += PAGE_SIZE;
268 }
269 }
270
271 /* Let vmalloc know that we've allocated some space. */
272 console_remap_vm.flags = VM_ALLOC;
273 console_remap_vm.addr = VMALLOC_START;
274 console_remap_vm.size = vaddr - VMALLOC_START;
275 vmlist = &console_remap_vm;
276 }
277
278 callback_init_done = 1;
279 return kernel_end;
280 }
281
282
283 #ifndef CONFIG_DISCONTIGMEM
284 /*
285 * paging_init() sets up the memory map.
286 */
287 void
288 paging_init(void)
289 {
290 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
291 unsigned long dma_pfn, high_pfn;
292
293 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
294 high_pfn = max_low_pfn;
295
296 if (dma_pfn >= high_pfn)
297 zones_size[ZONE_DMA] = high_pfn;
298 else {
299 zones_size[ZONE_DMA] = dma_pfn;
300 zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
301 }
302
303 /* Initialize mem_map[]. */
304 free_area_init(zones_size);
305
306 /* Initialize the kernel's ZERO_PGE. */
307 memset((void *)ZERO_PGE, 0, PAGE_SIZE);
308 }
309 #endif /* CONFIG_DISCONTIGMEM */
310
311 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
312 void
313 srm_paging_stop (void)
314 {
315 /* Move the vptb back to where the SRM console expects it. */
316 swapper_pg_dir[1] = swapper_pg_dir[1023];
317 tbia();
318 wrvptptr(0x200000000);
319 hwrpb->vptb = 0x200000000;
320 hwrpb_update_checksum(hwrpb);
321
322 /* Reload the page tables that the console had in use. */
323 load_PCB(&original_pcb);
324 tbia();
325 }
326 #endif
327
328 #ifndef CONFIG_DISCONTIGMEM
329 static void __init
330 printk_memory_info(void)
331 {
332 unsigned long codesize, reservedpages, datasize, initsize, tmp;
333 extern int page_is_ram(unsigned long) __init;
334 extern char _text, _etext, _data, _edata;
335 extern char __init_begin, __init_end;
336
337 /* printk all informations */
338 reservedpages = 0;
339 for (tmp = 0; tmp < max_low_pfn; tmp++)
340 /*
341 * Only count reserved RAM pages
342 */
343 if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
344 reservedpages++;
345
346 codesize = (unsigned long) &_etext - (unsigned long) &_text;
347 datasize = (unsigned long) &_edata - (unsigned long) &_data;
348 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
349
350 printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, %luk data, %luk init)\n",
351 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
352 max_mapnr << (PAGE_SHIFT-10),
353 codesize >> 10,
354 reservedpages << (PAGE_SHIFT-10),
355 datasize >> 10,
356 initsize >> 10);
357 }
358
359 void __init
360 mem_init(void)
361 {
362 max_mapnr = num_physpages = max_low_pfn;
363 totalram_pages += free_all_bootmem();
364 high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
365
366 printk_memory_info();
367 }
368 #endif /* CONFIG_DISCONTIGMEM */
369
370 void
371 free_initmem (void)
372 {
373 extern char __init_begin, __init_end;
374 unsigned long addr;
375
376 addr = (unsigned long)(&__init_begin);
377 for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
378 ClearPageReserved(virt_to_page(addr));
379 set_page_count(virt_to_page(addr), 1);
380 free_page(addr);
381 totalram_pages++;
382 }
383 printk ("Freeing unused kernel memory: %ldk freed\n",
384 (&__init_end - &__init_begin) >> 10);
385 }
386
387 #ifdef CONFIG_BLK_DEV_INITRD
388 void
389 free_initrd_mem(unsigned long start, unsigned long end)
390 {
391 unsigned long __start = start;
392 for (; start < end; start += PAGE_SIZE) {
393 ClearPageReserved(virt_to_page(start));
394 set_page_count(virt_to_page(start), 1);
395 free_page(start);
396 totalram_pages++;
397 }
398 printk ("Freeing initrd memory: %ldk freed\n", (end - __start) >> 10);
399 }
400 #endif
401
402 void
403 si_meminfo(struct sysinfo *val)
404 {
405 val->totalram = totalram_pages;
406 val->sharedram = 0;
407 val->freeram = nr_free_pages();
408 val->bufferram = atomic_read(&buffermem_pages);
409 val->totalhigh = 0;
410 val->freehigh = 0;
411 val->mem_unit = PAGE_SIZE;
412 }
413