Merge master.kernel.org:/home/rmk/linux-2.6-serial
[pandora-kernel.git] / arch / um / kernel / mem.c
1 /*
2  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/stddef.h"
7 #include "linux/kernel.h"
8 #include "linux/mm.h"
9 #include "linux/bootmem.h"
10 #include "linux/swap.h"
11 #include "linux/highmem.h"
12 #include "linux/gfp.h"
13 #include "asm/page.h"
14 #include "asm/fixmap.h"
15 #include "asm/pgalloc.h"
16 #include "user_util.h"
17 #include "kern_util.h"
18 #include "kern.h"
19 #include "mem_user.h"
20 #include "uml_uaccess.h"
21 #include "os.h"
22 #include "linux/types.h"
23 #include "linux/string.h"
24 #include "init.h"
25 #include "kern_constants.h"
26
27 /* Changed during early boot */
28 unsigned long *empty_zero_page = NULL;
29 unsigned long *empty_bad_page = NULL;
30 pgd_t swapper_pg_dir[PTRS_PER_PGD];
31 unsigned long long highmem;
32 int kmalloc_ok = 0;
33
34 static unsigned long brk_end;
35
36 void unmap_physmem(void)
37 {
38         os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
39 }
40
41 static void map_cb(void *unused)
42 {
43         map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
44 }
45
46 #ifdef CONFIG_HIGHMEM
47 static void setup_highmem(unsigned long highmem_start,
48                           unsigned long highmem_len)
49 {
50         struct page *page;
51         unsigned long highmem_pfn;
52         int i;
53
54         highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
55         for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
56                 page = &mem_map[highmem_pfn + i];
57                 ClearPageReserved(page);
58                 init_page_count(page);
59                 __free_page(page);
60         }
61 }
62 #endif
63
64 void mem_init(void)
65 {
66         max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
67
68         /* clear the zero-page */
69         memset((void *) empty_zero_page, 0, PAGE_SIZE);
70
71         /* Map in the area just after the brk now that kmalloc is about
72          * to be turned on.
73          */
74         brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
75         map_cb(NULL);
76         initial_thread_cb(map_cb, NULL);
77         free_bootmem(__pa(brk_end), uml_reserved - brk_end);
78         uml_reserved = brk_end;
79
80         /* this will put all low memory onto the freelists */
81         totalram_pages = free_all_bootmem();
82         totalhigh_pages = highmem >> PAGE_SHIFT;
83         totalram_pages += totalhigh_pages;
84         num_physpages = totalram_pages;
85         max_pfn = totalram_pages;
86         printk(KERN_INFO "Memory: %luk available\n", 
87                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
88         kmalloc_ok = 1;
89
90 #ifdef CONFIG_HIGHMEM
91         setup_highmem(end_iomem, highmem);
92 #endif
93 }
94
95 /*
96  * Create a page table and place a pointer to it in a middle page
97  * directory entry.
98  */
99 static void __init one_page_table_init(pmd_t *pmd)
100 {
101         if (pmd_none(*pmd)) {
102                 pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
103                 set_pmd(pmd, __pmd(_KERNPG_TABLE +
104                                            (unsigned long) __pa(pte)));
105                 if (pte != pte_offset_kernel(pmd, 0))
106                         BUG();
107         }
108 }
109
110 static void __init one_md_table_init(pud_t *pud)
111 {
112 #ifdef CONFIG_3_LEVEL_PGTABLES
113         pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
114         set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
115         if (pmd_table != pmd_offset(pud, 0))
116                 BUG();
117 #endif
118 }
119
120 static void __init fixrange_init(unsigned long start, unsigned long end, 
121                                  pgd_t *pgd_base)
122 {
123         pgd_t *pgd;
124         pud_t *pud;
125         pmd_t *pmd;
126         int i, j;
127         unsigned long vaddr;
128
129         vaddr = start;
130         i = pgd_index(vaddr);
131         j = pmd_index(vaddr);
132         pgd = pgd_base + i;
133
134         for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
135                 pud = pud_offset(pgd, vaddr);
136                 if (pud_none(*pud))
137                         one_md_table_init(pud);
138                 pmd = pmd_offset(pud, vaddr);
139                 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
140                         one_page_table_init(pmd);
141                         vaddr += PMD_SIZE;
142                 }
143                 j = 0;
144         }
145 }
146
147 #ifdef CONFIG_HIGHMEM
148 pte_t *kmap_pte;
149 pgprot_t kmap_prot;
150
151 #define kmap_get_fixmap_pte(vaddr)                                      \
152         pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
153                           (vaddr)), (vaddr))
154
155 static void __init kmap_init(void)
156 {
157         unsigned long kmap_vstart;
158
159         /* cache the first kmap pte */
160         kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
161         kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
162
163         kmap_prot = PAGE_KERNEL;
164 }
165
166 static void init_highmem(void)
167 {
168         pgd_t *pgd;
169         pud_t *pud;
170         pmd_t *pmd;
171         pte_t *pte;
172         unsigned long vaddr;
173
174         /*
175          * Permanent kmaps:
176          */
177         vaddr = PKMAP_BASE;
178         fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
179
180         pgd = swapper_pg_dir + pgd_index(vaddr);
181         pud = pud_offset(pgd, vaddr);
182         pmd = pmd_offset(pud, vaddr);
183         pte = pte_offset_kernel(pmd, vaddr);
184         pkmap_page_table = pte;
185
186         kmap_init();
187 }
188 #endif /* CONFIG_HIGHMEM */
189
190 static void __init fixaddr_user_init( void)
191 {
192 #ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
193         long size = FIXADDR_USER_END - FIXADDR_USER_START;
194         pgd_t *pgd;
195         pud_t *pud;
196         pmd_t *pmd;
197         pte_t *pte;
198         unsigned long paddr, vaddr = FIXADDR_USER_START;
199
200         if (  ! size )
201                 return;
202
203         fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
204         paddr = (unsigned long)alloc_bootmem_low_pages( size);
205         memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
206         paddr = __pa(paddr);
207         for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
208                 pgd = swapper_pg_dir + pgd_index(vaddr);
209                 pud = pud_offset(pgd, vaddr);
210                 pmd = pmd_offset(pud, vaddr);
211                 pte = pte_offset_kernel(pmd, vaddr);
212                 pte_set_val( (*pte), paddr, PAGE_READONLY);
213         }
214 #endif
215 }
216
217 void paging_init(void)
218 {
219         unsigned long zones_size[MAX_NR_ZONES], vaddr;
220         int i;
221
222         empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
223         empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
224         for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 
225                 zones_size[i] = 0;
226         zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
227         zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
228         free_area_init(zones_size);
229
230         /*
231          * Fixed mappings, only the page table structure has to be
232          * created - mappings will be set by set_fixmap():
233          */
234         vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
235         fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
236
237         fixaddr_user_init();
238
239 #ifdef CONFIG_HIGHMEM
240         init_highmem();
241 #endif
242 }
243
244 struct page *arch_validate(struct page *page, gfp_t mask, int order)
245 {
246         unsigned long addr, zero = 0;
247         int i;
248
249  again:
250         if(page == NULL) return(page);
251         if(PageHighMem(page)) return(page);
252
253         addr = (unsigned long) page_address(page);
254         for(i = 0; i < (1 << order); i++){
255                 current->thread.fault_addr = (void *) addr;
256                 if(__do_copy_to_user((void __user *) addr, &zero,
257                                      sizeof(zero),
258                                      &current->thread.fault_addr,
259                                      &current->thread.fault_catcher)){
260                         if(!(mask & __GFP_WAIT)) return(NULL);
261                         else break;
262                 }
263                 addr += PAGE_SIZE;
264         }
265
266         if(i == (1 << order)) return(page);
267         page = alloc_pages(mask, order);
268         goto again;
269 }
270
271 /* This can't do anything because nothing in the kernel image can be freed
272  * since it's not in kernel physical memory.
273  */
274
275 void free_initmem(void)
276 {
277 }
278
279 #ifdef CONFIG_BLK_DEV_INITRD
280
281 void free_initrd_mem(unsigned long start, unsigned long end)
282 {
283         if (start < end)
284                 printk ("Freeing initrd memory: %ldk freed\n", 
285                         (end - start) >> 10);
286         for (; start < end; start += PAGE_SIZE) {
287                 ClearPageReserved(virt_to_page(start));
288                 init_page_count(virt_to_page(start));
289                 free_page(start);
290                 totalram_pages++;
291         }
292 }
293         
294 #endif
295
296 void show_mem(void)
297 {
298         int pfn, total = 0, reserved = 0;
299         int shared = 0, cached = 0;
300         int highmem = 0;
301         struct page *page;
302
303         printk("Mem-info:\n");
304         show_free_areas();
305         printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
306         pfn = max_mapnr;
307         while(pfn-- > 0) {
308                 page = pfn_to_page(pfn);
309                 total++;
310                 if(PageHighMem(page))
311                         highmem++;
312                 if(PageReserved(page))
313                         reserved++;
314                 else if(PageSwapCache(page))
315                         cached++;
316                 else if(page_count(page))
317                         shared += page_count(page) - 1;
318         }
319         printk("%d pages of RAM\n", total);
320         printk("%d pages of HIGHMEM\n", highmem);
321         printk("%d reserved pages\n", reserved);
322         printk("%d pages shared\n", shared);
323         printk("%d pages swap cached\n", cached);
324 }
325
326 /*
327  * Allocate and free page tables.
328  */
329
330 pgd_t *pgd_alloc(struct mm_struct *mm)
331 {
332         pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
333
334         if (pgd) {
335                 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
336                 memcpy(pgd + USER_PTRS_PER_PGD, 
337                        swapper_pg_dir + USER_PTRS_PER_PGD, 
338                        (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
339         }
340         return pgd;
341 }
342
343 void pgd_free(pgd_t *pgd)
344 {
345         free_page((unsigned long) pgd);
346 }
347
348 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
349 {
350         pte_t *pte;
351
352         pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
353         return pte;
354 }
355
356 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
357 {
358         struct page *pte;
359    
360         pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
361         return pte;
362 }
363
364 struct iomem_region *iomem_regions = NULL;
365 int iomem_size = 0;
366
367 extern int parse_iomem(char *str, int *add) __init;
368
369 __uml_setup("iomem=", parse_iomem,
370 "iomem=<name>,<file>\n"
371 "    Configure <file> as an IO memory region named <name>.\n\n"
372 );
373
374 /*
375  * Overrides for Emacs so that we follow Linus's tabbing style.
376  * Emacs will notice this stuff at the end of the file and automatically
377  * adjust the settings for this buffer only.  This must remain at the end
378  * of the file.
379  * ---------------------------------------------------------------------------
380  * Local variables:
381  * c-file-style: "linux"
382  * End:
383  */