Почему мой модуль не может обработать пейджинговый запрос ядра? - PullRequest
9 голосов
/ 23 ноября 2011

Это мой модуль для выделения одной огромной страницы с помощью dequeue_huge_page_vma () и alloc_buddy_huge_page (). Чтобы сделать их независимыми от vma, я могу получить доступ к vm area из __get_vm_area_node (), а затем получить его виртуальный адрес. Я хочу выделить одну страницу размером 2 МБ, однако ядро ​​говорит:

[   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 

Мой код:

/*
 * 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");

1 Ответ

0 голосов
/ 25 сентября 2015

Это действительно старый вопрос, но какого чёрта ...

__ get_vm_area_node () может возвращать NULL по нескольким причинам, вы безоговорочно задерживаете его возвращаемое значение.Это неразумно.

...