“DevMem note”的版本间的差异

来自个人维基
跳转至: 导航搜索
第1行: 第1行:
 +
<source lang="awk">
 +
devmem ADDRESS [WIDTH [VALUE]]
 +
Read/write from physical address
 +
 +
        ADDRESS Address to act upon
 +
        WIDTH  Width (8/16/...)
 +
        VALUE  Data to be written
 +
 +
</source>
 
<source lang="c">
 
<source lang="c">
 
#include <sys/mman.h>
 
#include <sys/mman.h>
第23行: 第32行:
 
|}
 
|}
  
 +
 +
/dev/mem mmap operator:
 +
<source lang="c">
 +
static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 +
{
 +
    size_t size = vma->vm_end - vma->vm_start;
 +
    phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
 +
 +
    /* It's illegal to wrap around the end of the physical address space. */
 +
    if (offset + (phys_addr_t)size - 1 < offset)
 +
        return -EINVAL;
 +
 +
    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 */
 +
    if (remap_pfn_range(vma,---------------------------------------------将内核中vma->vm_pgoff对应的size个页面,映射到vma区域,返回的虚拟空间起始地址是vma->vm_start。
 +
                vma->vm_start,
 +
                vma->vm_pgoff,
 +
                size,
 +
                vma->vm_page_prot)) {
 +
        return -EAGAIN;
 +
    }
 +
    return 0;
 +
}
 +
</source>
  
 
vm_area_struct结构体
 
vm_area_struct结构体

2019年11月5日 (二) 15:34的版本

devmem ADDRESS [WIDTH [VALUE]]
Read/write from physical address
 
        ADDRESS Address to act upon
        WIDTH   Width (8/16/...)
        VALUE   Data to be written
#include <sys/mman.h>
 
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

详细参数如下:

参数 详细说明
addr 需要映射的虚拟内存地址;如果为NULL,系统会自动选定。映射成功后返回该地址
length 需要映射多大的数据量
prot 描述映射区域内存保护方式,包括:PROT_EXEC、PROT_READ、PROT_WRITE、PROT_NONE.
flags 描述映射区域的特性,比如是否对其他进程共享,是否建立匿名映射,是否创建私有的cow.
fd 要映射到内存中的文件描述符
offset 文件映射的偏移量


/dev/mem mmap operator:

static int mmap_mem(struct file *file, struct vm_area_struct *vma)
{
    size_t size = vma->vm_end - vma->vm_start;
    phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
 
    /* It's illegal to wrap around the end of the physical address space. */
    if (offset + (phys_addr_t)size - 1 < offset)
        return -EINVAL;
 
    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 */
    if (remap_pfn_range(vma,---------------------------------------------将内核中vma->vm_pgoff对应的size个页面,映射到vma区域,返回的虚拟空间起始地址是vma->vm_start。
                vma->vm_start,
                vma->vm_pgoff,
                size,
                vma->vm_page_prot)) {
        return -EAGAIN;
    }
    return 0;
}

vm_area_struct结构体