aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/mem.c')
-rw-r--r--arch/um/kernel/mem.c147
1 files changed, 76 insertions, 71 deletions
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 59822dee438a..d872fdce1d7e 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,49 +1,41 @@
1/* 1/*
2 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/stddef.h" 6#include <linux/stddef.h>
7#include "linux/kernel.h" 7#include <linux/bootmem.h>
8#include "linux/mm.h" 8#include <linux/gfp.h>
9#include "linux/bootmem.h" 9#include <linux/highmem.h>
10#include "linux/swap.h" 10#include <linux/mm.h>
11#include "linux/highmem.h" 11#include <linux/swap.h>
12#include "linux/gfp.h" 12#include <asm/fixmap.h>
13#include "asm/page.h" 13#include <asm/page.h>
14#include "asm/fixmap.h"
15#include "asm/pgalloc.h"
16#include "kern_util.h"
17#include "as-layout.h" 14#include "as-layout.h"
15#include "init.h"
18#include "kern.h" 16#include "kern.h"
17#include "kern_util.h"
19#include "mem_user.h" 18#include "mem_user.h"
20#include "um_uaccess.h"
21#include "os.h" 19#include "os.h"
22#include "linux/types.h"
23#include "linux/string.h"
24#include "init.h"
25#include "kern_constants.h"
26 20
27/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ 21/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
28unsigned long *empty_zero_page = NULL; 22unsigned long *empty_zero_page = NULL;
29/* allocated in paging_init and unchanged thereafter */ 23/* allocated in paging_init and unchanged thereafter */
30unsigned long *empty_bad_page = NULL; 24unsigned long *empty_bad_page = NULL;
25
26/*
27 * Initialized during boot, and readonly for initializing page tables
28 * afterwards
29 */
31pgd_t swapper_pg_dir[PTRS_PER_PGD]; 30pgd_t swapper_pg_dir[PTRS_PER_PGD];
31
32/* Initialized at boot time, and readonly after that */
32unsigned long long highmem; 33unsigned long long highmem;
33int kmalloc_ok = 0; 34int kmalloc_ok = 0;
34 35
36/* Used during early boot */
35static unsigned long brk_end; 37static unsigned long brk_end;
36 38
37void unmap_physmem(void)
38{
39 os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
40}
41
42static void map_cb(void *unused)
43{
44 map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
45}
46
47#ifdef CONFIG_HIGHMEM 39#ifdef CONFIG_HIGHMEM
48static void setup_highmem(unsigned long highmem_start, 40static void setup_highmem(unsigned long highmem_start,
49 unsigned long highmem_len) 41 unsigned long highmem_len)
@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
53 int i; 45 int i;
54 46
55 highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; 47 highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
56 for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ 48 for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
57 page = &mem_map[highmem_pfn + i]; 49 page = &mem_map[highmem_pfn + i];
58 ClearPageReserved(page); 50 ClearPageReserved(page);
59 init_page_count(page); 51 init_page_count(page);
@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
65void __init mem_init(void) 57void __init mem_init(void)
66{ 58{
67 /* clear the zero-page */ 59 /* clear the zero-page */
68 memset((void *) empty_zero_page, 0, PAGE_SIZE); 60 memset(empty_zero_page, 0, PAGE_SIZE);
69 61
70 /* Map in the area just after the brk now that kmalloc is about 62 /* Map in the area just after the brk now that kmalloc is about
71 * to be turned on. 63 * to be turned on.
72 */ 64 */
73 brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); 65 brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
74 map_cb(NULL); 66 map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
75 initial_thread_cb(map_cb, NULL);
76 free_bootmem(__pa(brk_end), uml_reserved - brk_end); 67 free_bootmem(__pa(brk_end), uml_reserved - brk_end);
77 uml_reserved = brk_end; 68 uml_reserved = brk_end;
78 69
@@ -85,7 +76,7 @@ void __init mem_init(void)
85#endif 76#endif
86 num_physpages = totalram_pages; 77 num_physpages = totalram_pages;
87 max_pfn = totalram_pages; 78 max_pfn = totalram_pages;
88 printk(KERN_INFO "Memory: %luk available\n", 79 printk(KERN_INFO "Memory: %luk available\n",
89 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); 80 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
90 kmalloc_ok = 1; 81 kmalloc_ok = 1;
91 82
@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
119#endif 110#endif
120} 111}
121 112
122static void __init fixrange_init(unsigned long start, unsigned long end, 113static void __init fixrange_init(unsigned long start, unsigned long end,
123 pgd_t *pgd_base) 114 pgd_t *pgd_base)
124{ 115{
125 pgd_t *pgd; 116 pgd_t *pgd;
@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
138 if (pud_none(*pud)) 129 if (pud_none(*pud))
139 one_md_table_init(pud); 130 one_md_table_init(pud);
140 pmd = pmd_offset(pud, vaddr); 131 pmd = pmd_offset(pud, vaddr);
141 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { 132 for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
142 one_page_table_init(pmd); 133 one_page_table_init(pmd);
143 vaddr += PMD_SIZE; 134 vaddr += PMD_SIZE;
144 } 135 }
@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
152 143
153#define kmap_get_fixmap_pte(vaddr) \ 144#define kmap_get_fixmap_pte(vaddr) \
154 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ 145 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
155 (vaddr)), (vaddr)) 146 (vaddr)), (vaddr))
156 147
157static void __init kmap_init(void) 148static void __init kmap_init(void)
158{ 149{
@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
197 pud_t *pud; 188 pud_t *pud;
198 pmd_t *pmd; 189 pmd_t *pmd;
199 pte_t *pte; 190 pte_t *pte;
200 unsigned long paddr, vaddr = FIXADDR_USER_START; 191 phys_t p;
192 unsigned long v, vaddr = FIXADDR_USER_START;
201 193
202 if ( ! size ) 194 if (!size)
203 return; 195 return;
204 196
205 fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir); 197 fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
206 paddr = (unsigned long)alloc_bootmem_low_pages( size); 198 v = (unsigned long) alloc_bootmem_low_pages(size);
207 memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size); 199 memcpy((void *) v , (void *) FIXADDR_USER_START, size);
208 paddr = __pa(paddr); 200 p = __pa(v);
209 for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){ 201 for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
202 p += PAGE_SIZE) {
210 pgd = swapper_pg_dir + pgd_index(vaddr); 203 pgd = swapper_pg_dir + pgd_index(vaddr);
211 pud = pud_offset(pgd, vaddr); 204 pud = pud_offset(pgd, vaddr);
212 pmd = pmd_offset(pud, vaddr); 205 pmd = pmd_offset(pud, vaddr);
213 pte = pte_offset_kernel(pmd, vaddr); 206 pte = pte_offset_kernel(pmd, vaddr);
214 pte_set_val( (*pte), paddr, PAGE_READONLY); 207 pte_set_val(*pte, p, PAGE_READONLY);
215 } 208 }
216#endif 209#endif
217} 210}
@@ -223,7 +216,7 @@ void __init paging_init(void)
223 216
224 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 217 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
225 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 218 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
226 for(i = 0; i < ARRAY_SIZE(zones_size); i++) 219 for (i = 0; i < ARRAY_SIZE(zones_size); i++)
227 zones_size[i] = 0; 220 zones_size[i] = 0;
228 221
229 zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) - 222 zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
253 int i; 246 int i;
254 247
255 again: 248 again:
256 if(page == NULL) 249 if (page == NULL)
257 return page; 250 return page;
258 if(PageHighMem(page)) 251 if (PageHighMem(page))
259 return page; 252 return page;
260 253
261 addr = (unsigned long) page_address(page); 254 addr = (unsigned long) page_address(page);
262 for(i = 0; i < (1 << order); i++){ 255 for (i = 0; i < (1 << order); i++) {
263 current->thread.fault_addr = (void *) addr; 256 current->thread.fault_addr = (void *) addr;
264 if(__do_copy_to_user((void __user *) addr, &zero, 257 if (__do_copy_to_user((void __user *) addr, &zero,
265 sizeof(zero), 258 sizeof(zero),
266 &current->thread.fault_addr, 259 &current->thread.fault_addr,
267 &current->thread.fault_catcher)){ 260 &current->thread.fault_catcher)) {
268 if(!(mask & __GFP_WAIT)) 261 if (!(mask & __GFP_WAIT))
269 return NULL; 262 return NULL;
270 else break; 263 else break;
271 } 264 }
272 addr += PAGE_SIZE; 265 addr += PAGE_SIZE;
273 } 266 }
274 267
275 if(i == (1 << order)) 268 if (i == (1 << order))
276 return page; 269 return page;
277 page = alloc_pages(mask, order); 270 page = alloc_pages(mask, order);
278 goto again; 271 goto again;
279} 272}
280 273
281/* This can't do anything because nothing in the kernel image can be freed 274/*
275 * This can't do anything because nothing in the kernel image can be freed
282 * since it's not in kernel physical memory. 276 * since it's not in kernel physical memory.
283 */ 277 */
284 278
@@ -290,8 +284,8 @@ void free_initmem(void)
290void free_initrd_mem(unsigned long start, unsigned long end) 284void free_initrd_mem(unsigned long start, unsigned long end)
291{ 285{
292 if (start < end) 286 if (start < end)
293 printk ("Freeing initrd memory: %ldk freed\n", 287 printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
294 (end - start) >> 10); 288 (end - start) >> 10);
295 for (; start < end; start += PAGE_SIZE) { 289 for (; start < end; start += PAGE_SIZE) {
296 ClearPageReserved(virt_to_page(start)); 290 ClearPageReserved(virt_to_page(start));
297 init_page_count(virt_to_page(start)); 291 init_page_count(virt_to_page(start));
@@ -308,32 +302,31 @@ void show_mem(void)
308 int highmem = 0; 302 int highmem = 0;
309 struct page *page; 303 struct page *page;
310 304
311 printk("Mem-info:\n"); 305 printk(KERN_INFO "Mem-info:\n");
312 show_free_areas(); 306 show_free_areas();
313 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); 307 printk(KERN_INFO "Free swap: %6ldkB\n",
308 nr_swap_pages<<(PAGE_SHIFT-10));
314 pfn = max_mapnr; 309 pfn = max_mapnr;
315 while(pfn-- > 0) { 310 while (pfn-- > 0) {
316 page = pfn_to_page(pfn); 311 page = pfn_to_page(pfn);
317 total++; 312 total++;
318 if(PageHighMem(page)) 313 if (PageHighMem(page))
319 highmem++; 314 highmem++;
320 if(PageReserved(page)) 315 if (PageReserved(page))
321 reserved++; 316 reserved++;
322 else if(PageSwapCache(page)) 317 else if (PageSwapCache(page))
323 cached++; 318 cached++;
324 else if(page_count(page)) 319 else if (page_count(page))
325 shared += page_count(page) - 1; 320 shared += page_count(page) - 1;
326 } 321 }
327 printk("%d pages of RAM\n", total); 322 printk(KERN_INFO "%d pages of RAM\n", total);
328 printk("%d pages of HIGHMEM\n", highmem); 323 printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
329 printk("%d reserved pages\n", reserved); 324 printk(KERN_INFO "%d reserved pages\n", reserved);
330 printk("%d pages shared\n", shared); 325 printk(KERN_INFO "%d pages shared\n", shared);
331 printk("%d pages swap cached\n", cached); 326 printk(KERN_INFO "%d pages swap cached\n", cached);
332} 327}
333 328
334/* 329/* Allocate and free page tables. */
335 * Allocate and free page tables.
336 */
337 330
338pgd_t *pgd_alloc(struct mm_struct *mm) 331pgd_t *pgd_alloc(struct mm_struct *mm)
339{ 332{
@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
341 334
342 if (pgd) { 335 if (pgd) {
343 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); 336 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
344 memcpy(pgd + USER_PTRS_PER_PGD, 337 memcpy(pgd + USER_PTRS_PER_PGD,
345 swapper_pg_dir + USER_PTRS_PER_PGD, 338 swapper_pg_dir + USER_PTRS_PER_PGD,
346 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 339 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
347 } 340 }
348 return pgd; 341 return pgd;
349} 342}
350 343
351void pgd_free(pgd_t *pgd) 344void pgd_free(struct mm_struct *mm, pgd_t *pgd)
352{ 345{
353 free_page((unsigned long) pgd); 346 free_page((unsigned long) pgd);
354} 347}
@@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
368 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); 361 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
369 return pte; 362 return pte;
370} 363}
364
365#ifdef CONFIG_3_LEVEL_PGTABLES
366pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
367{
368 pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
369
370 if (pmd)
371 memset(pmd, 0, PAGE_SIZE);
372
373 return pmd;
374}
375#endif