- 论坛徽章:
- 0
|
本帖最后由 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结构的物理地址;- unsigned long pnum;
- unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;
- void *vmemmap_buf_start;
- size = ALIGN(size, PMD_SIZE);
- vmemmap_buf_start = __earlyonly_bootmem_alloc(nodeid, size * map_count,
- PMD_SIZE, __pa(MAX_DMA_ADDRESS));
- if (vmemmap_buf_start) {
- vmemmap_buf = vmemmap_buf_start;
- vmemmap_buf_end = vmemmap_buf_start + size * map_count;
- }
复制代码 总结:很明显的,在内核最终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,线性映射关系,重新建立页表项映射的过程; |
|