|
发表于 2009-6-17 09:09:09
|
显示全部楼层
remap_pfn_range 通过你的页帧号来建立页表, 并映射到用户空间!
一般情况是你的驱动分配一块内存,然后在驱动的mmap中使用这块内存的 物理地址转成页帧号, 再调用remap_pfn_range!
假设1你是通过kmalloc(),get_free_pages()等分配的,这种内存页是不能通过remap_pfn_range()映射出去的,要对每个页面调用SetPageReserverd()标记为“保留”才可以,virt_to_phys()函数只是得到其物理地址,remap_pfn_range()中的第三个参数是要求物理页便的“帧”号,即pfn,所以你的phys还要“> > PAGE_SHIFT”操作
假设2你是通过vmalloc分配得来的,同上,不同的是要用vmalloc_to_pfn
3,用kmalloc,get_free_pages,vmalloc分配的物理内存页面最好还是不要用remap_pfn_page方法,建议使用VMA的nopage方法
4,对于这样的设备内存,最好对调用pgprot_nocached(vma-> vm_page_prot)后传给remap_pfn_range,防止处理器缓存
5,你写的是framebuffer驱动,最好是用fb_mmap(),可扩展
static int mmap_xxxxx(struct file *filp, struct vm_area_struct *vma)
{
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
if(size > MMAP_MEM_SIZE)
return -EINVAL;
printk( "start=0x%08x offset=0x%08x\n", start, offset );
printk( "kernel msg=%s\n", mmap_buf );
pos = (unsigned long)mmap_buf + offset;
page = virt_to_phys( pos ) >> PAGE_SHIFT ;
if ( remap_pfn_range( vma, start, page, size, PAGE_SHARED )) {
return -EAGAIN;
}
else {
printk( "remap_pfn_range %u\n success\n", page );
}
vma->vm_flags &= ~VM_IO;
vma->vm_flags |= VM_RESERVED;
return 0;
} |
|