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