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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * Generic VM initialization for x86-64 NUMA setups.
  3.  * Copyright 2002 Andi Kleen, SuSE Labs.
  4.  * $Id: numa.c,v 1.4 2002/09/05 15:28:12 ak Exp $
  5.  */ 
  6. #include <linux/kernel.h>
  7. #include <linux/mm.h>
  8. #include <linux/string.h>
  9. #include <linux/init.h>
  10. #include <linux/bootmem.h>
  11. #include <linux/mmzone.h>
  12. #include <linux/blk.h>
  13. #include <asm/e820.h>
  14. #include <asm/proto.h>
  15. #include <asm/dma.h>
  16. #undef Dprintk
  17. #define Dprintk(...) 
  18. plat_pg_data_t *plat_node_data[MAXNODE];
  19. bootmem_data_t plat_node_bdata[MAX_NUMNODES];
  20. #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
  21. static int numa_off __initdata; 
  22. unsigned long nodes_present; 
  23. int maxnode;
  24. /* Initialize bootmem allocator for a node */
  25. void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
  26. unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; 
  27. unsigned long nodedata_phys;
  28. const int pgdat_size = round_up(sizeof(plat_pg_data_t), PAGE_SIZE);
  29. start = round_up(start, ZONE_ALIGN); 
  30. printk("Bootmem setup node %d %016lx-%016lxn", nodeid, start, end);
  31. start_pfn = start >> PAGE_SHIFT;
  32. end_pfn = end >> PAGE_SHIFT;
  33. nodedata_phys = find_e820_area(start, end, pgdat_size); 
  34. if (nodedata_phys == -1L) 
  35. panic("Cannot find memory pgdat in node %dn", nodeid);
  36. Dprintk("nodedata_phys %lxn", nodedata_phys); 
  37. PLAT_NODE_DATA(nodeid) = phys_to_virt(nodedata_phys);
  38. memset(PLAT_NODE_DATA(nodeid), 0, sizeof(plat_pg_data_t));
  39. NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
  40. /* Find a place for the bootmem map */
  41. bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 
  42. bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
  43. bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT);
  44. if (bootmap_start == -1L) 
  45. panic("Not enough continuous space for bootmap on node %d", nodeid); 
  46. Dprintk("bootmap start %lu pages %lun", bootmap_start, bootmap_pages); 
  47. bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
  48.  bootmap_start >> PAGE_SHIFT, 
  49.  start_pfn, end_pfn); 
  50. e820_bootmem_free(NODE_DATA(nodeid), start, end);
  51. reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); 
  52. reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
  53. PLAT_NODE_DATA(nodeid)->start_pfn = start_pfn;
  54. PLAT_NODE_DATA(nodeid)->end_pfn = end_pfn;
  55. if (nodeid > maxnode) 
  56. maxnode = nodeid;
  57. nodes_present |= (1UL << nodeid); 
  58. /* Initialize final allocator for a zone */
  59. void __init setup_node_zones(int nodeid)
  60. unsigned long start_pfn, end_pfn; 
  61. unsigned long zones[MAX_NR_ZONES];
  62. unsigned long dma_end_pfn;
  63. unsigned long lmax_mapnr;
  64. memset(zones, 0, sizeof(unsigned long) * MAX_NR_ZONES); 
  65. start_pfn = PLAT_NODE_DATA(nodeid)->start_pfn; 
  66. end_pfn = PLAT_NODE_DATA(nodeid)->end_pfn; 
  67. printk("setting up node %d %lx-%lxn", nodeid, start_pfn, end_pfn); 
  68. /* All nodes > 0 have a zero length zone DMA */ 
  69. dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; 
  70. if (start_pfn < dma_end_pfn) { 
  71. zones[ZONE_DMA] = dma_end_pfn - start_pfn;
  72. zones[ZONE_NORMAL] = end_pfn - dma_end_pfn; 
  73. } else { 
  74. zones[ZONE_NORMAL] = end_pfn - start_pfn; 
  75.     
  76. free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, 
  77.     start_pfn<<PAGE_SHIFT, NULL); 
  78. lmax_mapnr = PLAT_NODE_DATA_STARTNR(nodeid) + PLAT_NODE_DATA_SIZE(nodeid);
  79. if (lmax_mapnr > max_mapnr)
  80. max_mapnr = lmax_mapnr;
  81. int fake_node;
  82. int __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
  83. #ifdef CONFIG_K8_NUMA
  84. if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT))
  85. return 0; 
  86. #endif
  87. printk(KERN_INFO "%sn",
  88.        numa_off ? "NUMA turned off" : "No NUMA configuration found");
  89.    
  90. printk(KERN_INFO "Faking a node at %016lx-%016lxn", 
  91.        start_pfn << PAGE_SHIFT,
  92.        end_pfn << PAGE_SHIFT); 
  93. /* setup dummy node covering all memory */ 
  94. fake_node = 1; 
  95. memnode_shift = 63; 
  96. memnodemap[0] = 0;
  97. setup_node_bootmem(0, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
  98. return -1; 
  99. #define for_all_nodes(x) for ((x) = 0; (x) <= maxnode; (x)++) 
  100. if ((1UL << (x)) & nodes_present)
  101. unsigned long __init numa_free_all_bootmem(void) 
  102. int i;
  103. unsigned long pages = 0;
  104. for_all_nodes(i) {
  105. pages += free_all_bootmem_node(NODE_DATA(i));
  106. }
  107. return pages;
  108. void __init paging_init(void)
  109. int i;
  110. for_all_nodes(i) { 
  111. setup_node_zones(i); 
  112. }
  113. void show_mem(void)
  114. {
  115. long i,free = 0,total = 0,reserved = 0;
  116. long shared = 0, cached = 0;
  117. int nid;
  118. printk("nMem-info:n");
  119. show_free_areas();
  120. printk("Free swap:       %6dkBn",nr_swap_pages<<(PAGE_SHIFT-10));
  121. for_all_nodes (nid) { 
  122. mem_map_t * lmem_map = NODE_MEM_MAP(nid);
  123. i = PLAT_NODE_DATA_SIZE(nid);
  124. while (i-- > 0) {
  125. total++;
  126. if (PageReserved(lmem_map+i))
  127. reserved++;
  128. else if (PageSwapCache(lmem_map+i))
  129. cached++;
  130. else if (!page_count(lmem_map+i))
  131. free++;
  132. else
  133. shared += atomic_read(&lmem_map[i].count) - 1;
  134. }
  135. }
  136. printk("%ld pages of RAMn",total);
  137. printk("%ld free pagesn",free);
  138. printk("%ld reserved pagesn",reserved);
  139. printk("%ld pages sharedn",shared);
  140. printk("%ld pages swap cachedn",cached);
  141. show_buffers();
  142. }
  143. /* [numa=off] */
  144. static __init int numa_setup(char *opt) 
  145. if (!strcmp(opt,"off"))
  146. numa_off = 1;
  147. return 1;
  148. __setup("numa=", numa_setup);