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