我正在使用Linux 3.18.20的简化版本,我需要创建两个新的系统调用:一个读取给定虚拟地址的页表项,另一个写入对应的页表项给定的虚拟地址。我一直在使用英特尔架构参考手册,卷。 3,第4章,第5节,了解虚拟地址如何转换为物理地址,并且为了实现我的系统调用,我创建了一个辅助函数,它返回所请求的页表项的虚拟地址(或NULL,如果该页表条目不存在)。
我创建了一个测试程序,它创建了一个局部变量(可能存储在堆栈中,对吗?)并将其虚拟地址传递给我的系统调用,以确保我的翻译正确完成。然后,我手动完成所有的移位操作,以确保我的代码完成我认为的操作;它似乎是正确的,所以我在这一点上得出的唯一结论是,我不知道我不知道的是什么;我需要一条至关重要的信息,我甚至没有意识到我需要这些信息。
你能看一下我的代码,并告诉我是否有一些明显的我做错了吗?
unsigned long *find_pte(unsigned long vaddr) {
unsigned long cr3, pml4_addr, pml4e, pml4e_addr;
unsigned long pdpt_addr, pdpte_addr, pdpte;
unsigned long pd_addr, pde_addr, pde;
unsigned long pt_addr, pte_addr;
unsigned long vaddr30thru38, vaddr39thru47, vaddr21thru29, vaddr12thru20;
cr3 = (unsigned long) get_pagetable();
/* get_pageable() is a helper function, provided by my professor,
that supposedly returns the contents of the CR3 register, with the most
significant and least significant 12 bits replaced with 0.*/
printk("in syscall: vaddr=%lx, cr3=%lx\n", vaddr, cr3);//DEBUG
pml4_addr = cr3;
vaddr39thru47 = (vaddr >> 36) & 0xff8;
printk("in syscall: vaddr39thru47=%lx\n", vaddr39thru47);//DEBUG
pml4e_addr = pml4_addr | vaddr39thru47;
printk("in syscall: physical pml4e_addr=%lx\n", pml4e_addr);//DEBUG
pml4e_addr = (unsigned long) __va(pml4e_addr);
printk("in syscall: virtual pml4e_addr=%lx\n", pml4e_addr);//DEBUG
pml4e = *((unsigned long*) pml4e_addr);
printk("in syscall: pml4e=%lx\n", pml4e);//DEBUG
if ((pml4e & 1) == 0) {
printk("in syscall: pml4e's valid bit is not set\n");//DEBUG
return NULL;
}
printk("in syscall: pml4e's valid bit is set\n");//DEBUG
vaddr30thru38 = (vaddr >> 27) & 0xff8;
printk("in syscall: vaddr30thru38=%lx\n", vaddr30thru38);
pdpte_addr = (pdpt_addr | vaddr30thru38);
printk("in syscall: physical pdpte_addr=%lx\n", pdpte_addr);//DEBUG
pdpte_addr = (unsigned long) __va(pdpte_addr);
printk("in syscall: virtual pdpte_addr=%lx\n", pdpte_addr);//DEBUG
pdpte = *((unsigned long*) pdpte_addr);
printk("in syscall: pdpte=%lx\n", pdpte);//DEBUG
if (((pdpte >> 7) & 1) == 1) {
printk("in syscall: pdpte's ps flag is 1\n");//DEBUG
return (unsigned long*) pdpte_addr;
}
printk("in syscall: pdpte's ps flag is 0\n");//DEBUG
if ((pdpte & 1) == 0) {
printk("in syscall: pdpte's valid bit is not set\n");//DEBUG
return NULL;
}
printk("in syscall: pdpte's valid bit is set\n");//DEBUG
pd_addr = pdpte & 0x000ffffffffff000;
printk("in syscall: pd_addr=%lx\n", pd_addr);//DEBUG
vaddr21thru29 = (vaddr >> 18) & 0xff8;
printk("in syscall: vaddr21thru29=%lx\n", vaddr21thru29);//DEBUG
pde_addr = pd_addr | vaddr21thru29;
printk("in syscall: physical pde_addr=%lx\n", pde_addr);//DEBUG
pde_addr = (unsigned long) __va(pde_addr);
printk("in syscall: virtual pde_addr=%lx\n", pde_addr);//DEBUG
pde = *((unsigned long*) pde_addr);
printk("in syscall: pde=%lx\n", pde);//DEBUG
if (((pde >> 7) & 1) == 1) {
printk("in syscall: pde's ps flag is 1\n");//DEBUG
return (unsigned long*) pde_addr;
}
printk("in syscall: pde's ps flag is 0\n");//DEBUG
if ((pde & 1) == 0) {
printk("in syscall: pde's valid bit is not set\n");//DEBUG
return NULL;
}
printk("in syscall: pde's valid bit is set\n");//DEBUG
pt_addr = pde & 0x000ffffffffff000;
printk("in syscall: pt_addr=%lx\n", pt_addr);//DEBUG
vaddr12thru20 = (vaddr >> 9) & 0xff8;
printk("in syscall: vaddr12thru20=%lx\n", vaddr12thru20);//DEBUG
pte_addr = pt_addr | vaddr12thru20;
printk("in syscall: physical pte_addr=%lx\n", pte_addr);//DEBUG
pte_addr = (unsigned long) __va(pte_addr);
return (unsigned long*) pte_addr;
答案 0 :(得分:1)
没关系。我的代码没有任何问题(除了省略一行,将代码从我的文件复制到Stack Overflow时出错)。我的测试错误地将其标记为已损坏。