include upstream ip1000a driver version 2.09f
[linux-2.4.git] / 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            On systems with larger consoles, additional pages will be
238            allocated as needed during the mapping process.
239
240            In the case of not SRM, but not CONFIG_ALPHA_LARGE_VMALLOC,
241            we need to allocate the PGD we use for vmalloc before we start
242            forking other tasks.  */
243
244         two_pages = (void *)
245           (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
246         kernel_end = two_pages + 2*PAGE_SIZE;
247         memset(two_pages, 0, 2*PAGE_SIZE);
248
249         pgd = pgd_offset_k(VMALLOC_START);
250         pgd_set(pgd, (pmd_t *)two_pages);
251         pmd = pmd_offset(pgd, VMALLOC_START);
252         pmd_set(pmd, (pte_t *)(two_pages + PAGE_SIZE));
253
254         if (alpha_using_srm) {
255                 static struct vm_struct console_remap_vm;
256                 unsigned long vaddr = VMALLOC_START;
257                 long i, j;
258
259                 /* Set up the third level PTEs and update the virtual
260                    addresses of the CRB entries.  */
261                 for (i = 0; i < crb->map_entries; ++i) {
262                         unsigned long paddr = crb->map[i].pa;
263                         crb->map[i].va = vaddr;
264                         for (j = 0; j < crb->map[i].count; ++j) {
265                                 /* Newer console's (especially on larger
266                                    systems) may require more pages of
267                                    PTEs. Grab additional pages as needed. */
268                                 if (pmd != pmd_offset(pgd, vaddr)) {
269                                         memset(kernel_end, 0, PAGE_SIZE);
270                                         pmd = pmd_offset(pgd, vaddr);
271                                         pmd_set(pmd, (pte_t *)kernel_end);
272                                         kernel_end += PAGE_SIZE;
273                                 }
274                                 set_pte(pte_offset(pmd, vaddr),
275                                         mk_pte_phys(paddr, PAGE_KERNEL));
276                                 paddr += PAGE_SIZE;
277                                 vaddr += PAGE_SIZE;
278                         }
279                 }
280
281                 /* Let vmalloc know that we've allocated some space.  */
282                 console_remap_vm.flags = VM_ALLOC;
283                 console_remap_vm.addr = VMALLOC_START;
284                 console_remap_vm.size = vaddr - VMALLOC_START;
285                 vmlist = &console_remap_vm;
286         }
287
288         callback_init_done = 1;
289         return kernel_end;
290 }
291
292
293 #ifndef CONFIG_DISCONTIGMEM
294 /*
295  * paging_init() sets up the memory map.
296  */
297 void
298 paging_init(void)
299 {
300         unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
301         unsigned long dma_pfn, high_pfn;
302
303         dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
304         high_pfn = max_low_pfn;
305
306         if (dma_pfn >= high_pfn)
307                 zones_size[ZONE_DMA] = high_pfn;
308         else {
309                 zones_size[ZONE_DMA] = dma_pfn;
310                 zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
311         }
312
313         /* Initialize mem_map[].  */
314         free_area_init(zones_size);
315
316         /* Initialize the kernel's ZERO_PGE. */
317         memset((void *)ZERO_PGE, 0, PAGE_SIZE);
318 }
319 #endif /* CONFIG_DISCONTIGMEM */
320
321 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
322 void
323 srm_paging_stop (void)
324 {
325         /* Move the vptb back to where the SRM console expects it.  */
326         swapper_pg_dir[1] = swapper_pg_dir[1023];
327         tbia();
328         wrvptptr(0x200000000);
329         hwrpb->vptb = 0x200000000;
330         hwrpb_update_checksum(hwrpb);
331
332         /* Reload the page tables that the console had in use.  */
333         load_PCB(&original_pcb);
334         tbia();
335 }
336 #endif
337
338 #ifndef CONFIG_DISCONTIGMEM
339 static void __init
340 printk_memory_info(void)
341 {
342         unsigned long codesize, reservedpages, datasize, initsize, tmp;
343         extern int page_is_ram(unsigned long) __init;
344         extern char _text, _etext, _data, _edata;
345         extern char __init_begin, __init_end;
346
347         /* printk all informations */
348         reservedpages = 0;
349         for (tmp = 0; tmp < max_low_pfn; tmp++)
350                 /*
351                  * Only count reserved RAM pages
352                  */
353                 if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
354                         reservedpages++;
355
356         codesize =  (unsigned long) &_etext - (unsigned long) &_text;
357         datasize =  (unsigned long) &_edata - (unsigned long) &_data;
358         initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
359
360         printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, %luk data, %luk init)\n",
361                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
362                max_mapnr << (PAGE_SHIFT-10),
363                codesize >> 10,
364                reservedpages << (PAGE_SHIFT-10),
365                datasize >> 10,
366                initsize >> 10);
367 }
368
369 void __init
370 mem_init(void)
371 {
372         max_mapnr = num_physpages = max_low_pfn;
373         totalram_pages += free_all_bootmem();
374         high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
375
376         printk_memory_info();
377 }
378 #endif /* CONFIG_DISCONTIGMEM */
379
380 void
381 free_reserved_mem(void *start, void *end)
382 {
383         void *__start = start;
384         for (; __start < end; __start += PAGE_SIZE) {
385                 ClearPageReserved(virt_to_page(__start));
386                 set_page_count(virt_to_page(__start), 1);
387                 free_page((long)__start);
388                 totalram_pages++;
389         }
390 }
391
392 void
393 free_initmem(void)
394 {
395         extern char __init_begin, __init_end;
396
397         free_reserved_mem(&__init_begin, &__init_end);
398         printk (KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
399                 (&__init_end - &__init_begin) >> 10);
400 }
401
402 #ifdef CONFIG_BLK_DEV_INITRD
403 void
404 free_initrd_mem(unsigned long start, unsigned long end)
405 {
406         free_reserved_mem((void *)start, (void *)end);
407         printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
408                (end - start) >> 10);
409 }
410 #endif
411
412 void
413 si_meminfo(struct sysinfo *val)
414 {
415         val->totalram = totalram_pages;
416         val->sharedram = 0;
417         val->freeram = nr_free_pages();
418         val->bufferram = atomic_read(&buffermem_pages);
419         val->totalhigh = 0;
420         val->freehigh = 0;
421         val->mem_unit = PAGE_SIZE;
422 }