2 * arch/xtensa/mm/init.c
4 * Derived from MIPS, PPC.
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
12 * Chris Zankel <chris@zankel.net>
13 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/bootmem.h>
21 #include <linux/gfp.h>
22 #include <linux/swap.h>
23 #include <linux/mman.h>
24 #include <linux/nodemask.h>
27 #include <asm/bootparam.h>
30 /* References to section boundaries */
32 extern char _ftext
, _etext
, _fdata
, _edata
, _rodata_end
;
33 extern char __init_begin
, __init_end
;
36 * mem_reserve(start, end, must_exist)
38 * Reserve some memory from the memory pool.
41 * start Start of region,
43 * must_exist Must exist in memory pool.
46 * 0 (memory area couldn't be mapped)
50 int __init
mem_reserve(unsigned long start
, unsigned long end
, int must_exist
)
57 start
= start
& PAGE_MASK
;
58 end
= PAGE_ALIGN(end
);
60 for (i
= 0; i
< sysmem
.nr_banks
; i
++)
61 if (start
< sysmem
.bank
[i
].end
62 && end
>= sysmem
.bank
[i
].start
)
65 if (i
== sysmem
.nr_banks
) {
67 printk (KERN_WARNING
"mem_reserve: [0x%0lx, 0x%0lx) "
68 "not in any region!\n", start
, end
);
72 if (start
> sysmem
.bank
[i
].start
) {
73 if (end
< sysmem
.bank
[i
].end
) {
75 if (sysmem
.nr_banks
>= SYSMEM_BANKS_MAX
)
76 panic("meminfo overflow\n");
77 sysmem
.bank
[sysmem
.nr_banks
].start
= end
;
78 sysmem
.bank
[sysmem
.nr_banks
].end
= sysmem
.bank
[i
].end
;
81 sysmem
.bank
[i
].end
= start
;
83 if (end
< sysmem
.bank
[i
].end
)
84 sysmem
.bank
[i
].start
= end
;
88 sysmem
.bank
[i
].start
= sysmem
.bank
[sysmem
.nr_banks
].start
;
89 sysmem
.bank
[i
].end
= sysmem
.bank
[sysmem
.nr_banks
].end
;
97 * Initialize the bootmem system and give it all the memory we have available.
100 void __init
bootmem_init(void)
103 unsigned long bootmap_start
, bootmap_size
;
106 max_low_pfn
= max_pfn
= 0;
109 for (i
=0; i
< sysmem
.nr_banks
; i
++) {
110 pfn
= PAGE_ALIGN(sysmem
.bank
[i
].start
) >> PAGE_SHIFT
;
111 if (pfn
< min_low_pfn
)
113 pfn
= PAGE_ALIGN(sysmem
.bank
[i
].end
- 1) >> PAGE_SHIFT
;
118 if (min_low_pfn
> max_pfn
)
119 panic("No memory found!\n");
121 max_low_pfn
= max_pfn
< MAX_MEM_PFN
>> PAGE_SHIFT
?
122 max_pfn
: MAX_MEM_PFN
>> PAGE_SHIFT
;
124 /* Find an area to use for the bootmem bitmap. */
126 bootmap_size
= bootmem_bootmap_pages(max_low_pfn
- min_low_pfn
);
127 bootmap_size
<<= PAGE_SHIFT
;
130 for (i
=0; i
<sysmem
.nr_banks
; i
++)
131 if (sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
>= bootmap_size
) {
132 bootmap_start
= sysmem
.bank
[i
].start
;
136 if (bootmap_start
== ~0UL)
137 panic("Cannot find %ld bytes for bootmap\n", bootmap_size
);
139 /* Reserve the bootmem bitmap area */
141 mem_reserve(bootmap_start
, bootmap_start
+ bootmap_size
, 1);
142 bootmap_size
= init_bootmem_node(NODE_DATA(0),
143 bootmap_start
>> PAGE_SHIFT
,
147 /* Add all remaining memory pieces into the bootmem map */
149 for (i
=0; i
<sysmem
.nr_banks
; i
++)
150 free_bootmem(sysmem
.bank
[i
].start
,
151 sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
);
156 void __init
zones_init(void)
158 unsigned long zones_size
[MAX_NR_ZONES
];
161 /* All pages are DMA-able, so we put them all in the DMA zone. */
163 zones_size
[ZONE_DMA
] = max_low_pfn
- ARCH_PFN_OFFSET
;
164 for (i
= 1; i
< MAX_NR_ZONES
; i
++)
167 #ifdef CONFIG_HIGHMEM
168 zones_size
[ZONE_HIGHMEM
] = max_pfn
- max_low_pfn
;
171 free_area_init_node(0, zones_size
, ARCH_PFN_OFFSET
, NULL
);
175 * Initialize memory pages.
178 void __init
mem_init(void)
180 unsigned long codesize
, reservedpages
, datasize
, initsize
;
181 unsigned long highmemsize
, tmp
, ram
;
183 max_mapnr
= num_physpages
= max_low_pfn
- ARCH_PFN_OFFSET
;
184 high_memory
= (void *) __va(max_low_pfn
<< PAGE_SHIFT
);
187 #ifdef CONFIG_HIGHMEM
188 #error HIGHGMEM not implemented in init.c
191 totalram_pages
+= free_all_bootmem();
193 reservedpages
= ram
= 0;
194 for (tmp
= 0; tmp
< max_mapnr
; tmp
++) {
196 if (PageReserved(mem_map
+tmp
))
200 codesize
= (unsigned long) &_etext
- (unsigned long) &_ftext
;
201 datasize
= (unsigned long) &_edata
- (unsigned long) &_fdata
;
202 initsize
= (unsigned long) &__init_end
- (unsigned long) &__init_begin
;
204 printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
205 "%ldk data, %ldk init %ldk highmem)\n",
206 nr_free_pages() << (PAGE_SHIFT
-10),
207 ram
<< (PAGE_SHIFT
-10),
209 reservedpages
<< (PAGE_SHIFT
-10),
216 free_reserved_mem(void *start
, void *end
)
218 for (; start
< end
; start
+= PAGE_SIZE
) {
219 ClearPageReserved(virt_to_page(start
));
220 init_page_count(virt_to_page(start
));
221 free_page((unsigned long)start
);
226 #ifdef CONFIG_BLK_DEV_INITRD
227 extern int initrd_is_mapped
;
229 void free_initrd_mem(unsigned long start
, unsigned long end
)
231 if (initrd_is_mapped
) {
232 free_reserved_mem((void*)start
, (void*)end
);
233 printk ("Freeing initrd memory: %ldk freed\n",(end
-start
)>>10);
238 void free_initmem(void)
240 free_reserved_mem(&__init_begin
, &__init_end
);
241 printk("Freeing unused kernel memory: %dk freed\n",
242 (&__init_end
- &__init_begin
) >> 10);