Skip to content

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