diff options
Diffstat (limited to 'arch/avr32/mm/init.c')
-rw-r--r-- | arch/avr32/mm/init.c | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index 70da6894acc1..82cf70854b90 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c | |||
@@ -10,11 +10,9 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/initrd.h> | ||
14 | #include <linux/mmzone.h> | 13 | #include <linux/mmzone.h> |
15 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
16 | #include <linux/pagemap.h> | 15 | #include <linux/pagemap.h> |
17 | #include <linux/pfn.h> | ||
18 | #include <linux/nodemask.h> | 16 | #include <linux/nodemask.h> |
19 | 17 | ||
20 | #include <asm/page.h> | 18 | #include <asm/page.h> |
@@ -78,242 +76,6 @@ void show_mem(void) | |||
78 | printk ("%d pages swap cached\n", cached); | 76 | printk ("%d pages swap cached\n", cached); |
79 | } | 77 | } |
80 | 78 | ||
81 | static void __init print_memory_map(const char *what, | ||
82 | struct tag_mem_range *mem) | ||
83 | { | ||
84 | printk ("%s:\n", what); | ||
85 | for (; mem; mem = mem->next) { | ||
86 | printk (" %08lx - %08lx\n", | ||
87 | (unsigned long)mem->addr, | ||
88 | (unsigned long)(mem->addr + mem->size)); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #define MAX_LOWMEM HIGHMEM_START | ||
93 | #define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) | ||
94 | |||
95 | /* | ||
96 | * Sort a list of memory regions in-place by ascending address. | ||
97 | * | ||
98 | * We're using bubble sort because we only have singly linked lists | ||
99 | * with few elements. | ||
100 | */ | ||
101 | static void __init sort_mem_list(struct tag_mem_range **pmem) | ||
102 | { | ||
103 | int done; | ||
104 | struct tag_mem_range **a, **b; | ||
105 | |||
106 | if (!*pmem) | ||
107 | return; | ||
108 | |||
109 | do { | ||
110 | done = 1; | ||
111 | a = pmem, b = &(*pmem)->next; | ||
112 | while (*b) { | ||
113 | if ((*a)->addr > (*b)->addr) { | ||
114 | struct tag_mem_range *tmp; | ||
115 | tmp = (*b)->next; | ||
116 | (*b)->next = *a; | ||
117 | *a = *b; | ||
118 | *b = tmp; | ||
119 | done = 0; | ||
120 | } | ||
121 | a = &(*a)->next; | ||
122 | b = &(*a)->next; | ||
123 | } | ||
124 | } while (!done); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Find a free memory region large enough for storing the | ||
129 | * bootmem bitmap. | ||
130 | */ | ||
131 | static unsigned long __init | ||
132 | find_bootmap_pfn(const struct tag_mem_range *mem) | ||
133 | { | ||
134 | unsigned long bootmap_pages, bootmap_len; | ||
135 | unsigned long node_pages = PFN_UP(mem->size); | ||
136 | unsigned long bootmap_addr = mem->addr; | ||
137 | struct tag_mem_range *reserved = mem_reserved; | ||
138 | struct tag_mem_range *ramdisk = mem_ramdisk; | ||
139 | unsigned long kern_start = virt_to_phys(_stext); | ||
140 | unsigned long kern_end = virt_to_phys(_end); | ||
141 | |||
142 | bootmap_pages = bootmem_bootmap_pages(node_pages); | ||
143 | bootmap_len = bootmap_pages << PAGE_SHIFT; | ||
144 | |||
145 | /* | ||
146 | * Find a large enough region without reserved pages for | ||
147 | * storing the bootmem bitmap. We can take advantage of the | ||
148 | * fact that all lists have been sorted. | ||
149 | * | ||
150 | * We have to check explicitly reserved regions as well as the | ||
151 | * kernel image and any RAMDISK images... | ||
152 | * | ||
153 | * Oh, and we have to make sure we don't overwrite the taglist | ||
154 | * since we're going to use it until the bootmem allocator is | ||
155 | * fully up and running. | ||
156 | */ | ||
157 | while (1) { | ||
158 | if ((bootmap_addr < kern_end) && | ||
159 | ((bootmap_addr + bootmap_len) > kern_start)) | ||
160 | bootmap_addr = kern_end; | ||
161 | |||
162 | while (reserved && | ||
163 | (bootmap_addr >= (reserved->addr + reserved->size))) | ||
164 | reserved = reserved->next; | ||
165 | |||
166 | if (reserved && | ||
167 | ((bootmap_addr + bootmap_len) >= reserved->addr)) { | ||
168 | bootmap_addr = reserved->addr + reserved->size; | ||
169 | continue; | ||
170 | } | ||
171 | |||
172 | while (ramdisk && | ||
173 | (bootmap_addr >= (ramdisk->addr + ramdisk->size))) | ||
174 | ramdisk = ramdisk->next; | ||
175 | |||
176 | if (!ramdisk || | ||
177 | ((bootmap_addr + bootmap_len) < ramdisk->addr)) | ||
178 | break; | ||
179 | |||
180 | bootmap_addr = ramdisk->addr + ramdisk->size; | ||
181 | } | ||
182 | |||
183 | if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size)) | ||
184 | return ~0UL; | ||
185 | |||
186 | return PFN_UP(bootmap_addr); | ||
187 | } | ||
188 | |||
189 | void __init setup_bootmem(void) | ||
190 | { | ||
191 | unsigned bootmap_size; | ||
192 | unsigned long first_pfn, bootmap_pfn, pages; | ||
193 | unsigned long max_pfn, max_low_pfn; | ||
194 | unsigned long kern_start = virt_to_phys(_stext); | ||
195 | unsigned long kern_end = virt_to_phys(_end); | ||
196 | unsigned node = 0; | ||
197 | struct tag_mem_range *bank, *res; | ||
198 | |||
199 | sort_mem_list(&mem_phys); | ||
200 | sort_mem_list(&mem_reserved); | ||
201 | |||
202 | print_memory_map("Physical memory", mem_phys); | ||
203 | print_memory_map("Reserved memory", mem_reserved); | ||
204 | |||
205 | nodes_clear(node_online_map); | ||
206 | |||
207 | if (mem_ramdisk) { | ||
208 | #ifdef CONFIG_BLK_DEV_INITRD | ||
209 | initrd_start = (unsigned long)__va(mem_ramdisk->addr); | ||
210 | initrd_end = initrd_start + mem_ramdisk->size; | ||
211 | |||
212 | print_memory_map("RAMDISK images", mem_ramdisk); | ||
213 | if (mem_ramdisk->next) | ||
214 | printk(KERN_WARNING | ||
215 | "Warning: Only the first RAMDISK image " | ||
216 | "will be used\n"); | ||
217 | sort_mem_list(&mem_ramdisk); | ||
218 | #else | ||
219 | printk(KERN_WARNING "RAM disk image present, but " | ||
220 | "no initrd support in kernel!\n"); | ||
221 | #endif | ||
222 | } | ||
223 | |||
224 | if (mem_phys->next) | ||
225 | printk(KERN_WARNING "Only using first memory bank\n"); | ||
226 | |||
227 | for (bank = mem_phys; bank; bank = NULL) { | ||
228 | first_pfn = PFN_UP(bank->addr); | ||
229 | max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size); | ||
230 | bootmap_pfn = find_bootmap_pfn(bank); | ||
231 | if (bootmap_pfn > max_pfn) | ||
232 | panic("No space for bootmem bitmap!\n"); | ||
233 | |||
234 | if (max_low_pfn > MAX_LOWMEM_PFN) { | ||
235 | max_low_pfn = MAX_LOWMEM_PFN; | ||
236 | #ifndef CONFIG_HIGHMEM | ||
237 | /* | ||
238 | * Lowmem is memory that can be addressed | ||
239 | * directly through P1/P2 | ||
240 | */ | ||
241 | printk(KERN_WARNING | ||
242 | "Node %u: Only %ld MiB of memory will be used.\n", | ||
243 | node, MAX_LOWMEM >> 20); | ||
244 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
245 | #else | ||
246 | #error HIGHMEM is not supported by AVR32 yet | ||
247 | #endif | ||
248 | } | ||
249 | |||
250 | /* Initialize the boot-time allocator with low memory only. */ | ||
251 | bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, | ||
252 | first_pfn, max_low_pfn); | ||
253 | |||
254 | printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n", | ||
255 | node, NODE_DATA(node)->bdata, | ||
256 | NODE_DATA(node)->bdata->node_bootmem_map); | ||
257 | |||
258 | /* | ||
259 | * Register fully available RAM pages with the bootmem | ||
260 | * allocator. | ||
261 | */ | ||
262 | pages = max_low_pfn - first_pfn; | ||
263 | free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), | ||
264 | PFN_PHYS(pages)); | ||
265 | |||
266 | /* | ||
267 | * Reserve space for the kernel image (if present in | ||
268 | * this node)... | ||
269 | */ | ||
270 | if ((kern_start >= PFN_PHYS(first_pfn)) && | ||
271 | (kern_start < PFN_PHYS(max_pfn))) { | ||
272 | printk("Node %u: Kernel image %08lx - %08lx\n", | ||
273 | node, kern_start, kern_end); | ||
274 | reserve_bootmem_node(NODE_DATA(node), kern_start, | ||
275 | kern_end - kern_start); | ||
276 | } | ||
277 | |||
278 | /* ...the bootmem bitmap... */ | ||
279 | reserve_bootmem_node(NODE_DATA(node), | ||
280 | PFN_PHYS(bootmap_pfn), | ||
281 | bootmap_size); | ||
282 | |||
283 | /* ...any RAMDISK images... */ | ||
284 | for (res = mem_ramdisk; res; res = res->next) { | ||
285 | if (res->addr > PFN_PHYS(max_pfn)) | ||
286 | break; | ||
287 | |||
288 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
289 | printk("Node %u: RAMDISK %08lx - %08lx\n", | ||
290 | node, | ||
291 | (unsigned long)res->addr, | ||
292 | (unsigned long)(res->addr + res->size)); | ||
293 | reserve_bootmem_node(NODE_DATA(node), | ||
294 | res->addr, res->size); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* ...and any other reserved regions. */ | ||
299 | for (res = mem_reserved; res; res = res->next) { | ||
300 | if (res->addr > PFN_PHYS(max_pfn)) | ||
301 | break; | ||
302 | |||
303 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
304 | printk("Node %u: Reserved %08lx - %08lx\n", | ||
305 | node, | ||
306 | (unsigned long)res->addr, | ||
307 | (unsigned long)(res->addr + res->size)); | ||
308 | reserve_bootmem_node(NODE_DATA(node), | ||
309 | res->addr, res->size); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | node_set_online(node); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /* | 79 | /* |
318 | * paging_init() sets up the page tables | 80 | * paging_init() sets up the page tables |
319 | * | 81 | * |