init.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * arch/xtensa/mm/init.c
  3. *
  4. * Derived from MIPS, PPC.
  5. *
  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
  8. * for more details.
  9. *
  10. * Copyright (C) 2001 - 2005 Tensilica Inc.
  11. *
  12. * Chris Zankel <chris@zankel.net>
  13. * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
  14. * Marc Gauthier
  15. * Kevin Chea
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/errno.h>
  19. #include <linux/bootmem.h>
  20. #include <linux/swap.h>
  21. #include <linux/mman.h>
  22. #include <linux/nodemask.h>
  23. #include <linux/mm.h>
  24. #include <linux/slab.h>
  25. #include <asm/pgtable.h>
  26. #include <asm/bootparam.h>
  27. #include <asm/mmu_context.h>
  28. #include <asm/tlb.h>
  29. #include <asm/page.h>
  30. #include <asm/pgalloc.h>
  31. DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
  32. /* References to section boundaries */
  33. extern char _ftext, _etext, _fdata, _edata, _rodata_end;
  34. extern char __init_begin, __init_end;
  35. /*
  36. * mem_reserve(start, end, must_exist)
  37. *
  38. * Reserve some memory from the memory pool.
  39. *
  40. * Parameters:
  41. * start Start of region,
  42. * end End of region,
  43. * must_exist Must exist in memory pool.
  44. *
  45. * Returns:
  46. * 0 (memory area couldn't be mapped)
  47. * -1 (success)
  48. */
  49. int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
  50. {
  51. int i;
  52. if (start == end)
  53. return 0;
  54. start = start & PAGE_MASK;
  55. end = PAGE_ALIGN(end);
  56. for (i = 0; i < sysmem.nr_banks; i++)
  57. if (start < sysmem.bank[i].end
  58. && end >= sysmem.bank[i].start)
  59. break;
  60. if (i == sysmem.nr_banks) {
  61. if (must_exist)
  62. printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
  63. "not in any region!\n", start, end);
  64. return 0;
  65. }
  66. if (start > sysmem.bank[i].start) {
  67. if (end < sysmem.bank[i].end) {
  68. /* split entry */
  69. if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
  70. panic("meminfo overflow\n");
  71. sysmem.bank[sysmem.nr_banks].start = end;
  72. sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
  73. sysmem.nr_banks++;
  74. }
  75. sysmem.bank[i].end = start;
  76. } else {
  77. if (end < sysmem.bank[i].end)
  78. sysmem.bank[i].start = end;
  79. else {
  80. /* remove entry */
  81. sysmem.nr_banks--;
  82. sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
  83. sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end;
  84. }
  85. }
  86. return -1;
  87. }
  88. /*
  89. * Initialize the bootmem system and give it all the memory we have available.
  90. */
  91. void __init bootmem_init(void)
  92. {
  93. unsigned long pfn;
  94. unsigned long bootmap_start, bootmap_size;
  95. int i;
  96. max_low_pfn = max_pfn = 0;
  97. min_low_pfn = ~0;
  98. for (i=0; i < sysmem.nr_banks; i++) {
  99. pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT;
  100. if (pfn < min_low_pfn)
  101. min_low_pfn = pfn;
  102. pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT;
  103. if (pfn > max_pfn)
  104. max_pfn = pfn;
  105. }
  106. if (min_low_pfn > max_pfn)
  107. panic("No memory found!\n");
  108. max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ?
  109. max_pfn : MAX_MEM_PFN >> PAGE_SHIFT;
  110. /* Find an area to use for the bootmem bitmap. */
  111. bootmap_size = bootmem_bootmap_pages(max_low_pfn) << PAGE_SHIFT;
  112. bootmap_start = ~0;
  113. for (i=0; i<sysmem.nr_banks; i++)
  114. if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) {
  115. bootmap_start = sysmem.bank[i].start;
  116. break;
  117. }
  118. if (bootmap_start == ~0UL)
  119. panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
  120. /* Reserve the bootmem bitmap area */
  121. mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1);
  122. bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn,
  123. bootmap_start >> PAGE_SHIFT,
  124. max_low_pfn);
  125. /* Add all remaining memory pieces into the bootmem map */
  126. for (i=0; i<sysmem.nr_banks; i++)
  127. free_bootmem(sysmem.bank[i].start,
  128. sysmem.bank[i].end - sysmem.bank[i].start);
  129. }
  130. void __init paging_init(void)
  131. {
  132. unsigned long zones_size[MAX_NR_ZONES];
  133. int i;
  134. /* All pages are DMA-able, so we put them all in the DMA zone. */
  135. zones_size[ZONE_DMA] = max_low_pfn;
  136. for (i = 1; i < MAX_NR_ZONES; i++)
  137. zones_size[i] = 0;
  138. #ifdef CONFIG_HIGHMEM
  139. zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
  140. #endif
  141. /* Initialize the kernel's page tables. */
  142. memset(swapper_pg_dir, 0, PAGE_SIZE);
  143. free_area_init(zones_size);
  144. }
  145. /*
  146. * Flush the mmu and reset associated register to default values.
  147. */
  148. void __init init_mmu (void)
  149. {
  150. /* Writing zeros to the <t>TLBCFG special registers ensure
  151. * that valid values exist in the register. For existing
  152. * PGSZID<w> fields, zero selects the first element of the
  153. * page-size array. For nonexistent PGSZID<w> fields, zero is
  154. * the best value to write. Also, when changing PGSZID<w>
  155. * fields, the corresponding TLB must be flushed.
  156. */
  157. set_itlbcfg_register (0);
  158. set_dtlbcfg_register (0);
  159. flush_tlb_all ();
  160. /* Set rasid register to a known value. */
  161. set_rasid_register (ASID_USER_FIRST);
  162. /* Set PTEVADDR special register to the start of the page
  163. * table, which is in kernel mappable space (ie. not
  164. * statically mapped). This register's value is undefined on
  165. * reset.
  166. */
  167. set_ptevaddr_register (PGTABLE_START);
  168. }
  169. /*
  170. * Initialize memory pages.
  171. */
  172. void __init mem_init(void)
  173. {
  174. unsigned long codesize, reservedpages, datasize, initsize;
  175. unsigned long highmemsize, tmp, ram;
  176. max_mapnr = num_physpages = max_low_pfn;
  177. high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
  178. highmemsize = 0;
  179. #ifdef CONFIG_HIGHMEM
  180. #error HIGHGMEM not implemented in init.c
  181. #endif
  182. totalram_pages += free_all_bootmem();
  183. reservedpages = ram = 0;
  184. for (tmp = 0; tmp < max_low_pfn; tmp++) {
  185. ram++;
  186. if (PageReserved(mem_map+tmp))
  187. reservedpages++;
  188. }
  189. codesize = (unsigned long) &_etext - (unsigned long) &_ftext;
  190. datasize = (unsigned long) &_edata - (unsigned long) &_fdata;
  191. initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
  192. printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
  193. "%ldk data, %ldk init %ldk highmem)\n",
  194. (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
  195. ram << (PAGE_SHIFT-10),
  196. codesize >> 10,
  197. reservedpages << (PAGE_SHIFT-10),
  198. datasize >> 10,
  199. initsize >> 10,
  200. highmemsize >> 10);
  201. }
  202. void
  203. free_reserved_mem(void *start, void *end)
  204. {
  205. for (; start < end; start += PAGE_SIZE) {
  206. ClearPageReserved(virt_to_page(start));
  207. init_page_count(virt_to_page(start));
  208. free_page((unsigned long)start);
  209. totalram_pages++;
  210. }
  211. }
  212. #ifdef CONFIG_BLK_DEV_INITRD
  213. extern int initrd_is_mapped;
  214. void free_initrd_mem(unsigned long start, unsigned long end)
  215. {
  216. if (initrd_is_mapped) {
  217. free_reserved_mem((void*)start, (void*)end);
  218. printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
  219. }
  220. }
  221. #endif
  222. void free_initmem(void)
  223. {
  224. free_reserved_mem(&__init_begin, &__init_end);
  225. printk("Freeing unused kernel memory: %dk freed\n",
  226. (&__init_end - &__init_begin) >> 10);
  227. }
  228. struct kmem_cache *pgtable_cache __read_mostly;
  229. static void pgd_ctor(void* addr)
  230. {
  231. pte_t* ptep = (pte_t*)addr;
  232. int i;
  233. for (i = 0; i < 1024; i++, ptep++)
  234. pte_clear(NULL, 0, ptep);
  235. }
  236. void __init pgtable_cache_init(void)
  237. {
  238. pgtable_cache = kmem_cache_create("pgd",
  239. PAGE_SIZE, PAGE_SIZE,
  240. SLAB_HWCACHE_ALIGN,
  241. pgd_ctor);
  242. }