init.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1994 - 2000 by Ralf Baechle
  7.  * Copyright (C) 2000 Silicon Graphics, Inc.
  8.  *
  9.  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  10.  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/init.h>
  14. #include <linux/signal.h>
  15. #include <linux/sched.h>
  16. #include <linux/kernel.h>
  17. #include <linux/errno.h>
  18. #include <linux/string.h>
  19. #include <linux/types.h>
  20. #include <linux/pagemap.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/mman.h>
  23. #include <linux/mm.h>
  24. #include <linux/bootmem.h>
  25. #include <linux/highmem.h>
  26. #include <linux/swap.h>
  27. #include <linux/swapctl.h>
  28. #include <linux/blk.h>
  29. #include <asm/bootinfo.h>
  30. #include <asm/cachectl.h>
  31. #include <asm/cpu.h>
  32. #include <asm/dma.h>
  33. #include <asm/jazzdma.h>
  34. #include <asm/system.h>
  35. #include <asm/pgtable.h>
  36. #include <asm/pgalloc.h>
  37. #include <asm/mmu_context.h>
  38. #include <asm/tlb.h>
  39. mmu_gather_t mmu_gathers[NR_CPUS];
  40. unsigned long highstart_pfn, highend_pfn;
  41. static unsigned long totalram_pages;
  42. static unsigned long totalhigh_pages;
  43. extern void prom_free_prom_memory(void);
  44. asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
  45. {
  46. /* This should flush more selectivly ...  */
  47. __flush_cache_all();
  48. return 0;
  49. }
  50. /*
  51.  * We have upto 8 empty zeroed pages so we can map one of the right colour
  52.  * when needed.  This is necessary only on R4000 / R4400 SC and MC versions
  53.  * where we have to avoid VCED / VECI exceptions for good performance at
  54.  * any price.  Since page is never written to after the initialization we
  55.  * don't have to care about aliases on other CPUs.
  56.  */
  57. unsigned long empty_zero_page, zero_page_mask;
  58. static inline unsigned long setup_zero_pages(void)
  59. {
  60. unsigned long order, size;
  61. struct page *page;
  62. if(mips_cpu.options & MIPS_CPU_VCE)
  63. order = 3;
  64. else
  65. order = 0;
  66. empty_zero_page = __get_free_pages(GFP_KERNEL, order);
  67. if (!empty_zero_page)
  68. panic("Oh boy, that early out of memory?");
  69. page = virt_to_page(empty_zero_page);
  70. while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
  71. set_bit(PG_reserved, &page->flags);
  72. set_page_count(page, 0);
  73. page++;
  74. }
  75. size = PAGE_SIZE << order;
  76. zero_page_mask = (size - 1) & PAGE_MASK;
  77. memset((void *)empty_zero_page, 0, size);
  78. return 1UL << order;
  79. }
  80. int do_check_pgt_cache(int low, int high)
  81. {
  82. int freed = 0;
  83. if (pgtable_cache_size > high) {
  84. do {
  85. if (pgd_quicklist)
  86. free_pgd_slow(get_pgd_fast()), freed++;
  87. if (pmd_quicklist)
  88. free_pmd_slow(get_pmd_fast()), freed++;
  89. if (pte_quicklist)
  90. free_pte_slow(get_pte_fast()), freed++;
  91. } while (pgtable_cache_size > low);
  92. }
  93. return freed;
  94. }
  95. #if CONFIG_HIGHMEM
  96. pte_t *kmap_pte;
  97. pgprot_t kmap_prot;
  98. #define kmap_get_fixmap_pte(vaddr)
  99. pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
  100. static void __init kmap_init(void)
  101. {
  102. unsigned long kmap_vstart;
  103. /* cache the first kmap pte */
  104. kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
  105. kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
  106. kmap_prot = PAGE_KERNEL;
  107. }
  108. #endif /* CONFIG_HIGHMEM */
  109. void show_mem(void)
  110. {
  111. int i, free = 0, total = 0, reserved = 0;
  112. int shared = 0, cached = 0;
  113. printk("Mem-info:n");
  114. show_free_areas();
  115. printk("Free swap:       %6dkBn", nr_swap_pages<<(PAGE_SHIFT-10));
  116. i = max_mapnr;
  117. while (i-- > 0) {
  118. total++;
  119. if (PageReserved(mem_map+i))
  120. reserved++;
  121. else if (PageSwapCache(mem_map+i))
  122. cached++;
  123. else if (!page_count(mem_map + i))
  124. free++;
  125. else
  126. shared += page_count(mem_map + i) - 1;
  127. }
  128. printk("%d pages of RAMn", total);
  129. printk("%d reserved pagesn", reserved);
  130. printk("%d pages sharedn", shared);
  131. printk("%d pages swap cachedn",cached);
  132. printk("%ld pages in page table cachen",pgtable_cache_size);
  133. printk("%d free pagesn", free);
  134. show_buffers();
  135. }
  136. /* References to section boundaries */
  137. extern char _ftext, _etext, _fdata, _edata;
  138. extern char __init_begin, __init_end;
  139. static void __init fixrange_init (unsigned long start, unsigned long end,
  140. pgd_t *pgd_base)
  141. {
  142. pgd_t *pgd;
  143. pmd_t *pmd;
  144. pte_t *pte;
  145. int i, j;
  146. unsigned long vaddr;
  147. vaddr = start;
  148. i = __pgd_offset(vaddr);
  149. j = __pmd_offset(vaddr);
  150. pgd = pgd_base + i;
  151. for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
  152. pmd = (pmd_t *)pgd;
  153. for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
  154. if (pmd_none(*pmd)) {
  155. pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
  156. set_pmd(pmd, __pmd(pte));
  157. if (pte != pte_offset(pmd, 0))
  158. BUG();
  159. }
  160. vaddr += PMD_SIZE;
  161. }
  162. j = 0;
  163. }
  164. }
  165. void __init pagetable_init(void)
  166. {
  167. unsigned long vaddr;
  168. pgd_t *pgd, *pgd_base;
  169. pmd_t *pmd;
  170. pte_t *pte;
  171. /* Initialize the entire pgd.  */
  172. pgd_init((unsigned long)swapper_pg_dir);
  173. pgd_init((unsigned long)swapper_pg_dir +
  174.          sizeof(pgd_t ) * USER_PTRS_PER_PGD);
  175. pgd_base = swapper_pg_dir;
  176. #ifdef CONFIG_HIGHMEM
  177. /*
  178.  * Fixed mappings:
  179.  */
  180. vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
  181. fixrange_init(vaddr, 0, pgd_base);
  182. /*
  183.  * Permanent kmaps:
  184.  */
  185. vaddr = PKMAP_BASE;
  186. fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
  187. pgd = swapper_pg_dir + __pgd_offset(vaddr);
  188. pmd = pmd_offset(pgd, vaddr);
  189. pte = pte_offset(pmd, vaddr);
  190. pkmap_page_table = pte;
  191. #endif
  192. }
  193. void __init paging_init(void)
  194. {
  195. unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
  196. unsigned long max_dma, high, low;
  197. pagetable_init();
  198. #ifdef CONFIG_HIGHMEM
  199. kmap_init();
  200. #endif
  201. max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
  202. low = max_low_pfn;
  203. high = highend_pfn;
  204. #ifdef CONFIG_ISA
  205. if (low < max_dma)
  206. zones_size[ZONE_DMA] = low;
  207. else {
  208. zones_size[ZONE_DMA] = max_dma;
  209. zones_size[ZONE_NORMAL] = low - max_dma;
  210. }
  211. #else
  212. zones_size[ZONE_DMA] = low;
  213. #endif
  214. #ifdef CONFIG_HIGHMEM
  215. zones_size[ZONE_HIGHMEM] = high - low;
  216. #endif
  217. free_area_init(zones_size);
  218. }
  219. #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
  220. #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
  221. static inline int page_is_ram(unsigned long pagenr)
  222. {
  223. int i;
  224. for (i = 0; i < boot_mem_map.nr_map; i++) {
  225. unsigned long addr, end;
  226. if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
  227. /* not usable memory */
  228. continue;
  229. addr = PFN_UP(boot_mem_map.map[i].addr);
  230. end = PFN_DOWN(boot_mem_map.map[i].addr
  231.        + boot_mem_map.map[i].size);
  232. if (pagenr >= addr && pagenr < end)
  233. return 1;
  234. }
  235. return 0;
  236. }
  237. void __init mem_init(void)
  238. {
  239. unsigned long codesize, reservedpages, datasize, initsize;
  240. unsigned long tmp, ram;
  241. #if defined(CONFIG_DISCONTIGMEM) && defined(CONFIG_HIGHMEM)
  242. #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
  243. #endif
  244. #ifdef CONFIG_HIGHMEM
  245. highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT;
  246. highmem_start_page = mem_map + highstart_pfn;
  247. max_mapnr = num_physpages = highend_pfn;
  248. num_mappedpages = max_low_pfn;
  249. #else
  250. max_mapnr = num_mappedpages = num_physpages = max_low_pfn;
  251. #endif
  252. high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
  253. totalram_pages += free_all_bootmem();
  254. totalram_pages -= setup_zero_pages(); /* Setup zeroed pages.  */
  255. reservedpages = ram = 0;
  256. for (tmp = 0; tmp < max_low_pfn; tmp++)
  257. if (page_is_ram(tmp)) {
  258. ram++;
  259. if (PageReserved(mem_map+tmp))
  260. reservedpages++;
  261. }
  262. #ifdef CONFIG_HIGHMEM
  263. for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
  264. struct page *page = mem_map + tmp;
  265. if (!page_is_ram(tmp)) {
  266. SetPageReserved(page);
  267. continue;
  268. }
  269. ClearPageReserved(page);
  270. set_bit(PG_highmem, &page->flags);
  271. atomic_set(&page->count, 1);
  272. __free_page(page);
  273. totalhigh_pages++;
  274. }
  275. totalram_pages += totalhigh_pages;
  276. #endif
  277. codesize =  (unsigned long) &_etext - (unsigned long) &_ftext;
  278. datasize =  (unsigned long) &_edata - (unsigned long) &_fdata;
  279. initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
  280. printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
  281.        "%ldk reserved, %ldk data, %ldk init, %ldk highmem)n",
  282.        (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
  283.        ram << (PAGE_SHIFT-10),
  284.        codesize >> 10,
  285.        reservedpages << (PAGE_SHIFT-10),
  286.        datasize >> 10,
  287.        initsize >> 10,
  288.        (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
  289. }
  290. #ifdef CONFIG_BLK_DEV_INITRD
  291. void free_initrd_mem(unsigned long start, unsigned long end)
  292. {
  293. if (start < end)
  294. printk(KERN_INFO "Freeing initrd memory: %ldk freedn",
  295.        (end - start) >> 10);
  296. for (; start < end; start += PAGE_SIZE) {
  297. ClearPageReserved(virt_to_page(start));
  298. set_page_count(virt_to_page(start), 1);
  299. free_page(start);
  300. totalram_pages++;
  301. }
  302. }
  303. #endif
  304. extern char __init_begin, __init_end;
  305. extern void prom_free_prom_memory(void);
  306. void free_initmem(void)
  307. {
  308. unsigned long addr;
  309. prom_free_prom_memory ();
  310. addr = (unsigned long) &__init_begin;
  311. while (addr < (unsigned long) &__init_end) {
  312. ClearPageReserved(virt_to_page(addr));
  313. set_page_count(virt_to_page(addr), 1);
  314. free_page(addr);
  315. totalram_pages++;
  316. addr += PAGE_SIZE;
  317. }
  318. printk(KERN_INFO "Freeing unused kernel memory: %dk freedn",
  319.        (&__init_end - &__init_begin) >> 10);
  320. }
  321. void si_meminfo(struct sysinfo *val)
  322. {
  323. val->totalram = totalram_pages;
  324. val->sharedram = 0;
  325. val->freeram = nr_free_pages();
  326. val->bufferram = atomic_read(&buffermem_pages);
  327. val->totalhigh = totalhigh_pages;
  328. val->freehigh = nr_free_highpages();
  329. val->mem_unit = PAGE_SIZE;
  330. return;
  331. }