remap_pfn_range、vm_pgoff、pfn
http://linux.chinaunix.net/bbs/archiver/tid-900802-page-2.htmlhttp://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=651015&page=0&view=collapsed&sb=5&o=7&fpart=1. vma->vm_pgoff 是
·
http://linux.chinaunix.net/bbs/archiver/tid-900802-page-2.html
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=651015&page=0&view=collapsed&sb=5&o=7&fpart=
1. vma->vm_pgoff 是 该vm 区域在map file中的以PAGE大小为单位的偏移。/* Offset (within vm_file) in PAGE_SIZE*/
比如4个vm_area MAP到一个文件的
1)0-----4096
2)5*4096 ------ 7*4096
3)9*4096 ------ 10*4096
4)15*4096 ----- 20*4096
那么4个vma的vm_pgoff分别为0,5,9, 15
本来和物理页号没有关系。
你们看到的和物理页号关系是一种特例和巧合
2, remap_pfn_range 函数是被驱动调用(cd drivers grep -r remap_pfn * )
用来将"所有"物理内存影射成一个文件中(driver/mem.c 参见)。
这时候,vm_pgoff就和物理PAGE号有关系了。是特例和巧合。
vm_pgoff的本意和物理PAGE号无关。
就是我上贴说的定义(看mm.h 一句话的说明: Offset (within vm_file) in PAGE_SIZE)
3. drivers/char/mem.c
static int mmap_mem(struct file *file, struct vm_area_struct *vma)
{
size_t size = vma->vm_end - vma->vm_start;
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
return -EINVAL;
if (!private_mapping_ok(vma))
return -ENOSYS;
if (!range_is_allowed(vma->vm_pgoff, size))
return -EPERM;
if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
&vma->vm_page_prot))
return -EINVAL;
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
size,
vma->vm_page_prot);
vma->vm_ops = &mmap_mem_ops;
/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
size,
vma->vm_page_prot)) {
return -EAGAIN;
}
return 0;
}
#ifdef CONFIG_DEVKMEM
static int mmap_kmem(struct file *file, struct vm_area_struct *vma)
{
unsigned long pfn;
/* Turn a kernel-virtual address into a physical page frame */
pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
/*
* RED-PEN: on some architectures there is more mapped memory than
* available in mem_map which pfn_valid checks for. Perhaps should add a
* new macro here.
*
* RED-PEN: vmalloc is not supported right now.
*/
if (!pfn_valid(pfn))
return -EIO;
vma->vm_pgoff = pfn;
return mmap_mem(file, vma);
}
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=651015&page=0&view=collapsed&sb=5&o=7&fpart=
1. vma->vm_pgoff 是 该vm 区域在map file中的以PAGE大小为单位的偏移。/* Offset (within vm_file) in PAGE_SIZE*/
比如4个vm_area MAP到一个文件的
1)0-----4096
2)5*4096 ------ 7*4096
3)9*4096 ------ 10*4096
4)15*4096 ----- 20*4096
那么4个vma的vm_pgoff分别为0,5,9, 15
本来和物理页号没有关系。
你们看到的和物理页号关系是一种特例和巧合
2, remap_pfn_range 函数是被驱动调用(cd drivers grep -r remap_pfn * )
用来将"所有"物理内存影射成一个文件中(driver/mem.c 参见)。
这时候,vm_pgoff就和物理PAGE号有关系了。是特例和巧合。
vm_pgoff的本意和物理PAGE号无关。
就是我上贴说的定义(看mm.h 一句话的说明: Offset (within vm_file) in PAGE_SIZE)
3. drivers/char/mem.c
static int mmap_mem(struct file *file, struct vm_area_struct *vma)
{
size_t size = vma->vm_end - vma->vm_start;
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
return -EINVAL;
if (!private_mapping_ok(vma))
return -ENOSYS;
if (!range_is_allowed(vma->vm_pgoff, size))
return -EPERM;
if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
&vma->vm_page_prot))
return -EINVAL;
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
size,
vma->vm_page_prot);
vma->vm_ops = &mmap_mem_ops;
/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
size,
vma->vm_page_prot)) {
return -EAGAIN;
}
return 0;
}
#ifdef CONFIG_DEVKMEM
static int mmap_kmem(struct file *file, struct vm_area_struct *vma)
{
unsigned long pfn;
/* Turn a kernel-virtual address into a physical page frame */
pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
/*
* RED-PEN: on some architectures there is more mapped memory than
* available in mem_map which pfn_valid checks for. Perhaps should add a
* new macro here.
*
* RED-PEN: vmalloc is not supported right now.
*/
if (!pfn_valid(pfn))
return -EIO;
vma->vm_pgoff = pfn;
return mmap_mem(file, vma);
}
更多推荐
已为社区贡献7条内容
所有评论(0)