免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2128 | 回复: 3
打印 上一主题 下一主题

[内核入门] 请教2.6.24版本的discontig_32.c中的setup_memory()普通和高端内存边界问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-04-04 12:05 |只看该作者 |倒序浏览
本帖最后由 aweii 于 2013-04-04 12:43 编辑

注释说分配node_mem_map 并留出映射页的空间后,需要调整ZONE_NORMAL和ZONE_HIGHMEM之间的边界,我怎么没见max_low_pfn有调整呢?按理说返回的max_low_pfn应该减去kva_pages 啊。该函数最后setup_bootmem_allocator()调用了numa_kva_reserve()把kva_start_pfn~max_low_pfn这段物理内存保留而不参与分配了,为什么不把这段内存也归入高端内存分配而浪费掉呢?
  1. unsigned long __init setup_memory(void)
  2. {
  3.         int nid;
  4.         unsigned long system_start_pfn, system_max_low_pfn;

  5.         /*
  6.          * When mapping a NUMA machine we allocate the node_mem_map arrays
  7.          * from node local memory.  They are then mapped directly into KVA
  8.          * between zone normal and vmalloc space.  Calculate the size of
  9.          * this space and use it to adjust the boundary between ZONE_NORMAL
  10.          * and ZONE_HIGHMEM.
  11.          */
  12.         find_max_pfn();
  13.         get_memcfg_numa();

  14.         kva_pages = calculate_numa_remap_pages();//这里计算出重映射的页数

  15.         /* partially used pages are not usable - thus round upwards */
  16.         system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end);

  17.         kva_start_pfn = find_max_low_pfn() - kva_pages;//重映射区的地址页号,max_low_pfn应该也到这里吧,往上都作为high_memory

  18. #ifdef CONFIG_BLK_DEV_INITRD
  19.         /* Numa kva area is below the initrd */
  20.         if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image)
  21.                 kva_start_pfn = PFN_DOWN(boot_params.hdr.ramdisk_image)
  22.                         - kva_pages;
  23. #endif
  24.         kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1);

  25.         system_max_low_pfn = max_low_pfn = find_max_low_pfn();//max_low_pfn = find_max_low_pfn();为啥没有考虑减去kva_pages

  26.         printk("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n",
  27.                 kva_start_pfn, max_low_pfn);
  28.         printk("max_pfn = %ld\n", max_pfn);
  29. #ifdef CONFIG_HIGHMEM
  30.         highstart_pfn = highend_pfn = max_pfn;
  31.         if (max_pfn > system_max_low_pfn)
  32.                 highstart_pfn = system_max_low_pfn;
  33.         printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
  34.                pages_to_mb(highend_pfn - highstart_pfn));
  35.         num_physpages = highend_pfn;
  36.         high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
  37. #else
  38.         num_physpages = system_max_low_pfn;
  39.         high_memory = (void *) __va(system_max_low_pfn * PAGE_SIZE - 1) + 1;
  40. #endif
  41.         printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
  42.                         pages_to_mb(system_max_low_pfn));
  43.         printk("min_low_pfn = %ld, max_low_pfn = %ld, highstart_pfn = %ld\n",
  44.                         min_low_pfn, max_low_pfn, highstart_pfn);

  45.         printk("Low memory ends at vaddr %08lx\n",
  46.                         (ulong) pfn_to_kaddr(max_low_pfn));
  47.         for_each_online_node(nid) {
  48.                 node_remap_start_vaddr[nid] = pfn_to_kaddr(
  49.                                 kva_start_pfn + node_remap_offset[nid]);
  50.                 /* Init the node remap allocator */
  51.                 node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
  52.                         (node_remap_size[nid] * PAGE_SIZE);
  53.                 node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
  54.                         ALIGN(sizeof(pg_data_t), PAGE_SIZE);

  55.                 allocate_pgdat(nid);
  56.                 printk ("node %d will remap to vaddr %08lx - %08lx\n", nid,
  57.                         (ulong) node_remap_start_vaddr[nid],
  58.                         (ulong) pfn_to_kaddr(highstart_pfn
  59.                            + node_remap_offset[nid] + node_remap_size[nid]));
  60.         }
  61.         printk("High memory starts at vaddr %08lx\n",
  62.                         (ulong) pfn_to_kaddr(highstart_pfn));
  63.         for_each_online_node(nid)
  64.                 find_max_pfn_node(nid);

  65.         memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
  66.         NODE_DATA(0)->bdata = &node0_bdata;
  67.         setup_bootmem_allocator();
  68.         return max_low_pfn;
  69. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-04-09 10:24 |只看该作者
没有你那个版本的化代码,新版本的处理已经有所变化了,但是大同小异。

想了一下,假如按你说的:不浪费那些内存,拉低max_low_pfn,实现起来还是有些问题的。

1,跑到这个位置时,内核的低端内存的固定一致映射页面已经创建起来了,这个映射是要依赖于max_low_pfn的,映射创建后把max_low_pfn拉低,意味着内核给这段高端内存创建了一致映射。这还不是问题的关键所在,问题在于max_low_pfn变化以后,内核能直接访问的线性地址和HOLE以及VMALLOC等使用的线性地址比例会发生变化,也就是说,如果把calculate_numa_remap_pages()算出的这些页面空间变成高端内存,那么这些内存原来的线性地址(va(x))能被内核直接访问的条提条件已被打破,这些线性地址就不能被直接访问了,而是vmalloc()的返回后才行。。。说白了,现在之所以在低端内存申请这些内存,并不是真的需要物理内存,而是需要它的线性地址(含有低端内存的node相应的空间除外,其它各node是要从它们自己的内存段分配内存,重新映射到这个上面来的。)

所以这些说得不好听是被浪费,说得好听点,是需要他们来“占位”的,因为他们有直接访问的线性地址名额。

2,如果这些内存真要被使用,只能以高端内存的使用方式,重新申请线性地址后映射再使用。但怎么管理它们,是个问题,估计得重新写一套机制。

论坛徽章:
0
3 [报告]
发表于 2013-04-09 20:39 |只看该作者
本帖最后由 aweii 于 2013-04-09 20:47 编辑

回复 2# 鸟菜小


    正是因为这段地址被remap到其它内存了,一对一的直接映射被打破。我才疑惑原来被映射的内存为什么不归到high_memory里去。另外注释也说了要调整ZONE_NORMAL和ZONE_HIGHMEM的边界(Calculate the size of this space and use it to adjust the boundary between ZONE_NORMAL and ZONE_HIGHMEM),但怎么不见调整的代码呢?

论坛徽章:
0
4 [报告]
发表于 2013-04-11 16:04 |只看该作者
回复 3# aweii


    看下free_area_init_nodes和find_zone_movable_pfns_for_nodes,主要是后者。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP