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
- min_low_pfn
);
134 bootmap_size
<<= PAGE_SHIFT
;
137 for (i
=0; i
<sysmem
.nr_banks
; i
++)
138 if (sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
>= bootmap_size
) {
139 bootmap_start
= sysmem
.bank
[i
].start
;
143 if (bootmap_start
== ~0UL)
144 panic("Cannot find %ld bytes for bootmap\n", bootmap_size
);
146 /* Reserve the bootmem bitmap area */
148 mem_reserve(bootmap_start
, bootmap_start
+ bootmap_size
, 1);
149 bootmap_size
= init_bootmem_node(NODE_DATA(0),
150 bootmap_start
>> PAGE_SHIFT
,
154 /* Add all remaining memory pieces into the bootmem map */
156 for (i
=0; i
<sysmem
.nr_banks
; i
++)
157 free_bootmem(sysmem
.bank
[i
].start
,
158 sysmem
.bank
[i
].end
- sysmem
.bank
[i
].start
);
163 void __init
paging_init(void)
165 unsigned long zones_size
[MAX_NR_ZONES
];
168 /* All pages are DMA-able, so we put them all in the DMA zone. */
170 zones_size
[ZONE_DMA
] = max_low_pfn
;
171 for (i
= 1; i
< MAX_NR_ZONES
; i
++)
174 #ifdef CONFIG_HIGHMEM
175 zones_size
[ZONE_HIGHMEM
] = max_pfn
- max_low_pfn
;
178 /* Initialize the kernel's page tables. */
180 memset(swapper_pg_dir
, 0, PAGE_SIZE
);
182 free_area_init(zones_size
);
186 * Flush the mmu and reset associated register to default values.
189 void __init
init_mmu (void)
191 /* Writing zeros to the <t>TLBCFG special registers ensure
192 * that valid values exist in the register. For existing
193 * PGSZID<w> fields, zero selects the first element of the
194 * page-size array. For nonexistent PGSZID<w> fields, zero is
195 * the best value to write. Also, when changing PGSZID<w>
196 * fields, the corresponding TLB must be flushed.
198 set_itlbcfg_register (0);
199 set_dtlbcfg_register (0);
202 /* Set rasid register to a known value. */
204 set_rasid_register (ASID_USER_FIRST
);
206 /* Set PTEVADDR special register to the start of the page
207 * table, which is in kernel mappable space (ie. not
208 * statically mapped). This register's value is undefined on
211 set_ptevaddr_register (PGTABLE_START
);
215 * Initialize memory pages.
218 void __init
mem_init(void)
220 unsigned long codesize
, reservedpages
, datasize
, initsize
;
221 unsigned long highmemsize
, tmp
, ram
;
223 max_mapnr
= num_physpages
= max_low_pfn
;
224 high_memory
= (void *) __va(max_mapnr
<< PAGE_SHIFT
);
227 #ifdef CONFIG_HIGHMEM
228 #error HIGHGMEM not implemented in init.c
231 totalram_pages
+= free_all_bootmem();
233 reservedpages
= ram
= 0;
234 for (tmp
= 0; tmp
< max_low_pfn
; tmp
++) {
236 if (PageReserved(mem_map
+tmp
))
240 codesize
= (unsigned long) &_etext
- (unsigned long) &_ftext
;
241 datasize
= (unsigned long) &_edata
- (unsigned long) &_fdata
;
242 initsize
= (unsigned long) &__init_end
- (unsigned long) &__init_begin
;
244 printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
245 "%ldk data, %ldk init %ldk highmem)\n",
246 (unsigned long) nr_free_pages() << (PAGE_SHIFT
-10),
247 ram
<< (PAGE_SHIFT
-10),
249 reservedpages
<< (PAGE_SHIFT
-10),
256 free_reserved_mem(void *start
, void *end
)
258 for (; start
< end
; start
+= PAGE_SIZE
) {
259 ClearPageReserved(virt_to_page(start
));
260 init_page_count(virt_to_page(start
));
261 free_page((unsigned long)start
);
266 #ifdef CONFIG_BLK_DEV_INITRD
267 extern int initrd_is_mapped
;
269 void free_initrd_mem(unsigned long start
, unsigned long end
)
271 if (initrd_is_mapped
) {
272 free_reserved_mem((void*)start
, (void*)end
);
273 printk ("Freeing initrd memory: %ldk freed\n",(end
-start
)>>10);
278 void free_initmem(void)
280 free_reserved_mem(&__init_begin
, &__init_end
);
281 printk("Freeing unused kernel memory: %dk freed\n",
282 (&__init_end
- &__init_begin
) >> 10);
285 struct kmem_cache
*pgtable_cache __read_mostly
;
287 static void pgd_ctor(void* addr
)
289 pte_t
* ptep
= (pte_t
*)addr
;
292 for (i
= 0; i
< 1024; i
++, ptep
++)
293 pte_clear(NULL
, 0, ptep
);
297 void __init
pgtable_cache_init(void)
299 pgtable_cache
= kmem_cache_create("pgd",
300 PAGE_SIZE
, PAGE_SIZE
,