init.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/parisc/mm/init.c
  3.  *
  4.  *  Copyright (C) 1995 Linus Torvalds
  5.  *  Copyright 1999 SuSE GmbH
  6.  *    changed by Philipp Rumpf
  7.  *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  8.  *
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/mm.h>
  12. #include <linux/bootmem.h>
  13. #include <linux/delay.h>
  14. #include <linux/init.h>
  15. #include <linux/pci.h> /* for hppa_dma_ops and pcxl_dma_ops */
  16. #include <linux/swap.h>
  17. #include <linux/unistd.h>
  18. #include <asm/pgalloc.h>
  19. static unsigned long totalram_pages;
  20. extern unsigned long max_pfn, mem_max;
  21. void free_initmem(void)  {
  22. }
  23. /*
  24.  * Just an arbitrary offset to serve as a "hole" between mapping areas
  25.  * (between top of physical memory and a potential pcxl dma mapping
  26.  * area, and below the vmalloc mapping area).
  27.  *
  28.  * The current 32K value just means that there will be a 32K "hole"
  29.  * between mapping areas. That means that  any out-of-bounds memory
  30.  * accesses will hopefully be caught. The vmalloc() routines leaves
  31.  * a hole of 4kB between each vmalloced area for the same reason.
  32.  */
  33. #define VM_MAP_OFFSET  (32*1024)
  34. #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) 
  35.      & ~(VM_MAP_OFFSET-1)))
  36. void *vmalloc_start;
  37. unsigned long pcxl_dma_start;
  38. void __init mem_init(void)
  39. {
  40. max_mapnr = num_physpages = max_low_pfn;
  41. high_memory = __va(max_low_pfn * PAGE_SIZE);
  42. totalram_pages += free_all_bootmem();
  43. printk("Memory: %luk availablen", totalram_pages << (PAGE_SHIFT-10));
  44. if (hppa_dma_ops == &pcxl_dma_ops) {
  45.     pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory);
  46.     vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
  47. }
  48. else {
  49.     pcxl_dma_start = 0;
  50.     vmalloc_start = SET_MAP_OFFSET(high_memory);
  51. }
  52. }
  53. void __bad_pgd(pgd_t *pgd)
  54. {
  55. printk("Bad pgd in pmd_alloc: %08lxn", pgd_val(*pgd));
  56. pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
  57. }
  58. void __bad_pmd(pmd_t *pmd)
  59. {
  60. printk("Bad pmd in pte_alloc: %08lxn", pmd_val(*pmd));
  61. pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
  62. }
  63. pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
  64. {
  65. pte_t *pte;
  66. pte = (pte_t *) __get_free_page(GFP_KERNEL);
  67. if (pmd_none(*pmd)) {
  68. if (pte) {
  69. clear_page(pte);
  70. pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte);
  71. return pte + offset;
  72. }
  73. pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
  74. return NULL;
  75. }
  76. free_page((unsigned long)pte);
  77. if (pmd_bad(*pmd)) {
  78. __bad_pmd(pmd);
  79. return NULL;
  80. }
  81. return (pte_t *) pmd_page(*pmd) + offset;
  82. }
  83. int do_check_pgt_cache(int low, int high)
  84. {
  85. return 0;
  86. }
  87. /*
  88.  * BAD_PAGE is the page that is used for page faults when linux
  89.  * is out-of-memory. Older versions of linux just did a
  90.  * do_exit(), but using this instead means there is less risk
  91.  * for a process dying in kernel mode, possibly leaving an inode
  92.  * unused etc..
  93.  *
  94.  * BAD_PAGETABLE is the accompanying page-table: it is initialized
  95.  * to point to BAD_PAGE entries.
  96.  *
  97.  * ZERO_PAGE is a special page that is used for zero-initialized
  98.  * data and COW.
  99.  */
  100. pte_t * __bad_pagetable(void)
  101. {
  102. return (pte_t *) NULL;
  103. }
  104. unsigned long *empty_zero_page;
  105. unsigned long *empty_bad_page;
  106. pte_t __bad_page(void)
  107. {
  108. return *(pte_t *)NULL;
  109. }
  110. void show_mem(void)
  111. {
  112. int i,free = 0,total = 0,reserved = 0;
  113. int shared = 0, cached = 0;
  114. printk("Mem-info:n");
  115. show_free_areas();
  116. printk("Free swap:  %6dkBn",nr_swap_pages<<(PAGE_SHIFT-10));
  117. i = max_mapnr;
  118. while (i-- > 0) {
  119. total++;
  120. if (PageReserved(mem_map+i))
  121. reserved++;
  122. else if (PageSwapCache(mem_map+i))
  123. cached++;
  124. else if (!atomic_read(&mem_map[i].count))
  125. free++;
  126. else
  127. shared += atomic_read(&mem_map[i].count) - 1;
  128. }
  129. printk("%d pages of RAMn",total);
  130. printk("%d reserved pagesn",reserved);
  131. printk("%d pages sharedn",shared);
  132. printk("%d pages swap cachedn",cached);
  133. show_buffers();
  134. }
  135. void set_pte_phys (unsigned long vaddr, unsigned long phys)
  136. {
  137. }
  138. /*
  139.  * pagetable_init() sets up the page tables
  140.  *
  141.  * Note that gateway_init() places the Linux gateway page at page 0.
  142.  * Since gateway pages cannot be dereferenced this has the desirable
  143.  * side effect of trapping those pesky NULL-reference errors in the
  144.  * kernel.
  145.  */
  146. static void __init pagetable_init(void)
  147. {
  148. pgd_t *pg_dir;
  149. pmd_t *pmd;
  150. pte_t *pg_table;
  151. unsigned long tmp1;
  152. unsigned long tmp2;
  153. unsigned long address;
  154. unsigned long ro_start;
  155. unsigned long ro_end;
  156. unsigned long fv_addr;
  157. extern  const int stext;
  158. extern  int data_start;
  159. extern  const unsigned long fault_vector_20;
  160. ro_start = __pa((unsigned long)&stext);
  161. ro_end   = __pa((unsigned long)&data_start);
  162. fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
  163. printk("pagetable_initn");
  164. /* Map whole memory from PAGE_OFFSET */
  165. pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS;
  166. address = 0;
  167. while (address < mem_max) {
  168. /* XXX: BTLB should be done here */
  169. #if PTRS_PER_PMD == 1
  170. pmd = (pmd_t *)__pa(pg_dir);
  171. #else
  172. pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
  173. /*
  174.  * pmd is physical at this point
  175.  */
  176. if (!pmd) {
  177. pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
  178. pmd = (pmd_t *) __pa(pmd);
  179. }
  180. pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
  181. #endif
  182. pg_dir++;
  183. /* now change pmd to kernel virtual addresses */
  184. pmd = (pmd_t *) __va(pmd);
  185. for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) {
  186. /*
  187.  * pg_table is physical at this point
  188.  */
  189. pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
  190. if (!pg_table) {
  191. pg_table = (pte_t *)
  192. alloc_bootmem_low_pages(PAGE_SIZE);
  193. pg_table = (pte_t *) __pa(pg_table);
  194. }
  195. pmd_val(*pmd) = _PAGE_TABLE |
  196.    (unsigned long) pg_table;
  197. /* now change pg_table to kernel virtual addresses */
  198. pg_table = (pte_t *) __va(pg_table);
  199. for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
  200. pte_t pte;
  201. #if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
  202. #warning STI console should explicitly allocate executable pages but does not
  203. /* KWDB needs to write kernel text when setting break points.
  204. **
  205. ** The right thing to do seems like KWDB modify only the pte which
  206. ** has a break point on it...otherwise we might mask worse bugs.
  207. */
  208. if (address >= ro_start && address < ro_end
  209. && address != fv_addr)
  210.     pte = __mk_pte(address, PAGE_KERNEL_RO);
  211. else
  212. #endif
  213.     pte = __mk_pte(address, PAGE_KERNEL);
  214. if (address >= mem_max)
  215. pte_val(pte) = 0;
  216. set_pte(pg_table, pte);
  217. address += PAGE_SIZE;
  218. }
  219. if (address >= mem_max)
  220.     break;
  221. }
  222. }
  223. empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
  224. memset(empty_zero_page, 0, PAGE_SIZE);
  225. }
  226. unsigned long gateway_pgd_offset;
  227. unsigned long gateway_pgd_entry;
  228. static void __init gateway_init(void)
  229. {
  230. unsigned long hpux_gateway_page_addr;
  231. unsigned long linux_gateway_page_addr;
  232. pgd_t *pg_dir;
  233. pmd_t *pmd_base;
  234. pmd_t *pmd;
  235. pte_t *pg_table_base;
  236. pte_t *pg_table;
  237. /* FIXME: These are 'const' in order to trick the compiler
  238.            into not treating them as DP-relative data. */
  239. extern void * const hpux_gateway_page;
  240. extern void * const linux_gateway_page;
  241. pte_t pte;
  242. hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
  243. linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
  244. gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT;
  245. /*
  246.  * Setup Linux Gateway page.
  247.  *
  248.  * The Linux gateway page will reside in kernel space (on virtual
  249.  * page 0), so it doesn't need to be aliased into user space.
  250.  */
  251. pg_dir = (pgd_t *)swapper_pg_dir;
  252. #if PTRS_PER_PMD == 1
  253. pmd_base = (pmd_t *)pg_dir;
  254. pmd = pmd_base +
  255. ((linux_gateway_page_addr) >> PGDIR_SHIFT);
  256. #else
  257. pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
  258. pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) =
  259. _PAGE_TABLE | __pa(pmd_base);
  260. pmd = pmd_base +
  261. ((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
  262. PMD_SHIFT);
  263. #endif
  264. pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
  265. pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
  266. pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
  267. pg_table = pg_table_base +
  268. ((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
  269. PAGE_SHIFT);
  270. set_pte(pg_table,pte);
  271. /*
  272.  * Setup HP-UX gateway page.
  273.  * This page will be aliased into each user address space.
  274.  */
  275. pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
  276. pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY);
  277. pg_table = pg_table_base +
  278. ((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
  279. PAGE_SHIFT);
  280. set_pte(pg_table,pte);
  281. #if PTRS_PER_PMD == 1
  282. pmd_base = (pmd_t *)pg_table_base;
  283. #else
  284. pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
  285. pmd = pmd_base +
  286. ((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
  287. PMD_SHIFT);
  288. pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
  289. #endif
  290. gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base);
  291. /*
  292.  * We will be aliasing the HP-UX gateway page into all HP-UX
  293.  * user spaces at the same address (not counting the space register
  294.  * value) that will be equivalently mapped as long as space register
  295.  * hashing is disabled. It will be a problem if anyone touches
  296.  * the gateway pages at its "kernel" address, since that is
  297.  * NOT equivalently mapped. We'll flush the caches at this
  298.  * point, just in case some code has touched those addresses
  299.  * previous to this, but all bets are off if they get touched
  300.  * after this point.
  301.  */
  302. flush_all_caches();
  303. return;
  304. }
  305. void __init paging_init(void)
  306. {
  307. pagetable_init();
  308. gateway_init();
  309. {
  310. unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, };
  311. free_area_init(zones_size);
  312. }
  313. }
  314. #define NR_SPACE_IDS 8192
  315. static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))];
  316. static unsigned long space_id_index;
  317. static unsigned long free_space_ids = NR_SPACE_IDS;
  318. /*
  319.  * XXX: We should probably unfold the set_bit / test_bit / clear_bit
  320.  * locking out of these two functions and have a single spinlock on the
  321.  * space_id data structures.
  322.  *
  323.  * Don't bother. This is all going to be significantly changed in the
  324.  * very near future.
  325.  */
  326. #define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32)
  327. unsigned long alloc_sid(void)
  328. {
  329. unsigned long index;
  330. if (free_space_ids == 0)
  331. BUG();
  332. free_space_ids--;
  333. do {
  334. index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
  335. } while(test_and_set_bit(index, space_id));
  336. space_id_index = index;
  337. return index << SPACEID_SHIFT;
  338. }
  339. void free_sid(unsigned long spaceid)
  340. {
  341. unsigned long index = spaceid >> SPACEID_SHIFT;
  342. if (index < 0)
  343. BUG();
  344. clear_bit(index, space_id);
  345. if (space_id_index > index) {
  346. space_id_index = index;
  347. }
  348. free_space_ids++;
  349. }
  350. #ifdef CONFIG_BLK_DEV_INITRD
  351. void free_initrd_mem(unsigned long start, unsigned long end)
  352. {
  353. #if 0
  354. for (; start < end; start += PAGE_SIZE) {
  355. ClearPageReserved(mem_map + MAP_NR(start));
  356. set_page_count(mem_map+MAP_NR(start), 1);
  357. free_page(start);
  358. totalram_pages++;
  359. }
  360. printk ("Freeing initrd memory: %ldk freedn", (end - start) >> 10);
  361. #endif
  362. }
  363. #endif
  364. void si_meminfo(struct sysinfo *val)
  365. {
  366. int i;
  367. i = max_mapnr;
  368. val->totalram = totalram_pages;
  369. val->sharedram = 0;
  370. val->freeram = nr_free_pages();
  371. val->bufferram = atomic_read(&buffermem_pages);
  372. #if 0
  373. while (i-- > 0)  {
  374. if (PageReserved(mem_map+i))
  375. continue;
  376. val->totalram++;
  377. if (!atomic_read(&mem_map[i].count))
  378. continue;
  379. val->sharedram += atomic_read(&mem_map[i].count) - 1;
  380. }
  381. val->totalram <<= PAGE_SHIFT;
  382. val->sharedram <<= PAGE_SHIFT;
  383. #endif
  384. val->totalhigh = 0;
  385. val->freehigh = 0;
  386. return;
  387. }