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