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/swap.h>
22 #include <linux/mman.h>
23 #include <linux/nodemask.h>
25 #include <linux/slab.h>
27 #include <asm/pgtable.h>
28 #include <asm/bootparam.h>
29 #include <asm/mmu_context.h>
32 #include <asm/pgalloc.h>
35 DEFINE_PER_CPU(struct mmu_gather
, mmu_gathers
);
37 /* References to section boundaries */
39 extern char _ftext
, _etext
, _fdata
, _edata
, _rodata_end
;
40 extern char __init_begin
, __init_end
;
43 * mem_reserve(start, end, must_exist)
45 * Reserve some memory from the memory pool.
48 * start Start of region,
50 * must_exist Must exist in memory pool.
53 * 0 (memory area couldn't be mapped)
57 int __init
mem_reserve(unsigned long start
, unsigned long end
, int must_exist
)
64 start
= start
& PAGE_MASK
;
65 end
= PAGE_ALIGN(end
);
67 for (i
= 0; i
< sysmem
.nr_banks
; i
++)
68 if (start
< sysmem
.bank
[i
].end
69 && end
>= sysmem
.bank
[i
].start
)
72 if (i
== sysmem
.nr_banks
) {
74 printk (KERN_WARNING
"mem_reserve: [0x%0lx, 0x%0lx) "
75 "not in any region!\n", start
, end
);
79 if (start
> sysmem
.bank
[i
].start
) {
80 if (end
< sysmem
.bank
[i
].end
) {
82 if (sysmem
.nr_banks
>= SYSMEM_BANKS_MAX
)
83 panic("meminfo overflow\n");
84 sysmem
.bank
[sysmem
.nr_banks
].start
= end
;
85 sysmem
.bank
[sysmem
.nr_banks
].end
= sysmem
.bank
[i
].end
;
88 sysmem
.bank
[i
].end
= start
;
90 if (end
< sysmem
.bank
[i
].end
)
91 sysmem
.bank
[i
].start
= end
;
95 sysmem
.bank
[i
].start
= sysmem
.bank
[sysmem
.nr_banks
].start
;
96 sysmem
.bank
[i
].end
= sysmem
.bank
[sysmem
.nr_banks
].end
;
104 * Initialize the bootmem system and give it all the memory we have available.
107 void __init
bootmem_init(void)
110 unsigned long bootmap_start
, bootmap_size
;
113 max_low_pfn
= max_pfn
= 0;
116 for (i
=0; i
< sysmem
.nr_banks
; i
++) {
117 pfn
= PAGE_ALIGN(sysmem
.bank
[i
].start
) >> PAGE_SHIFT
;
118 if (pfn
< min_low_pfn
)
120 pfn
= PAGE_ALIGN(sysmem
.bank
[i
].end
- 1) >> PAGE_SHIFT
;
125 if (min_low_pfn
> max_pfn
)
126 panic("No memory found!\n");
128 max_low_pfn
= max_pfn
< MAX_MEM_PFN
>> PAGE_SHIFT
?
129 max_pfn
: MAX_MEM_PFN
>> PAGE_SHIFT
;
131 /* Find an area to use for the bootmem bitmap. */
133 bootmap_size
= bootmem_bootmap_pages(max_low_pfn
) << PAGE_SHIFT
;
136 for (i
=0; i
<sysmem
.nr_banks
; i
++)
137 if (sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
>= bootmap_size
) {
138 bootmap_start
= sysmem
.bank
[i
].start
;
142 if (bootmap_start
== ~0UL)
143 panic("Cannot find %ld bytes for bootmap\n", bootmap_size
);
145 /* Reserve the bootmem bitmap area */
147 mem_reserve(bootmap_start
, bootmap_start
+ bootmap_size
, 1);
148 bootmap_size
= init_bootmem_node(NODE_DATA(0), min_low_pfn
,
149 bootmap_start
>> PAGE_SHIFT
,
152 /* Add all remaining memory pieces into the bootmem map */
154 for (i
=0; i
<sysmem
.nr_banks
; i
++)
155 free_bootmem(sysmem
.bank
[i
].start
,
156 sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
);
161 void __init
paging_init(void)
163 unsigned long zones_size
[MAX_NR_ZONES
];
166 /* All pages are DMA-able, so we put them all in the DMA zone. */
168 zones_size
[ZONE_DMA
] = max_low_pfn
;
169 for (i
= 1; i
< MAX_NR_ZONES
; i
++)
172 #ifdef CONFIG_HIGHMEM
173 zones_size
[ZONE_HIGHMEM
] = max_pfn
- max_low_pfn
;
176 /* Initialize the kernel's page tables. */
178 memset(swapper_pg_dir
, 0, PAGE_SIZE
);
180 free_area_init(zones_size
);
184 * Flush the mmu and reset associated register to default values.
187 void __init
init_mmu (void)
189 /* Writing zeros to the <t>TLBCFG special registers ensure
190 * that valid values exist in the register. For existing
191 * PGSZID<w> fields, zero selects the first element of the
192 * page-size array. For nonexistent PGSZID<w> fields, zero is
193 * the best value to write. Also, when changing PGSZID<w>
194 * fields, the corresponding TLB must be flushed.
196 set_itlbcfg_register (0);
197 set_dtlbcfg_register (0);
200 /* Set rasid register to a known value. */
202 set_rasid_register (ASID_USER_FIRST
);
204 /* Set PTEVADDR special register to the start of the page
205 * table, which is in kernel mappable space (ie. not
206 * statically mapped). This register's value is undefined on
209 set_ptevaddr_register (PGTABLE_START
);
213 * Initialize memory pages.
216 void __init
mem_init(void)
218 unsigned long codesize
, reservedpages
, datasize
, initsize
;
219 unsigned long highmemsize
, tmp
, ram
;
221 max_mapnr
= num_physpages
= max_low_pfn
;
222 high_memory
= (void *) __va(max_mapnr
<< PAGE_SHIFT
);
225 #ifdef CONFIG_HIGHMEM
226 #error HIGHGMEM not implemented in init.c
229 totalram_pages
+= free_all_bootmem();
231 reservedpages
= ram
= 0;
232 for (tmp
= 0; tmp
< max_low_pfn
; tmp
++) {
234 if (PageReserved(mem_map
+tmp
))
238 codesize
= (unsigned long) &_etext
- (unsigned long) &_ftext
;
239 datasize
= (unsigned long) &_edata
- (unsigned long) &_fdata
;
240 initsize
= (unsigned long) &__init_end
- (unsigned long) &__init_begin
;
242 printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
243 "%ldk data, %ldk init %ldk highmem)\n",
244 (unsigned long) nr_free_pages() << (PAGE_SHIFT
-10),
245 ram
<< (PAGE_SHIFT
-10),
247 reservedpages
<< (PAGE_SHIFT
-10),
254 free_reserved_mem(void *start
, void *end
)
256 for (; start
< end
; start
+= PAGE_SIZE
) {
257 ClearPageReserved(virt_to_page(start
));
258 init_page_count(virt_to_page(start
));
259 free_page((unsigned long)start
);
264 #ifdef CONFIG_BLK_DEV_INITRD
265 extern int initrd_is_mapped
;
267 void free_initrd_mem(unsigned long start
, unsigned long end
)
269 if (initrd_is_mapped
) {
270 free_reserved_mem((void*)start
, (void*)end
);
271 printk ("Freeing initrd memory: %ldk freed\n",(end
-start
)>>10);
276 void free_initmem(void)
278 free_reserved_mem(&__init_begin
, &__init_end
);
279 printk("Freeing unused kernel memory: %dk freed\n",
280 (&__init_end
- &__init_begin
) >> 10);
283 struct kmem_cache
*pgtable_cache __read_mostly
;
285 static void pgd_ctor(void* addr
)
287 pte_t
* ptep
= (pte_t
*)addr
;
290 for (i
= 0; i
< 1024; i
++, ptep
++)
291 pte_clear(NULL
, 0, ptep
);
295 void __init
pgtable_cache_init(void)
297 pgtable_cache
= kmem_cache_create("pgd",
298 PAGE_SIZE
, PAGE_SIZE
,