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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/mm/init.c
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Hartmut Penner (hpenner@de.ibm.com)
  7.  *
  8.  *  Derived from "arch/i386/mm/init.c"
  9.  *    Copyright (C) 1995  Linus Torvalds
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/signal.h>
  13. #include <linux/sched.h>
  14. #include <linux/kernel.h>
  15. #include <linux/errno.h>
  16. #include <linux/string.h>
  17. #include <linux/types.h>
  18. #include <linux/ptrace.h>
  19. #include <linux/mman.h>
  20. #include <linux/mm.h>
  21. #include <linux/swap.h>
  22. #include <linux/smp.h>
  23. #include <linux/init.h>
  24. #ifdef CONFIG_BLK_DEV_INITRD
  25. #include <linux/blk.h>
  26. #endif
  27. #include <linux/pagemap.h>
  28. #include <linux/bootmem.h>
  29. #include <asm/processor.h>
  30. #include <asm/system.h>
  31. #include <asm/uaccess.h>
  32. #include <asm/pgtable.h>
  33. #include <asm/pgalloc.h>
  34. #include <asm/dma.h>
  35. #include <asm/lowcore.h>
  36. #include <asm/tlb.h>
  37. mmu_gather_t mmu_gathers[NR_CPUS];
  38. static unsigned long totalram_pages;
  39. pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
  40. char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
  41. pmd_t *pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
  42. {
  43.         unsigned long addr = (unsigned long) pgd;
  44.         unsigned long *pgd_slot =  (unsigned long *) (addr & -8);
  45.         unsigned long offset = addr & 4;
  46. pmd_t *new, *pmd2;
  47. int i;
  48.  
  49.         if (offset == 0 && 
  50.     ((*pgd_slot & _PGD_ENTRY_INV) != 0 ||
  51.      (*pgd_slot & _PGD_ENTRY_LEN(2)) == 0)) {
  52.                 /* Set lower pmd, upper pmd is empty. */
  53.                 *pgd_slot = __pa(pmd) | _PGD_ENTRY_MASK |
  54.                                 _PGD_ENTRY_OFF(0) | _PGD_ENTRY_LEN(1);
  55.                 return pmd;
  56.         }
  57.         if (offset == 4 &&
  58.     ((*pgd_slot & _PGD_ENTRY_INV) != 0 ||
  59.      (*pgd_slot & _PGD_ENTRY_OFF(2)) != 0)) {
  60.                 /* Lower pmd empty, set upper pmd. */
  61.                 *pgd_slot = (__pa(pmd) - 0x2000) | _PGD_ENTRY_MASK |
  62.                                 _PGD_ENTRY_OFF(2) | _PGD_ENTRY_LEN(3);
  63.                 return pmd;
  64.         }
  65.         /* We have to enlarge the pmd to 16K if we arrive here. */
  66. new = (pmd_t *) __get_free_pages(GFP_KERNEL, 2);
  67. if (new == NULL) {
  68. pmd_free(pmd);
  69. return NULL;
  70. }
  71. /* Set the PG_arch_1 bit on the first and the third pmd page
  72.            so that pmd_free_fast can recognize pmds that have been
  73.            allocated with an order 2 allocation.  */
  74. set_bit(PG_arch_1, &virt_to_page(new)->flags);
  75. set_bit(PG_arch_1, &virt_to_page(new+PTRS_PER_PMD)->flags);
  76. /* Now copy the two pmds to the new memory area. */
  77. if (offset == 0) {
  78. pmd2 = (pmd_t *)(*pgd_slot & PAGE_MASK) + PTRS_PER_PMD;
  79. memcpy(new, pmd, sizeof(pmd_t)*PTRS_PER_PMD);
  80. memcpy(new + PTRS_PER_PMD, pmd2, sizeof(pmd_t)*PTRS_PER_PMD);
  81. } else {
  82. pmd2 = (pmd_t *)(*pgd_slot & PAGE_MASK);
  83. memcpy(new, pmd2, sizeof(pmd_t)*PTRS_PER_PMD);
  84. memcpy(new + PTRS_PER_PMD, pmd, sizeof(pmd_t)*PTRS_PER_PMD);
  85. }
  86. *pgd_slot = __pa(new) | _PGD_ENTRY_MASK |
  87. _PGD_ENTRY_OFF(0) | _PGD_ENTRY_LEN(3);
  88. for (i = 0; i < PTRS_PER_PMD; i++) {
  89. pmd_clear(pmd + i);
  90. pmd_clear(pmd2 + i);
  91. }
  92. pmd_free(pmd);
  93. pmd_free(pmd2);
  94. return new;
  95. }
  96. void pmd_free_order2(pmd_t *pmd)
  97. {
  98. pmd_t *pmd2 = (pmd_t *) ((unsigned long) pmd ^ 8192);
  99. clear_bit(PG_arch_1, &virt_to_page(pmd)->flags);
  100. if (test_bit(PG_arch_1, &virt_to_page(pmd2)->flags) == 0) {
  101. /* The other pmd of the order 2 allocation has already
  102.    been freed. Now we can release the order 2 allocation.  */
  103. free_pages((unsigned long) pmd & ~8192, 2);
  104. }
  105. }
  106. int do_check_pgt_cache(int low, int high)
  107. {
  108.         int freed = 0;
  109.         if(pgtable_cache_size > high) {
  110.                 do {
  111.                         if(pgd_quicklist) {
  112. free_pgd_slow(get_pgd_fast());
  113. freed += 2;
  114. }
  115.                         if(pmd_quicklist) {
  116. pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
  117. freed += 2;
  118. }
  119.                         if(pte_quicklist) {
  120. pte_free_slow(pte_alloc_one_fast(NULL, 0));
  121. freed += 1;
  122. }
  123.                 } while(pgtable_cache_size > low);
  124.         }
  125.         return freed;
  126. }
  127. void show_mem(void)
  128. {
  129.         int i, total = 0,reserved = 0;
  130.         int shared = 0, cached = 0;
  131.         printk("Mem-info:n");
  132.         show_free_areas();
  133.         printk("Free swap:       %6dkBn",nr_swap_pages<<(PAGE_SHIFT-10));
  134.         i = max_mapnr;
  135.         while (i-- > 0) {
  136.                 total++;
  137.                 if (PageReserved(mem_map+i))
  138.                         reserved++;
  139.                 else if (PageSwapCache(mem_map+i))
  140.                         cached++;
  141.                 else if (page_count(mem_map+i))
  142.                         shared += atomic_read(&mem_map[i].count) - 1;
  143.         }
  144.         printk("%d pages of RAMn",total);
  145.         printk("%d reserved pagesn",reserved);
  146.         printk("%d pages sharedn",shared);
  147.         printk("%d pages swap cachedn",cached);
  148.         printk("%ld pages in page table cachen",pgtable_cache_size);
  149.         show_buffers();
  150. }
  151. /* References to section boundaries */
  152. extern unsigned long _text;
  153. extern unsigned long _etext;
  154. extern unsigned long _edata;
  155. extern unsigned long __bss_start;
  156. extern unsigned long _end;
  157. extern unsigned long __init_begin;
  158. extern unsigned long __init_end;
  159. /*
  160.  * paging_init() sets up the page tables
  161.  */
  162. unsigned long last_valid_pfn;
  163. void __init paging_init(void)
  164. {
  165. unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
  166. static const int ssm_mask = 0x04000000L;
  167. unsigned long dma_pfn, address, end_mem;
  168.         pgd_t * pg_dir;
  169. int     i,j,k;
  170. dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
  171. if (dma_pfn > max_low_pfn)
  172. zones_size[ZONE_DMA] = max_low_pfn;
  173. else {
  174. zones_size[ZONE_DMA] = dma_pfn;
  175. zones_size[ZONE_NORMAL] = max_low_pfn - dma_pfn;
  176. }
  177. /* Initialize mem_map[].  */
  178. free_area_init(zones_size);
  179. /*
  180.  * map whole physical memory to virtual memory (identity mapping) 
  181.  */
  182.         pg_dir = swapper_pg_dir;
  183. address = 0;
  184. end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
  185.         for (i = 0 ; i < PTRS_PER_PGD/2 ; i++, pg_dir += 2) {
  186. pmd_t *pm_dir;
  187.                 if (address >= end_mem) {
  188.                         pgd_clear(pg_dir);
  189.                         continue;
  190.                 }
  191.         
  192.         pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
  193. *((unsigned long *) pg_dir) = __pa(pm_dir) | _PGD_ENTRY_MASK |
  194. _PGD_ENTRY_LEN(3) | _PGD_ENTRY_OFF(0);
  195.                 for (j = 0 ; j < PTRS_PER_PMD*2 ; j++, pm_dir++) {
  196. pte_t *pt_dir;
  197.                         if (address >= end_mem) {
  198.                                 pmd_clear(pm_dir);
  199.                                 continue; 
  200.                         }          
  201.                         
  202.                         pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
  203.                         pmd_populate(&init_mm, pm_dir, pt_dir);
  204.                         for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
  205.                                 pte_t pte = mk_pte_phys(address, PAGE_KERNEL);
  206.                                 if (address >= end_mem) {
  207.                                         pte_clear(&pte); 
  208.                                         continue;
  209.                                 }
  210.                                 set_pte(pt_dir, pte);
  211.                                 address += PAGE_SIZE;
  212.                         }
  213.                 }
  214.         }
  215.         
  216.         /* enable virtual mapping in kernel mode */
  217.         __asm__ __volatile__("lctlg 1,1,%0nt"
  218.                              "lctlg 7,7,%0nt"
  219.                              "lctlg 13,13,%0nt"
  220.                              "ssm   %1"
  221.      : :"m" (__pa(swapper_pg_dir) | _KERN_REGION_TABLE),
  222.         "m" (ssm_mask));
  223.         local_flush_tlb();
  224.         return;
  225. }
  226. void __init mem_init(void)
  227. {
  228. unsigned long codesize, reservedpages, datasize, initsize;
  229.         max_mapnr = num_physpages = max_low_pfn;
  230.         high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
  231.         /* clear the zero-page */
  232.         memset(empty_zero_page, 0, PAGE_SIZE);
  233. /* this will put all low memory onto the freelists */
  234. totalram_pages += free_all_bootmem();
  235. reservedpages = 0;
  236. codesize =  (unsigned long) &_etext - (unsigned long) &_text;
  237. datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
  238. initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
  239.         printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)n",
  240.                 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
  241.                 max_mapnr << (PAGE_SHIFT-10),
  242.                 codesize >> 10,
  243.                 reservedpages << (PAGE_SHIFT-10),
  244.                 datasize >>10,
  245.                 initsize >> 10);
  246. }
  247. void free_initmem(void)
  248. {
  249.         unsigned long addr;
  250.         addr = (unsigned long)(&__init_begin);
  251.         for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
  252. ClearPageReserved(virt_to_page(addr));
  253. set_page_count(virt_to_page(addr), 1);
  254. free_page(addr);
  255. totalram_pages++;
  256.         }
  257.         printk (KERN_INFO "Freeing unused kernel memory: %ldk freedn",
  258. (&__init_end - &__init_begin) >> 10);
  259. }
  260. #ifdef CONFIG_BLK_DEV_INITRD
  261. void free_initrd_mem(unsigned long start, unsigned long end)
  262. {
  263.         if (start < end)
  264.                 printk (KERN_INFO "Freeing initrd memory: %ldk freedn", (end - start) >> 10);
  265. for (; start < end; start += PAGE_SIZE) {
  266.                 ClearPageReserved(virt_to_page(start));
  267.                 set_page_count(virt_to_page(start), 1);
  268. free_page(start);
  269. totalram_pages++;
  270. }
  271. }
  272. #endif
  273. void si_meminfo(struct sysinfo *val)
  274. {
  275.         val->totalram = totalram_pages;
  276. val->sharedram = 0;
  277. val->freeram = nr_free_pages();
  278. val->bufferram = atomic_read(&buffermem_pages);
  279. val->totalhigh = 0;
  280. val->freehigh = 0;
  281. val->mem_unit = PAGE_SIZE;
  282. }
  283. /*
  284.  * Overrides for Emacs so that we follow Linus's tabbing style.
  285.  * Emacs will notice this stuff at the end of the file and automatically
  286.  * adjust the settings for this buffer only.  This must remain at the end
  287.  * of the file.
  288.  * ---------------------------------------------------------------------------
  289.  * Local variables:
  290.  * c-indent-level: 4 
  291.  * c-brace-imaginary-offset: 0
  292.  * c-brace-offset: -4
  293.  * c-argdecl-indent: 4
  294.  * c-label-offset: -4
  295.  * c-continued-statement-offset: 4
  296.  * c-continued-brace-offset: 0
  297.  * indent-tabs-mode: nil
  298.  * tab-width: 8
  299.  * End:
  300.  */