免费注册 查看新帖 |

Chinaunix

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

[内存管理] X86-64平台上的memmap&ioremap出的内存相关 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-08-14 10:39 |只看该作者 |倒序浏览
本帖最后由 kirapangzi 于 2013-08-27 17:03 编辑

自二楼指出我理解混淆后,决定深究源码,找出问题所在。

概括下我的问题:怎样才能获取到这样一段内存的page*描述符?——它经由memmap启动参数保留,然后再ioremap出来独自管理。

依照源码所在,分拆开来:
首先,申明环境与内核版本:Fedora 18,3.6.11,X86-64
1,memmap参数所保留的内存,内核启动时,有没有建立page*结构,来描述它?
a,内核启动后,调用setup_arch->setup_memory_map建立内核的e820表,然后parse_early_param->parse_memmap_opt解析memmap=x$y参数,将对应的物理地址范围修改为E820_RESERVED。
b,memblock_x86_fill将e820表中类型为E820_RAM|E820_RESERVED_KERN建立mem_block;
c,paging_init->sparse_memory_present_with_active_regions中,依照上述mem_block中的区域,填充mem_section全局数组;
d,paging_init->sparse_init->sparse_early_mem_maps_alloc_node中,对当前numa nodeid中每个mem_section做page *初始化;
——终于找到重点了,在这个调用路径中,下述代码申请了section中的struct page结构的物理空间,而后以虚拟地址起始为vmemmap(ffffea0000000000)起,通过建立页表项,映射到这些page结构的物理地址;
  1.         unsigned long pnum;
  2.         unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;
  3.         void *vmemmap_buf_start;

  4.         size = ALIGN(size, PMD_SIZE);
  5.         vmemmap_buf_start = __earlyonly_bootmem_alloc(nodeid, size * map_count,
  6.                          PMD_SIZE, __pa(MAX_DMA_ADDRESS));

  7.         if (vmemmap_buf_start) {
  8.                 vmemmap_buf = vmemmap_buf_start;
  9.                 vmemmap_buf_end = vmemmap_buf_start + size * map_count;
  10.         }
复制代码
总结:很明显的,在内核最终e820表被设置为reserved类型的物理地址空间,肯定是没有建立上述page结构。

一篇不错的SPARSEMEM介绍文章:http://wangcong.org/blog/archives/2043

2,ioremap时,有没有涉及到对这段物理地址空间的page*结构操作?
走读源码路径:__ioremap_caller->ioremap_page_range->...->ioremap_pte_range;该函数中,是针对指定的phys_addr构建的pte。
总结:ioremap指定的物理内存,在ioremap的整个调用完成后,内核也没有为这片物理内存建立struct page的管理结构;而只是建立了virt<->phys这样的一个转换关系;

3,如果采用vmalloc_to_page获取到的page*,到底是何时建立的?
走读源码:通过virt_addr walk到pte、pfn后,通过pfn_to_page宏获取到page *虚拟地址;也就是从前述vmemmap空间中直接线性偏移获取一个虚拟地址返回;
如果vmalloc_to_page函数传入的虚拟地址,内核没有建立page结构的话,此时,page*仅仅只是一个虚拟地址、指针而已,而没有实际的指向page结构;

那为何将这个page *赋值到bio下发后,底层驱动反而可以正常工作呢?此处感觉是因为scsi、ata层其实不会去更改page 结构里面的具体数值,而只是通过page *虚拟地址再次获取到phys而已;

浏览代码初步验证:
1,block lld:调用blk_rq_map_sg->..->sg_set_page;将page*转换为sg->page_link;
2,ata lld/sas lld:调用dma_map_sg->...->sg_phys;将sg->page_link转换成page*,再获取到真实的物理地址用作dma;

-------------------------------------------------------------------------------------分割线(下面是旧帖,错误的内容已经删除)

与X86-64相关的:
1,当系统没有了Highmem后,vmalloc的作用仅体现在将不连续的物理区映射为连续的virt地址;且是以page为最小单位的;

2,vmalloc、进程的空间申请,都是打乱原有virt<->phys,线性映射关系,重新建立页表项映射的过程;

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
2 [报告]
发表于 2013-08-18 14:37 |只看该作者
感觉楼主理解的各种混淆。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
3 [报告]
发表于 2013-08-19 14:14 |只看该作者
回复 2# embeddedlwp
感觉楼主理解的各种混淆。


呵呵。WP兄,给斧正一下

   

论坛徽章:
0
4 [报告]
发表于 2013-08-19 17:58 |只看该作者
最简单的办法是 改e820 表,这样 保留内存不进入 系统内存视图,然后再ioremap。

论坛徽章:
0
5 [报告]
发表于 2013-08-20 14:06 |只看该作者
回复 2# embeddedlwp

还请指正一下啊!

   

论坛徽章:
0
6 [报告]
发表于 2013-08-20 14:13 |只看该作者
superwiles 发表于 2013-08-19 17:58
最简单的办法是 改e820 表,这样 保留内存不进入 系统内存视图,然后再ioremap。


使用memmap=x$y指定的物理内存,是没有进入OS内存视图的啊;请问你说的改e820表,是怎么改呢?可以达到怎样的效果呢?

论坛徽章:
0
7 [报告]
发表于 2013-08-24 17:40 |只看该作者
自己顶一下,希望各位牛人能不吝赐教啊。

论坛徽章:
0
8 [报告]
发表于 2013-08-27 17:05 |只看该作者
花了几天时间来走读源码,得出了贴子中的结论。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP