2 * linux/arch/sh/mm/init.c
4 * Copyright (C) 1999 Niibe Yutaka
6 * Based on linux/arch/i386/mm/init.c:
7 * Copyright (C) 1995 Linus Torvalds
10 #include <linux/config.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>
20 #include <linux/swap.h>
21 #include <linux/smp.h>
22 #include <linux/init.h>
23 #ifdef CONFIG_BLK_DEV_INITRD
24 #include <linux/blk.h>
27 #include <asm/processor.h>
28 #include <asm/system.h>
29 #include <asm/uaccess.h>
30 #include <asm/pgtable.h>
31 #include <asm/mmu_context.h>
34 * Cache of MMU context last used.
36 unsigned long mmu_context_cache
;
38 static unsigned long totalram
= 0;
40 extern void show_net_buffers(void);
41 extern unsigned long init_smp_mappings(unsigned long);
43 void __bad_pte_kernel(pmd_t
*pmd
)
45 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd
));
46 pmd_val(*pmd
) = _KERNPG_TABLE
+ __pa(BAD_PAGETABLE
);
49 void __bad_pte(pmd_t
*pmd
)
51 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd
));
52 pmd_val(*pmd
) = _PAGE_TABLE
+ __pa(BAD_PAGETABLE
);
55 pte_t
*get_pte_kernel_slow(pmd_t
*pmd
, unsigned long offset
)
59 pte
= (pte_t
*) __get_free_page(GFP_KERNEL
);
62 clear_page((unsigned long)pte
);
63 pmd_val(*pmd
) = _KERNPG_TABLE
+ __pa(pte
);
66 pmd_val(*pmd
) = _KERNPG_TABLE
+ __pa(BAD_PAGETABLE
);
69 free_page((unsigned long)pte
);
71 __bad_pte_kernel(pmd
);
74 return (pte_t
*) pmd_page(*pmd
) + offset
;
77 pte_t
*get_pte_slow(pmd_t
*pmd
, unsigned long offset
)
81 pte
= (unsigned long) __get_free_page(GFP_KERNEL
);
85 pmd_val(*pmd
) = _PAGE_TABLE
+ __pa(pte
);
86 return (pte_t
*)(pte
+ offset
);
88 pmd_val(*pmd
) = _PAGE_TABLE
+ __pa(BAD_PAGETABLE
);
96 return (pte_t
*) (pmd_page(*pmd
) + offset
);
99 int do_check_pgt_cache(int low
, int high
)
102 if(pgtable_cache_size
> high
) {
105 free_pgd_slow(get_pgd_fast()), freed
++;
107 free_pmd_slow(get_pmd_fast()), freed
++;
109 free_pte_slow(get_pte_fast()), freed
++;
110 } while(pgtable_cache_size
> low
);
116 * BAD_PAGE is the page that is used for page faults when linux
117 * is out-of-memory. Older versions of linux just did a
118 * do_exit(), but using this instead means there is less risk
119 * for a process dying in kernel mode, possibly leaving an inode
122 * BAD_PAGETABLE is the accompanying page-table: it is initialized
123 * to point to BAD_PAGE entries.
125 * ZERO_PAGE is a special page that is used for zero-initialized
128 pte_t
* __bad_pagetable(void)
130 extern char empty_bad_page_table
[PAGE_SIZE
];
131 unsigned long page
= (unsigned long)empty_bad_page_table
;
134 return (pte_t
*)empty_bad_page_table
;
137 pte_t
__bad_page(void)
139 extern char empty_bad_page
[PAGE_SIZE
];
140 unsigned long page
= (unsigned long)empty_bad_page
;
143 return pte_mkdirty(mk_pte(page
, PAGE_SHARED
));
148 int i
,free
= 0,total
= 0,reserved
= 0;
149 int shared
= 0, cached
= 0;
151 printk("Mem-info:\n");
153 printk("Free swap: %6dkB\n",nr_swap_pages
<<(PAGE_SHIFT
-10));
157 if (PageReserved(mem_map
+i
))
159 else if (PageSwapCache(mem_map
+i
))
161 else if (!page_count(mem_map
+i
))
164 shared
+= page_count(mem_map
+i
) - 1;
166 printk("%d pages of RAM\n",total
);
167 printk("%d reserved pages\n",reserved
);
168 printk("%d pages shared\n",shared
);
169 printk("%d pages swap cached\n",cached
);
170 printk("%ld pages in page table cache\n",pgtable_cache_size
);
176 extern unsigned long free_area_init(unsigned long, unsigned long);
178 /* References to section boundaries */
180 extern char _text
, _etext
, _edata
, __bss_start
, _end
;
181 extern char __init_begin
, __init_end
;
183 pgd_t swapper_pg_dir
[1024];
186 * paging_init() sets up the page tables
188 * This routines also unmaps the page at virtual kernel address 0, so
189 * that we can trap those pesky NULL-reference errors in the kernel.
192 paging_init(unsigned long start_mem
, unsigned long end_mem
)
196 start_mem
= PAGE_ALIGN(start_mem
);
198 /* We don't need kernel mapping as hardware support that. */
199 pg_dir
= swapper_pg_dir
;
201 /* Unmap the original low memory mappings to detect NULL reference */
202 pgd_val(pg_dir
[0]) = 0;
205 __asm__
__volatile__ ("mov.l %0,%1"
207 : "r" (MMU_CONTROL_INIT
), "m" (__m(MMUCR
)));
209 return free_area_init(start_mem
, end_mem
);
212 unsigned long empty_bad_page
[1024];
213 unsigned long empty_bad_page_table
[1024];
214 unsigned long empty_zero_page
[1024];
216 void __init
mem_init(unsigned long start_mem
, unsigned long end_mem
)
219 int reservedpages
= 0;
224 end_mem
&= PAGE_MASK
;
225 high_memory
= (void *) end_mem
;
226 max_mapnr
= num_physpages
= MAP_NR(end_mem
);
228 /* clear the zero-page */
229 memset(empty_zero_page
, 0, PAGE_SIZE
);
231 /* Mark (clear "reserved" bit) usable pages in the mem_map[] */
232 /* Note that all are marked reserved already. */
233 tmp
= start_mem
= PAGE_ALIGN(start_mem
);
234 while (tmp
< end_mem
) {
235 clear_bit(PG_reserved
, &mem_map
[MAP_NR(tmp
)].flags
);
236 clear_bit(PG_DMA
, &mem_map
[MAP_NR(tmp
)].flags
);
240 for (tmp
= PAGE_OFFSET
; tmp
< end_mem
; tmp
+= PAGE_SIZE
) {
241 if (PageReserved(mem_map
+MAP_NR(tmp
))) {
242 if (tmp
>= (unsigned long) &_text
&& tmp
< (unsigned long) &_edata
) {
243 if (tmp
< (unsigned long) &_etext
)
247 } else if (tmp
>= (unsigned long) &__init_begin
248 && tmp
< (unsigned long) &__init_end
)
250 else if (tmp
>= (unsigned long) &__bss_start
251 && tmp
< (unsigned long) start_mem
)
257 set_page_count(mem_map
+MAP_NR(tmp
), 1);
258 totalram
+= PAGE_SIZE
;
259 #ifdef CONFIG_BLK_DEV_INITRD
260 if (!initrd_start
|| (tmp
< initrd_start
|| tmp
>= initrd_end
))
264 printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
265 (unsigned long) nr_free_pages
<< (PAGE_SHIFT
-10),
266 max_mapnr
<< (PAGE_SHIFT
-10),
267 codepages
<< (PAGE_SHIFT
-10),
268 reservedpages
<< (PAGE_SHIFT
-10),
269 datapages
<< (PAGE_SHIFT
-10),
270 initpages
<< (PAGE_SHIFT
-10));
273 void free_initmem(void)
277 addr
= (unsigned long)(&__init_begin
);
278 for (; addr
< (unsigned long)(&__init_end
); addr
+= PAGE_SIZE
) {
279 mem_map
[MAP_NR(addr
)].flags
&= ~(1 << PG_reserved
);
280 set_page_count(mem_map
+MAP_NR(addr
), 1);
282 totalram
+= PAGE_SIZE
;
284 printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end
- &__init_begin
) >> 10);
287 void si_meminfo(struct sysinfo
*val
)
289 val
->totalram
= totalram
;
291 val
->freeram
= nr_free_pages
<< PAGE_SHIFT
;
292 val
->bufferram
= atomic_read(&buffermem
);