diff options
Diffstat (limited to 'arch/sh/mm/init.c')
-rw-r--r-- | arch/sh/mm/init.c | 197 |
1 files changed, 92 insertions, 105 deletions
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index ae957a932375..4d030988b368 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c | |||
@@ -1,37 +1,20 @@ | |||
1 | /* $Id: init.c,v 1.19 2004/02/21 04:42:16 kkojima Exp $ | 1 | /* |
2 | * | 2 | * linux/arch/sh/mm/init.c |
3 | * linux/arch/sh/mm/init.c | ||
4 | * | 3 | * |
5 | * Copyright (C) 1999 Niibe Yutaka | 4 | * Copyright (C) 1999 Niibe Yutaka |
6 | * Copyright (C) 2002, 2004 Paul Mundt | 5 | * Copyright (C) 2002 - 2007 Paul Mundt |
7 | * | 6 | * |
8 | * Based on linux/arch/i386/mm/init.c: | 7 | * Based on linux/arch/i386/mm/init.c: |
9 | * Copyright (C) 1995 Linus Torvalds | 8 | * Copyright (C) 1995 Linus Torvalds |
10 | */ | 9 | */ |
11 | |||
12 | #include <linux/signal.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | #include <linux/mman.h> | ||
20 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
21 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
22 | #include <linux/smp.h> | ||
23 | #include <linux/init.h> | 12 | #include <linux/init.h> |
24 | #include <linux/highmem.h> | ||
25 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
26 | #include <linux/pagemap.h> | ||
27 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
28 | #include <asm/processor.h> | 15 | #include <linux/percpu.h> |
29 | #include <asm/system.h> | 16 | #include <linux/io.h> |
30 | #include <asm/uaccess.h> | ||
31 | #include <asm/pgtable.h> | ||
32 | #include <asm/pgalloc.h> | ||
33 | #include <asm/mmu_context.h> | 17 | #include <asm/mmu_context.h> |
34 | #include <asm/io.h> | ||
35 | #include <asm/tlb.h> | 18 | #include <asm/tlb.h> |
36 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
37 | #include <asm/cache.h> | 20 | #include <asm/cache.h> |
@@ -39,37 +22,51 @@ | |||
39 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
40 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 23 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
41 | 24 | ||
42 | #ifdef CONFIG_MMU | ||
43 | /* It'd be good if these lines were in the standard header file. */ | ||
44 | #define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) | ||
45 | #define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) | ||
46 | #endif | ||
47 | |||
48 | void (*copy_page)(void *from, void *to); | 25 | void (*copy_page)(void *from, void *to); |
49 | void (*clear_page)(void *to); | 26 | void (*clear_page)(void *to); |
50 | 27 | ||
51 | void show_mem(void) | 28 | void show_mem(void) |
52 | { | 29 | { |
53 | int i, total = 0, reserved = 0; | 30 | int total = 0, reserved = 0, free = 0; |
54 | int shared = 0, cached = 0; | 31 | int shared = 0, cached = 0, slab = 0; |
32 | pg_data_t *pgdat; | ||
55 | 33 | ||
56 | printk("Mem-info:\n"); | 34 | printk("Mem-info:\n"); |
57 | show_free_areas(); | 35 | show_free_areas(); |
58 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 36 | |
59 | i = max_mapnr; | 37 | for_each_online_pgdat(pgdat) { |
60 | while (i-- > 0) { | 38 | struct page *page, *end; |
61 | total++; | 39 | unsigned long flags; |
62 | if (PageReserved(mem_map+i)) | 40 | |
63 | reserved++; | 41 | pgdat_resize_lock(pgdat, &flags); |
64 | else if (PageSwapCache(mem_map+i)) | 42 | page = pgdat->node_mem_map; |
65 | cached++; | 43 | end = page + pgdat->node_spanned_pages; |
66 | else if (page_count(mem_map+i)) | 44 | |
67 | shared += page_count(mem_map+i) - 1; | 45 | do { |
46 | total++; | ||
47 | if (PageReserved(page)) | ||
48 | reserved++; | ||
49 | else if (PageSwapCache(page)) | ||
50 | cached++; | ||
51 | else if (PageSlab(page)) | ||
52 | slab++; | ||
53 | else if (!page_count(page)) | ||
54 | free++; | ||
55 | else | ||
56 | shared += page_count(page) - 1; | ||
57 | page++; | ||
58 | } while (page < end); | ||
59 | |||
60 | pgdat_resize_unlock(pgdat, &flags); | ||
68 | } | 61 | } |
69 | printk("%d pages of RAM\n",total); | 62 | |
70 | printk("%d reserved pages\n",reserved); | 63 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
71 | printk("%d pages shared\n",shared); | 64 | printk("%d pages of RAM\n", total); |
72 | printk("%d pages swap cached\n",cached); | 65 | printk("%d free pages\n", free); |
66 | printk("%d reserved pages\n", reserved); | ||
67 | printk("%d slab pages\n", slab); | ||
68 | printk("%d pages shared\n", shared); | ||
69 | printk("%d pages swap cached\n", cached); | ||
73 | } | 70 | } |
74 | 71 | ||
75 | #ifdef CONFIG_MMU | 72 | #ifdef CONFIG_MMU |
@@ -147,52 +144,38 @@ extern char __init_begin, __init_end; | |||
147 | */ | 144 | */ |
148 | void __init paging_init(void) | 145 | void __init paging_init(void) |
149 | { | 146 | { |
150 | unsigned long zones_size[MAX_NR_ZONES] = { 0, }; | 147 | int nid; |
151 | 148 | ||
152 | /* | 149 | /* We don't need to map the kernel through the TLB, as |
153 | * Setup some defaults for the zone sizes.. these should be safe | 150 | * it is permanatly mapped using P1. So clear the |
154 | * regardless of distcontiguous memory or MMU settings. | 151 | * entire pgd. */ |
155 | */ | 152 | memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); |
156 | zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT; | ||
157 | #ifdef CONFIG_HIGHMEM | ||
158 | zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT; | ||
159 | #endif | ||
160 | |||
161 | #ifdef CONFIG_MMU | ||
162 | /* | ||
163 | * If we have an MMU, and want to be using it .. we need to adjust | ||
164 | * the zone sizes accordingly, in addition to turning it on. | ||
165 | */ | ||
166 | { | ||
167 | /* We don't need to map the kernel through the TLB, as | ||
168 | * it is permanatly mapped using P1. So clear the | ||
169 | * entire pgd. */ | ||
170 | memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); | ||
171 | |||
172 | /* Turn on the MMU */ | ||
173 | enable_mmu(); | ||
174 | zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN; | ||
175 | } | ||
176 | 153 | ||
177 | /* Set an initial value for the MMU.TTB so we don't have to | 154 | /* Set an initial value for the MMU.TTB so we don't have to |
178 | * check for a null value. */ | 155 | * check for a null value. */ |
179 | set_TTB(swapper_pg_dir); | 156 | set_TTB(swapper_pg_dir); |
180 | 157 | ||
181 | #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) | 158 | for_each_online_node(nid) { |
182 | /* | 159 | pg_data_t *pgdat = NODE_DATA(nid); |
183 | * If we don't have CONFIG_MMU set and the processor in question | 160 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
184 | * still has an MMU, care needs to be taken to make sure it doesn't | 161 | unsigned long low, start_pfn; |
185 | * stay on.. Since the boot loader could have potentially already | 162 | |
186 | * turned it on, and we clearly don't want it, we simply turn it off. | 163 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
187 | * | 164 | |
188 | * We don't need to do anything special for the zone sizes, since the | 165 | start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT; |
189 | * default values that were already configured up above should be | 166 | low = pgdat->bdata->node_low_pfn; |
190 | * satisfactory. | 167 | |
191 | */ | 168 | max_zone_pfns[ZONE_NORMAL] = low; |
192 | disable_mmu(); | 169 | add_active_range(nid, start_pfn, low); |
193 | #endif | 170 | |
194 | NODE_DATA(0)->node_mem_map = NULL; | 171 | printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", |
195 | free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); | 172 | nid, start_pfn, low); |
173 | |||
174 | free_area_init_nodes(max_zone_pfns); | ||
175 | |||
176 | printk("Node %u: mem_map starts at %p\n", | ||
177 | pgdat->node_id, pgdat->node_mem_map); | ||
178 | } | ||
196 | } | 179 | } |
197 | 180 | ||
198 | static struct kcore_list kcore_mem, kcore_vmalloc; | 181 | static struct kcore_list kcore_mem, kcore_vmalloc; |
@@ -200,18 +183,33 @@ static struct kcore_list kcore_mem, kcore_vmalloc; | |||
200 | void __init mem_init(void) | 183 | void __init mem_init(void) |
201 | { | 184 | { |
202 | int codesize, reservedpages, datasize, initsize; | 185 | int codesize, reservedpages, datasize, initsize; |
203 | int tmp; | 186 | int nid; |
204 | extern unsigned long memory_start; | ||
205 | 187 | ||
206 | #ifdef CONFIG_MMU | 188 | reservedpages = 0; |
207 | high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE); | ||
208 | #else | ||
209 | extern unsigned long memory_end; | ||
210 | 189 | ||
211 | high_memory = (void *)(memory_end & PAGE_MASK); | 190 | for_each_online_node(nid) { |
212 | #endif | 191 | pg_data_t *pgdat = NODE_DATA(nid); |
192 | unsigned long node_pages = 0; | ||
193 | void *node_high_memory; | ||
194 | int i; | ||
195 | |||
196 | num_physpages += pgdat->node_present_pages; | ||
197 | |||
198 | if (pgdat->node_spanned_pages) | ||
199 | node_pages = free_all_bootmem_node(pgdat); | ||
200 | |||
201 | totalram_pages += node_pages; | ||
213 | 202 | ||
214 | max_mapnr = num_physpages = MAP_NR(high_memory) - MAP_NR(memory_start); | 203 | for (i = 0; i < node_pages; i++) |
204 | if (PageReserved(pgdat->node_mem_map + i)) | ||
205 | reservedpages++; | ||
206 | |||
207 | node_high_memory = (void *)((pgdat->node_start_pfn + | ||
208 | pgdat->node_spanned_pages) << | ||
209 | PAGE_SHIFT); | ||
210 | if (node_high_memory > high_memory) | ||
211 | high_memory = node_high_memory; | ||
212 | } | ||
215 | 213 | ||
216 | /* clear the zero-page */ | 214 | /* clear the zero-page */ |
217 | memset(empty_zero_page, 0, PAGE_SIZE); | 215 | memset(empty_zero_page, 0, PAGE_SIZE); |
@@ -229,16 +227,6 @@ void __init mem_init(void) | |||
229 | clear_page = clear_page_nommu; | 227 | clear_page = clear_page_nommu; |
230 | #endif | 228 | #endif |
231 | 229 | ||
232 | /* this will put all low memory onto the freelists */ | ||
233 | totalram_pages += free_all_bootmem_node(NODE_DATA(0)); | ||
234 | reservedpages = 0; | ||
235 | for (tmp = 0; tmp < num_physpages; tmp++) | ||
236 | /* | ||
237 | * Only count reserved RAM pages | ||
238 | */ | ||
239 | if (PageReserved(mem_map+tmp)) | ||
240 | reservedpages++; | ||
241 | |||
242 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | 230 | codesize = (unsigned long) &_etext - (unsigned long) &_text; |
243 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; | 231 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; |
244 | initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; | 232 | initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; |
@@ -250,7 +238,7 @@ void __init mem_init(void) | |||
250 | printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, " | 238 | printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, " |
251 | "%dk reserved, %dk data, %dk init)\n", | 239 | "%dk reserved, %dk data, %dk init)\n", |
252 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), | 240 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), |
253 | max_mapnr << (PAGE_SHIFT-10), | 241 | totalram_pages << (PAGE_SHIFT-10), |
254 | codesize >> 10, | 242 | codesize >> 10, |
255 | reservedpages << (PAGE_SHIFT-10), | 243 | reservedpages << (PAGE_SHIFT-10), |
256 | datasize >> 10, | 244 | datasize >> 10, |
@@ -289,4 +277,3 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
289 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); | 277 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); |
290 | } | 278 | } |
291 | #endif | 279 | #endif |
292 | |||