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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/alpha/mm/numa.c
  3.  *
  4.  *  DISCONTIGMEM NUMA alpha support.
  5.  *
  6.  *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/mm.h>
  12. #include <linux/bootmem.h>
  13. #include <linux/swap.h>
  14. #ifdef CONFIG_BLK_DEV_INITRD
  15. #include <linux/blk.h>
  16. #endif
  17. #include <asm/hwrpb.h>
  18. #include <asm/pgalloc.h>
  19. plat_pg_data_t *plat_node_data[MAX_NUMNODES];
  20. bootmem_data_t plat_node_bdata[MAX_NUMNODES];
  21. #undef DEBUG_DISCONTIG
  22. #ifdef DEBUG_DISCONTIG
  23. #define DBGDCONT(args...) printk(args)
  24. #else
  25. #define DBGDCONT(args...)
  26. #endif
  27. #define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
  28. #define PFN_DOWN(x)     ((x) >> PAGE_SHIFT)
  29. #define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
  30. #define for_each_mem_cluster(memdesc, cluster, i)
  31. for ((cluster) = (memdesc)->cluster, (i) = 0;
  32.      (i) < (memdesc)->numclusters; (i)++, (cluster)++)
  33. static void __init show_mem_layout(void)
  34. {
  35. struct memclust_struct * cluster;
  36. struct memdesc_struct * memdesc;
  37. int i;
  38. /* Find free clusters, and init and free the bootmem accordingly.  */
  39. memdesc = (struct memdesc_struct *)
  40.   (hwrpb->mddt_offset + (unsigned long) hwrpb);
  41. printk("Raw memory layout:n");
  42. for_each_mem_cluster(memdesc, cluster, i) {
  43. printk(" memcluster %2d, usage %1lx, start %8lu, end %8lun",
  44.        i, cluster->usage, cluster->start_pfn,
  45.        cluster->start_pfn + cluster->numpages);
  46. }
  47. }
  48. static void __init
  49. setup_memory_node(int nid, void *kernel_end)
  50. {
  51. extern unsigned long mem_size_limit;
  52. struct memclust_struct * cluster;
  53. struct memdesc_struct * memdesc;
  54. unsigned long start_kernel_pfn, end_kernel_pfn;
  55. unsigned long bootmap_size, bootmap_pages, bootmap_start;
  56. unsigned long start, end;
  57. unsigned long node_pfn_start, node_pfn_end;
  58. int i;
  59. unsigned long node_datasz = PFN_UP(sizeof(plat_pg_data_t));
  60. int show_init = 0;
  61. /* Find the bounds of current node */
  62. node_pfn_start = (nid * NODE_MAX_MEM_SIZE) >> PAGE_SHIFT;
  63. node_pfn_end = node_pfn_start + (NODE_MAX_MEM_SIZE >> PAGE_SHIFT);
  64. /* Find free clusters, and init and free the bootmem accordingly.  */
  65. memdesc = (struct memdesc_struct *)
  66.   (hwrpb->mddt_offset + (unsigned long) hwrpb);
  67. /* find the bounds of this node (min_low_pfn/max_low_pfn) */
  68. min_low_pfn = ~0UL;
  69. for_each_mem_cluster(memdesc, cluster, i) {
  70. /* Bit 0 is console/PALcode reserved.  Bit 1 is
  71.    non-volatile memory -- we might want to mark
  72.    this for later.  */
  73. if (cluster->usage & 3)
  74. continue;
  75. start = cluster->start_pfn;
  76. end = start + cluster->numpages;
  77. if (start >= node_pfn_end || end <= node_pfn_start)
  78. continue;
  79. if (!show_init) {
  80. show_init = 1;
  81. printk("Initialing bootmem allocator on Node ID %dn", nid);
  82. }
  83. printk(" memcluster %2d, usage %1lx, start %8lu, end %8lun",
  84.        i, cluster->usage, cluster->start_pfn,
  85.        cluster->start_pfn + cluster->numpages);
  86. if (start < node_pfn_start)
  87. start = node_pfn_start;
  88. if (end > node_pfn_end)
  89. end = node_pfn_end;
  90. if (start < min_low_pfn)
  91. min_low_pfn = start;
  92. if (end > max_low_pfn)
  93. max_low_pfn = end;
  94. }
  95. if (mem_size_limit && max_low_pfn >= mem_size_limit) {
  96. printk("setup: forcing memory size to %ldK (from %ldK).n",
  97.        mem_size_limit << (PAGE_SHIFT - 10),
  98.        max_low_pfn    << (PAGE_SHIFT - 10));
  99. max_low_pfn = mem_size_limit;
  100. }
  101. if (min_low_pfn >= max_low_pfn)
  102. return;
  103. num_physpages += max_low_pfn - min_low_pfn;
  104. /* Cute trick to make sure our local node data is on local memory */
  105. PLAT_NODE_DATA(nid) = (plat_pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
  106. /* Quasi-mark the plat_pg_data_t as in-use */
  107. min_low_pfn += node_datasz;
  108. if (min_low_pfn >= max_low_pfn) {
  109. printk(" not enough mem to reserve PLAT_NODE_DATA");
  110. return;
  111. }
  112. NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
  113. printk(" Detected node memory:   start %8lu, end %8lun",
  114.        min_low_pfn, max_low_pfn);
  115. DBGDCONT(" DISCONTIG: plat_node_data[%d]   is at 0x%pn", nid, PLAT_NODE_DATA(nid));
  116. DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%pn", nid, NODE_DATA(nid)->bdata);
  117. /* Find the bounds of kernel memory.  */
  118. start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
  119. end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
  120. bootmap_start = -1;
  121. if (!nid && (max_low_pfn < end_kernel_pfn || min_low_pfn > start_kernel_pfn))
  122. panic("kernel loaded out of ram");
  123. /* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned */
  124. min_low_pfn = (min_low_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1);
  125. /* We need to know how many physically contiguous pages
  126.    we'll need for the bootmap.  */
  127. bootmap_pages = bootmem_bootmap_pages(max_low_pfn-min_low_pfn);
  128. /* Now find a good region where to allocate the bootmap.  */
  129. for_each_mem_cluster(memdesc, cluster, i) {
  130. if (cluster->usage & 3)
  131. continue;
  132. start = cluster->start_pfn;
  133. end = start + cluster->numpages;
  134. if (start >= max_low_pfn || end <= min_low_pfn)
  135. continue;
  136. if (end > max_low_pfn)
  137. end = max_low_pfn;
  138. if (start < min_low_pfn)
  139. start = min_low_pfn;
  140. if (start < start_kernel_pfn) {
  141. if (end > end_kernel_pfn
  142.     && end - end_kernel_pfn >= bootmap_pages) {
  143. bootmap_start = end_kernel_pfn;
  144. break;
  145. } else if (end > start_kernel_pfn)
  146. end = start_kernel_pfn;
  147. } else if (start < end_kernel_pfn)
  148. start = end_kernel_pfn;
  149. if (end - start >= bootmap_pages) {
  150. bootmap_start = start;
  151. break;
  152. }
  153. }
  154. if (bootmap_start == -1)
  155. panic("couldn't find a contigous place for the bootmap");
  156. /* Allocate the bootmap and mark the whole MM as reserved.  */
  157. bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start,
  158.  min_low_pfn, max_low_pfn);
  159. DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lun",
  160.  bootmap_start, bootmap_size, bootmap_pages);
  161. /* Mark the free regions.  */
  162. for_each_mem_cluster(memdesc, cluster, i) {
  163. if (cluster->usage & 3)
  164. continue;
  165. start = cluster->start_pfn;
  166. end = cluster->start_pfn + cluster->numpages;
  167. if (start >= max_low_pfn || end <= min_low_pfn)
  168. continue;
  169. if (end > max_low_pfn)
  170. end = max_low_pfn;
  171. if (start < min_low_pfn)
  172. start = min_low_pfn;
  173. if (start < start_kernel_pfn) {
  174. if (end > end_kernel_pfn) {
  175. free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start),
  176.      (PFN_PHYS(start_kernel_pfn)
  177.       - PFN_PHYS(start)));
  178. printk(" freeing pages %ld:%ldn",
  179.        start, start_kernel_pfn);
  180. start = end_kernel_pfn;
  181. } else if (end > start_kernel_pfn)
  182. end = start_kernel_pfn;
  183. } else if (start < end_kernel_pfn)
  184. start = end_kernel_pfn;
  185. if (start >= end)
  186. continue;
  187. free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
  188. printk(" freeing pages %ld:%ldn", start, end);
  189. }
  190. /* Reserve the bootmap memory.  */
  191. reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size);
  192. printk(" reserving pages %ld:%ldn", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
  193. numnodes++;
  194. }
  195. void __init
  196. setup_memory(void *kernel_end)
  197. {
  198. int nid;
  199. show_mem_layout();
  200. numnodes = 0;
  201. for (nid = 0; nid < MAX_NUMNODES; nid++)
  202. setup_memory_node(nid, kernel_end);
  203. #ifdef CONFIG_BLK_DEV_INITRD
  204. initrd_start = INITRD_START;
  205. if (initrd_start) {
  206. initrd_end = initrd_start+INITRD_SIZE;
  207. printk("Initial ramdisk at: 0x%p (%lu bytes)n",
  208.        (void *) initrd_start, INITRD_SIZE);
  209. if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
  210. printk("initrd extends beyond end of memory "
  211.        "(0x%08lx > 0x%p)ndisabling initrdn",
  212.        initrd_end,
  213.        phys_to_virt(PFN_PHYS(max_low_pfn)));
  214. initrd_start = initrd_end = 0;
  215. } else {
  216. reserve_bootmem_node(NODE_DATA(KVADDR_TO_NID(initrd_start)),
  217.      virt_to_phys((void *)initrd_start),
  218.      INITRD_SIZE);
  219. }
  220. }
  221. #endif /* CONFIG_BLK_DEV_INITRD */
  222. }
  223. void __init paging_init(void)
  224. {
  225. unsigned int    nid;
  226. unsigned long   zones_size[MAX_NR_ZONES] = {0, };
  227. unsigned long dma_local_pfn;
  228. /*
  229.  * The old global MAX_DMA_ADDRESS per-arch API doesn't fit
  230.  * in the NUMA model, for now we convert it to a pfn and
  231.  * we interpret this pfn as a local per-node information.
  232.  * This issue isn't very important since none of these machines
  233.  * have legacy ISA slots anyways.
  234.  */
  235. dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
  236. for (nid = 0; nid < numnodes; nid++) {
  237. unsigned long start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT;
  238. unsigned long end_pfn = plat_node_bdata[nid].node_low_pfn;
  239. unsigned long lmax_mapnr;
  240. if (dma_local_pfn >= end_pfn - start_pfn)
  241. zones_size[ZONE_DMA] = end_pfn - start_pfn;
  242. else {
  243. zones_size[ZONE_DMA] = dma_local_pfn;
  244. zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
  245. }
  246. free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn<<PAGE_SHIFT, NULL);
  247. lmax_mapnr = PLAT_NODE_DATA_STARTNR(nid) + PLAT_NODE_DATA_SIZE(nid);
  248. if (lmax_mapnr > max_mapnr) {
  249. max_mapnr = lmax_mapnr;
  250. DBGDCONT("Grow max_mapnr to %ldn", max_mapnr);
  251. }
  252. }
  253. /* Initialize the kernel's ZERO_PGE. */
  254. memset((void *)ZERO_PGE, 0, PAGE_SIZE);
  255. }
  256. #define printkdot()
  257. do {
  258. if (!(i++ % ((100UL*1024*1024)>>PAGE_SHIFT)))
  259. printk(".");
  260. } while(0)
  261. #define clobber(p, size) memset((p)->virtual, 0xaa, (size))
  262. void __init mem_stress(void)
  263. {
  264. LIST_HEAD(x);
  265. LIST_HEAD(xx);
  266. struct page * p;
  267. unsigned long i = 0;
  268. printk("starting memstress");
  269. while ((p = alloc_pages(GFP_ATOMIC, 1))) {
  270. clobber(p, PAGE_SIZE*2);
  271. list_add(&p->list, &x);
  272. printkdot();
  273. }
  274. while ((p = alloc_page(GFP_ATOMIC))) {
  275. clobber(p, PAGE_SIZE);
  276. list_add(&p->list, &xx);
  277. printkdot();
  278. }
  279. while (!list_empty(&x)) {
  280. p = list_entry(x.next, struct page, list);
  281. clobber(p, PAGE_SIZE*2);
  282. list_del(x.next);
  283. __free_pages(p, 1);
  284. printkdot();
  285. }
  286. while (!list_empty(&xx)) {
  287. p = list_entry(xx.next, struct page, list);
  288. clobber(p, PAGE_SIZE);
  289. list_del(xx.next);
  290. __free_pages(p, 0);
  291. printkdot();
  292. }
  293. printk("I'm still alive duh!n");
  294. }
  295. #undef printkdot
  296. #undef clobber
  297. void __init mem_init(void)
  298. {
  299. unsigned long codesize, reservedpages, datasize, initsize, pfn;
  300. extern int page_is_ram(unsigned long) __init;
  301. extern char _text, _etext, _data, _edata;
  302. extern char __init_begin, __init_end;
  303. extern unsigned long totalram_pages;
  304. unsigned long nid, i;
  305. mem_map_t * lmem_map;
  306. high_memory = (void *) __va(max_mapnr <<PAGE_SHIFT);
  307. reservedpages = 0;
  308. for (nid = 0; nid < numnodes; nid++) {
  309. /*
  310.  * This will free up the bootmem, ie, slot 0 memory
  311.  */
  312. totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
  313. lmem_map = NODE_MEM_MAP(nid);
  314. pfn = NODE_DATA(nid)->node_start_paddr >> PAGE_SHIFT;
  315. for (i = 0; i < PLAT_NODE_DATA_SIZE(nid); i++, pfn++)
  316. if (page_is_ram(pfn) && PageReserved(lmem_map+i))
  317. reservedpages++;
  318. }
  319. codesize =  (unsigned long) &_etext - (unsigned long) &_text;
  320. datasize =  (unsigned long) &_edata - (unsigned long) &_data;
  321. initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
  322. printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, "
  323. "%luk data, %luk init)n",
  324.        nr_free_pages() << (PAGE_SHIFT-10),
  325.        num_physpages << (PAGE_SHIFT-10),
  326.        codesize >> 10,
  327.        reservedpages << (PAGE_SHIFT-10),
  328.        datasize >> 10,
  329.        initsize >> 10);
  330. #if 0
  331. mem_stress();
  332. #endif
  333. }
  334. void
  335. show_mem(void)
  336. {
  337. long i,free = 0,total = 0,reserved = 0;
  338. long shared = 0, cached = 0;
  339. int nid;
  340. printk("nMem-info:n");
  341. show_free_areas();
  342. printk("Free swap:       %6dkBn",nr_swap_pages<<(PAGE_SHIFT-10));
  343. for (nid = 0; nid < numnodes; nid++) {
  344. mem_map_t * lmem_map = NODE_MEM_MAP(nid);
  345. i = PLAT_NODE_DATA_SIZE(nid);
  346. while (i-- > 0) {
  347. total++;
  348. if (PageReserved(lmem_map+i))
  349. reserved++;
  350. else if (PageSwapCache(lmem_map+i))
  351. cached++;
  352. else if (!page_count(lmem_map+i))
  353. free++;
  354. else
  355. shared += atomic_read(&lmem_map[i].count) - 1;
  356. }
  357. }
  358. printk("%ld pages of RAMn",total);
  359. printk("%ld free pagesn",free);
  360. printk("%ld reserved pagesn",reserved);
  361. printk("%ld pages sharedn",shared);
  362. printk("%ld pages swap cachedn",cached);
  363. printk("%ld pages in page table cachen",pgtable_cache_size);
  364. show_buffers();
  365. }