0

我参考以下两个链接在我的 linux 驱动程序中使用大页面:

在内核驱动程序http://nuncaalaprimera.com/2014/using-hugepage-backed-buffers-in-linux-kernel-driver中顺序访问大页面

下面是我的代码:

#define PAGE_SHIFT_2M   21
pages = vmalloc(nr_pages * sizeof(struct page*));

down_read(&current->mm->mmap_sem);
get_nr_pages = get_user_pages(current, current->mm, buffer_start, nr_pages,
    1 /* Write enable */, 0 /* Force */, pages, NULL);
up_read(&current->mm->mmap_sem);

nid = page_to_nid(pages[0]);    // Remap on the same NUMA node.
remapped_addr = vm_map_ram(pages, nr_pages, nid, PAGE_KERNEL);

printf("page pfn [0]=%lX, [1]=0x%lX, [2]=0x%lX\n", 
    page_to_pfn(pages[0]), 
    page_to_pfn(pages[1]),
    page_to_pfn(pages[2]));
printf("page physical [0]=%lX, [1]=0x%lX, [2]=0x%lX\n", 
    page_to_pfn(pages[0])<<PAGE_SHIFT_2M, 
    page_to_pfn(pages[1])<<PAGE_SHIFT_2M,
    page_to_pfn(pages[2])<<PAGE_SHIFT_2M);
printf("page logical addr [0]=%p, [1]=%p, [2]=%p\n", 
    __va(page_to_pfn(pages[0])<<PAGE_SHIFT_2M), 
    __va(page_to_pfn(pages[1])<<PAGE_SHIFT_2M),
    __va(page_to_pfn(pages[2])<<PAGE_SHIFT_2M));
printf("page_address [0]=%p, [1]=%p, [2]=%p\n", 
    page_address(pages[0]), 
    page_address(pages[1]),
    page_address(pages[2]));

日志打印:

页 pfn [0]=154A00, [1]=0x154A01, [2]=0x154A02
页物理 [0]=2A940000000, [1]=0x2A940200000, [2]=0x2A940400000
页逻辑地址 [0]=ffff8aa940000000, [1] =ffff8aa940200000, [2]=ffff8aa940400000
page_address [0]=ffff880154a00000, [1]=ffff880154a01000, [2]=ffff880154a02000

我有几个问题:
1)我想知道 vm_map_ram() 是否可以处理大页面。从内核源代码中,我可以看到 vm_map_ram() 使用 PAGE_SIZE 和 PAGE_SHIFT,它的值应该是默认的 4KB 页面大小。就我而言,在写入从 vm_map_ram() 返回的虚拟地址后,我遇到了“BUG:无法在 XXXX 处处理内核分页请求”问题。
2) 两个页面的 page_address 返回值为 0x1000(4KB) 间隙,而不是 2MB 间隙。这是为什么?
3) 我是否正确使用了 "__va(page_to_pfn(pages[0])<

提前致谢!

4

0 回答 0