Print a page table (easy)
为了帮助您了解RISC-V页表,也许为了帮助将来的调试,您的第一个任务是编写一个打印页表内容的函数。
将vmprint的原型定义在kernel/defs.h中,
diff --git a/kernel/defs.h b/kernel/defs.h
index 4b9bbc0..52ef0d5 100644
--- a/kernel/defs.h
+++ b/kernel/defs.h
@@ -171,6 +171,7 @@ uint64 walkaddr(pagetable_t, uint64);
int copyout(pagetable_t, uint64, char *, uint64);
int copyin(pagetable_t, char *, uint64, uint64);
int copyinstr(pagetable_t, char *, uint64, uint64);
void vmprint(pagetable_t);
然后在exec.c中调用它
diff --git a/kernel/exec.c b/kernel/exec.c
index 0e8762f..fc832f7 100644
--- a/kernel/exec.c
+++ b/kernel/exec.c
@@ -116,6 +116,9 @@ exec(char *path, char **argv)
p->trapframe->sp = sp; // initial stack pointer
proc_freepagetable(oldpagetable, oldsz);
if(p->pid==1) {
vmprint(p->pagetable);
}
return argc; // this ends up in a0, the first argument to main(argc, argv)
bad:
参考函数freewalk
c
// Recursively free page-table pages.
// All leaf mappings must already have been removed.
void
freewalk(pagetable_t pagetable)
{
// there are 2^9 = 512 PTEs in a page table.
for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
freewalk((pagetable_t)child);
pagetable[i] = 0;
} else if(pte & PTE_V){
panic("freewalk: leaf");
}
}
kfree((void*)pagetable);
}
freewalk 函数的实现,用于释放页表及其下级页表的内存。
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0)
:
检查当前页表项是否有效(PTE_V 表示有效),并且该页表项不具有读、写或执行权限(即它指向一个下级页表)。
else if(pte & PTE_V)
:
如果当前页表项有效但具有读、写或执行权限,则调用 panic 函数,输出错误信息 "freewalk: leaf",表示该页表项是一个叶子节点,不应被释放
将vmprint()放在kernel/vm.c中
在printf调用中使用%p来打印像上面示例中的完成的64比特的十六进制PTE和地址
修改初版
写个雏形,体现思路,也就是从freewalk启发的改动
diff --git a/kernel/vm.c b/kernel/vm.c
index bccb405..ed8d315 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -440,3 +440,46 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
return -1;
}
}
void
vmprint_sub(pagetable_t pagetable, int deep){
// there are 2^9 = 512 PTEs in a page table.
for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
for(int j = 0; j <= deep; j++){
if(j)
printf(" ");
printf("..");
}
printf("%d: pte %p pa %p \n",i,pte,child);
vmprint_sub((pagetable_t)child, deep + 1);
pagetable[i] = 0;
} else if(pte & PTE_V){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
for(int j = 0; j <= deep; j++){
if(j)
printf(" ");
printf("..");
}
printf("%d: pte %p pa %p \n",i,pte,child);
continue;
}
}
// kfree((void*)pagetable);
}
void
vmprint(pagetable_t pagetable){
printf("page table %p \n", pagetable);
vmprint_sub(pagetable, 0);
}
\ No newline at end of file
优化整理代码
简化分支结构
diff --git a/kernel/vm.c b/kernel/vm.c
index bccb405..8137b05 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -440,3 +440,40 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
return -1;
}
}
// there are 2^9 = 512 PTEs in a page table.
for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if(pte & PTE_V){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
for(int j = 0; j <= deep; j++){
if(j)
printf(" ");
printf("..");
}
printf("%d: pte %p pa %p\n",i,pte,child);
if((pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
vmprint_sub((pagetable_t)child, deep + 1);
// pagetable[i] = 0;
}
}
}
// kfree((void*)pagetable);
}
void
vmprint(pagetable_t pagetable){
printf("page table %p\n", pagetable);
vmprint_sub(pagetable, 0);
}
\ No newline at end of file