linux remap_pfn_range、vm_pgoff、pfn

原文地址:https://blog.csdn.net/hshl1214/article/details/8789507

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);
}

你可能感兴趣的:(linux驱动,linux,remap_pfn_range,vm_pgoff)