Chinaunix

标题: linux x86内存分页时,pgd与cr3的疑问 [打印本页]

作者: superwujc    时间: 2016-06-06 13:50
标题: linux x86内存分页时,pgd与cr3的疑问
请教各位高手

每个进程都有独立的PGD,保存在当前进程的内存描述符mm_struct的pgd字段中,而该字段的值是从cr3中加载

但我通过运行以下内核模块,打印cr3与pgd的值时,发现二者并不一致
  1. #include <linux/kernel.h>  
  2. #include <linux/module.h>  
  3. #include <linux/init.h>  
  4. #include <linux/mm.h>  
  5. #include <linux/mm_types.h>  
  6. #include <asm/pgtable.h>  
  7. #include <linux/vmalloc.h>  
  8. #include <linux/sched.h>  

  9. static int __init show_pgd(void)
  10. {
  11.         unsigned long cr3, pgd_entry_index;
  12.         struct mm_struct *mm;
  13.         pgd_t *pgdir, *pgd_entry;
  14.         unsigned long vaddr = 0;
  15.         vaddr = (unsigned long)vmalloc(1000 * sizeof(char));
  16.         if (vaddr == 0) {
  17.                 printk("vmalloc failed..\n");
  18.                 return -1;
  19.         }
  20.         printk("vmalloc_vaddr=0x%lx\n", vaddr);

  21.         cr3 = read_cr3();
  22.         mm = current->mm;
  23.         pgdir = mm->pgd;
  24.         pgd_entry = pgd_offset(current->mm, vaddr);
  25.         pgd_entry_index = pgd_index(vaddr);

  26.         printk("cr3 = 0x%lx\n", cr3);
  27.         printk("pgdir = 0x%lx\n", pgd_val(*pgdir));
  28.         printk("pgd_entry = 0x%lx\n", pgd_val(*pgd_entry));
  29.         printk("pgd_entry_index = %ld\n", pgd_entry_index);

  30.         vfree((void*)vaddr);  

  31.         return 0;
  32. }

  33. static void __exit finish(void)
  34. {
  35.         printk("The module is exit\n");
  36. }

  37. module_init(show_pgd);  
  38. module_exit(finish);  
  39. MODULE_LICENSE("GPL");
复制代码
make并insmod,dmesg查看结果
  1. vmalloc_vaddr=0xffffc90009852000
  2. cr3 = 0x36b9a000
  3. pgdir = 0x3a2e1067
  4. pgd_entry = 0x3fad8067
  5. pgd_entry_index = 402
复制代码
PGD的值为0x3a2e1067,而cr3中的值为0x36b9a000

此处不解,请各位指点一下,谢谢。


作者: qianguozheng    时间: 2016-06-06 19:15
cr3是什么玩意。。。
作者: qianguozheng    时间: 2016-06-06 19:21
http://bbs.chinaunix.net/thread-2091410-1-1.html
作者: superwujc    时间: 2016-06-07 05:26
回复 3# qianguozheng

感谢,但不知道楼上想说什么?
   
作者: nswcfd    时间: 2016-06-07 14:09
回答不了楼主cr3和pgd不一致问题,但是用vmalloc做测试貌似是有问题的,
vmalloc修改的是init_mm的页表,而不是current->mm。——当然产生一次缺页中断之后就一致了。
作者: superwujc    时间: 2016-06-07 15:23
回复 5# nswcfd

感谢楼上,cr3与current->mm->pgd确实是一致的,进程context 切换后,current->mm->pgd相当于二级指针,自身是一个地址,另指向页全局目录PGD的地址
  1. #include <linux/kernel.h>  
  2. #include <linux/module.h>  
  3. #include <linux/init.h>  
  4. #include <linux/mm.h>  
  5. #include <linux/mm_types.h>  
  6. #include <asm/pgtable.h>  
  7. #include <linux/vmalloc.h>  
  8. #include <linux/sched.h>  

  9. static int __init show_pgd(void)
  10. {
  11.         unsigned long cr3, vaddr, pgd_entry_index;
  12.         pgd_t *pgdir, *pgd_entry;
  13.         vaddr = (unsigned long)vmalloc(1000 * sizeof(char));
  14.         if (vaddr == 0) {
  15.                 printk("vmalloc failed..\n");
  16.                 return -1;
  17.         }
  18.         printk("vmalloc_vaddr=0x%lx\n", vaddr);

  19.         cr3 = read_cr3();
  20.         pgdir = current->mm->pgd;
  21.         pgd_entry = pgd_offset(current->mm, vaddr);
  22.         pgd_entry_index = pgd_index(vaddr);

  23.         printk("cr3 = 0x%lx\n", cr3);
  24.         printk("virtual pgd = %p\n", pgdir);
  25.         printk("physical pgd = 0x%lx\n", __pa(pgdir));
  26.         printk("pgd_entry = 0x%lx\n", pgd_val(*pgd_entry));
  27.         printk("pgd_entry_index = %ld\n", pgd_entry_index);

  28.         vfree((void*)vaddr);  

  29.         return 0;
  30. }

  31. static void __exit finish(void)
  32. {
  33.         printk("The module is exit\n");
  34. }

  35. module_init(show_pgd);  
  36. module_exit(finish);  
  37. MODULE_LICENSE("GPL");
复制代码
运行结果为
  1. vmalloc_vaddr=0xffffc90009c2d000
  2. cr3 = 0x38be9000
  3. virtual pgd = ffff880038be9000
  4. physical pgd = 0x38be9000
  5. pgd_entry = 0x3fad8067
  6. pgd_entry_index = 402
复制代码
另请教一下

怎样在kernel module中自行处理page fault,也就是pte不存在时手动分配页帧?
作者: nswcfd    时间: 2016-06-12 16:43
不是很清楚,或许现有的page fault流程有hook或者notifier可以使用,但不知道是否能够完全替代kernel自身的流程。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2