linux x86内存分页时,pgd与cr3的疑问
请教各位高手每个进程都有独立的PGD,保存在当前进程的内存描述符mm_struct的pgd字段中,而该字段的值是从cr3中加载
但我通过运行以下内核模块,打印cr3与pgd的值时,发现二者并不一致#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <asm/pgtable.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
static int __init show_pgd(void)
{
unsigned long cr3, pgd_entry_index;
struct mm_struct *mm;
pgd_t *pgdir, *pgd_entry;
unsigned long vaddr = 0;
vaddr = (unsigned long)vmalloc(1000 * sizeof(char));
if (vaddr == 0) {
printk("vmalloc failed..\n");
return -1;
}
printk("vmalloc_vaddr=0x%lx\n", vaddr);
cr3 = read_cr3();
mm = current->mm;
pgdir = mm->pgd;
pgd_entry = pgd_offset(current->mm, vaddr);
pgd_entry_index = pgd_index(vaddr);
printk("cr3 = 0x%lx\n", cr3);
printk("pgdir = 0x%lx\n", pgd_val(*pgdir));
printk("pgd_entry = 0x%lx\n", pgd_val(*pgd_entry));
printk("pgd_entry_index = %ld\n", pgd_entry_index);
vfree((void*)vaddr);
return 0;
}
static void __exit finish(void)
{
printk("The module is exit\n");
}
module_init(show_pgd);
module_exit(finish);
MODULE_LICENSE("GPL");
make并insmod,dmesg查看结果vmalloc_vaddr=0xffffc90009852000
cr3 = 0x36b9a000
pgdir = 0x3a2e1067
pgd_entry = 0x3fad8067
pgd_entry_index = 402PGD的值为0x3a2e1067,而cr3中的值为0x36b9a000
此处不解,请各位指点一下,谢谢。
cr3是什么玩意。。。 http://bbs.chinaunix.net/thread-2091410-1-1.html 回复 3# qianguozheng
感谢,但不知道楼上想说什么?
回答不了楼主cr3和pgd不一致问题,但是用vmalloc做测试貌似是有问题的,
vmalloc修改的是init_mm的页表,而不是current->mm。——当然产生一次缺页中断之后就一致了。 回复 5# nswcfd
感谢楼上,cr3与current->mm->pgd确实是一致的,进程context 切换后,current->mm->pgd相当于二级指针,自身是一个地址,另指向页全局目录PGD的地址#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <asm/pgtable.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
static int __init show_pgd(void)
{
unsigned long cr3, vaddr, pgd_entry_index;
pgd_t *pgdir, *pgd_entry;
vaddr = (unsigned long)vmalloc(1000 * sizeof(char));
if (vaddr == 0) {
printk("vmalloc failed..\n");
return -1;
}
printk("vmalloc_vaddr=0x%lx\n", vaddr);
cr3 = read_cr3();
pgdir = current->mm->pgd;
pgd_entry = pgd_offset(current->mm, vaddr);
pgd_entry_index = pgd_index(vaddr);
printk("cr3 = 0x%lx\n", cr3);
printk("virtual pgd = %p\n", pgdir);
printk("physical pgd = 0x%lx\n", __pa(pgdir));
printk("pgd_entry = 0x%lx\n", pgd_val(*pgd_entry));
printk("pgd_entry_index = %ld\n", pgd_entry_index);
vfree((void*)vaddr);
return 0;
}
static void __exit finish(void)
{
printk("The module is exit\n");
}
module_init(show_pgd);
module_exit(finish);
MODULE_LICENSE("GPL");
运行结果为vmalloc_vaddr=0xffffc90009c2d000
cr3 = 0x38be9000
virtual pgd = ffff880038be9000
physical pgd = 0x38be9000
pgd_entry = 0x3fad8067
pgd_entry_index = 402另请教一下
怎样在kernel module中自行处理page fault,也就是pte不存在时手动分配页帧? 不是很清楚,或许现有的page fault流程有hook或者notifier可以使用,但不知道是否能够完全替代kernel自身的流程。
页:
[1]