2.6.18核心和2.6.25以後核心remap_pfn_range()對kmalloc()到的區別

來源:互聯網
上載者:User
對於2.6.25以上核心,直接調用
vma->vm_flags |= VM_SHARED | VM_RESERVED;
io_remap_pfn_range(vma, vma->vm_start, phy_addr >> PAGE_SHIFT,
                 vma->vm_end - vma->vm_start, vma->vm_page_prot);

但是2.6.18核心就必須按照下面的步驟來完成映射
對於2.6.18核心使用如下方法的驅動執行個體可以參考2.6.18.5核心源碼
sound/oss/i810_audio.c|1044| SetPageReserved(page);
alloc_dmabuf {
    /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
    pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
    for (page = virt_to_page(rawbuf); page <= pend; page++)
        SetPageReserved(page);
}
dealloc_dmabuf {
    for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
            ClearPageReserved(page);
}
static int i810_mmap(struct file *file, struct vm_area_struct *vma)
{
    if (remap_pfn_range(vma, vma->vm_start,
                 virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
                 size, vma->vm_page_prot))
}
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;
}
還有就是
offset參數右移PAGE_SHIFT
就是得到頁幀號, 前提是offset 是核心物理地址!
kmalloc, get_free_pages都可以通過 virt_to_phy取得
vmalloc 可以通過page_address( vmalloc_to_page( addr ) )取得

 

 原文地址 http://www.linuxsir.org/bbs/thread349986.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.