C 为什么我的模块无法处理内核分页请求?

C 为什么我的模块无法处理内核分页请求?,c,memory-management,linux-kernel,kernel-module,virtual-memory,C,Memory Management,Linux Kernel,Kernel Module,Virtual Memory,这是我的模块,通过使用dequeue_hug_page_vma()和alloc_buddy_hug_page()分配一个大页面。为了使它们独立于vma,我从u get_vm_area_node()获取可用的vm区域,然后获取其虚拟地址。我想分配一个2MB页面,但是内核说: [ 84.944634] BUG: unable to handle kernel paging request at ffffc90013d02000 [ 84.944641] IP: [<ffffffffa0

这是我的模块,通过使用dequeue_hug_page_vma()和alloc_buddy_hug_page()分配一个大页面。为了使它们独立于vma,我从u get_vm_area_node()获取可用的vm区域,然后获取其虚拟地址。我想分配一个2MB页面,但是内核说:

[   84.944634] BUG: unable to handle kernel paging request at ffffc90013d02000
[   84.944641] IP: [<ffffffffa0ac9063>] vma_null_test+0x63/0xa3 [vma_null_test]
[   84.944650] PGD bd019067 PUD bd01a067 PMD b35c0067 PTE 0
[   84.944657] Oops: 0000 [#1] SMP 
[84.944634]错误:无法处理ffffc90013d02000上的内核分页请求
[84.944641]IP:[]vma_空_测试+0x63/0xa3[vma_空_测试]
[84.944650]PGD bd019067 PUD bd01a067 PMD b35c0067 PTE 0
[84.944657]Oops:0000[#1]SMP
我的代码:

/*
 * vma_null_test.c - Cindy: to test if vma can be set to NULL in alloc_huge_page() 
 */

 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/hugetlb.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <asm/page.h>
 #include <linux/nodemask.h>
 #include <linux/gfp.h>
 #include <linux/mm_types.h>
 #include <asm-generic/pgtable.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
 #define TWO_MB 0x200000

struct hstate *h;

struct vm_struct *__get_vm_area_node(unsigned long size,
            unsigned long align, unsigned long flags, unsigned long start,
            unsigned long end, int node, gfp_t gfp_mask, void *caller);

struct page *dequeue_huge_page_vma(struct hstate *,struct vm_area_struct *,
            unsigned long, int);

struct page *alloc_buddy_huge_page(struct hstate *,struct vm_area_struct *,
                            unsigned long);

struct page *alloc_huge_page_node_mod(unsigned long vaddr)
{
struct page *page;

page = dequeue_huge_page_vma(h, NULL, vaddr, 0);

if (!page)
    page = alloc_buddy_huge_page(h, NULL, vaddr);

return page;
}

static int __init vma_null_test(void)
{
  struct vm_struct *area;
  h=&default_hstate;
  unsigned long *address;
  struct page *page;
  int ret;

  area=__get_vm_area_node(TWO_MB, 1, VM_ALLOC, VMALLOC_START, VMALLOC_END, -1,   GFP_KERNEL|__GFP_HIGHMEM, __builtin_return_address(0));
  address=(unsigned long *)area->addr;
  page=alloc_huge_page_node_mod(*address);
  if(IS_ERR(page)){
  ret=-PTR_ERR(page);
  printk(KERN_ERR "Cannot allocate page\n");

  }
  else{
  ret=0;
  printk(KERN_ERR "Allocate one huge page at virtual address:%x\n",*address);
  }

  return ret;
}

static void __exit vma_null_exit(void)
{
  printk(KERN_ERR ".............Exit..........\n");
}

module_init(vma_null_test);
module_exit(vma_null_exit);
MODULE_LICENSE("GPL");
/*
*c-Cindy:在alloc_页面()中测试vma是否可以设置为null
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义两个_MB 0x200000
结构hstate*h;
struct vm\u struct*\u get\u vm\u area\u节点(无符号长大小,
无符号长对齐、无符号长标志、无符号长起始、,
无符号长端、int节点、gfp_t gfp_掩码、void*调用者);
结构页面*出列大型页面\u vma(结构状态*,结构虚拟区域\u结构*,
无符号长,int);
结构页面*alloc\u buddy\u巨大页面(结构状态*,结构虚拟区域*,
无符号长);
结构页*alloc\u巨型\u页\u节点\u模块(无符号长vaddr)
{
结构页面*页面;
page=dequeue_-page_-vma(h,NULL,vaddr,0);
如果(!第页)
page=alloc\u buddy\u hug\u page(h,NULL,vaddr);
返回页面;
}
静态整数初始化vma\U空值测试(无效)
{
结构vm_结构*区域;
h=&default_hstate;
无符号长*地址;
结构页面*页面;
int ret;
area=uu get_vm_area_节点(两个字节,1,vm_ALLOC,VMALLOC_开始,VMALLOC_结束,-1,GFP_内核| uu GFP_高内存,uu内置返回_地址(0));
地址=(无符号长*)区域->地址;
页面=所有页面节点模块(*地址);
如果(是否有错误(第页)){
ret=-PTR_ERR(第页);
printk(KERN_ERR“无法分配页面”\n);
}
否则{
ret=0;
printk(KERN_ERR“在虚拟地址分配一个大页面:%x\n”,*地址);
}
返回ret;
}
静态无效退出vma\U无效退出(无效)
{
printk(KERN_ERR“……退出………\n”);
}
模块初始化(vma_null_测试);
模块退出(vma\U null\U退出);
模块许可证(“GPL”);

这是一个非常古老的问题,但到底是什么


__get_vm_area_node()可以返回NULL,原因有几个,您可以无条件地遵从其返回值。这是不明智的。

在每条语句后添加一条printk语句,看看它在哪里崩溃。此外,您还可以尝试将调试符号加载到调试器中,并检查其崩溃的位置。并从碰撞报告中粘贴更多信息。应该有比你包括的更多的。你能提供区域对象的转储吗?