Lab3:Page Tables(1) —— 源码解读

--------24.6.13------------
  目前,我通过了 MIT6.S081 Lab3 的实验,通过各种办法,阅读 xv6 的中文译本,参考别人的思路、代码等等,不完全是自己的思路,但也总算是将该实验完成了。
  所以就有了一些想法,想要通过博客的方式记录自己做 lab3 的过程,以及对操作系统的相关收获,预计会写几篇博客来叙述,目前还没有怎么构思好,因为在这个lab着实花费了不少时间,踩了不少坑,想要更完整地记录学习的过程。


虚拟内存地址和物理地址转换

如图1所示

  1. 虚拟地址使用了低39位,其中高27位作为页表的索引,低12位作为物理地址的偏移量
  2. 页表索引具体又分为三级页表,每级页表包含512条PTE,每条PTE大小为8个字节,所以每级页表大小占4KB

图片来自https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf

代码解读

  1. walk 函数
// Return the address of the PTE in page table pagetable
// that corresponds to virtual address va.  If alloc!=0,
// create any required page-table pages.
//
// The risc-v Sv39 scheme has three levels of page-table
// pages. A page-table page contains 512 64-bit PTEs.
// A 64-bit virtual address is split into five fields:
//   39..63 -- must be zero.
//   30..38 -- 9 bits of level-2 index.
//   21..29 -- 9 bits of level-1 index.
//   12..20 -- 9 bits of level-0 index.
//    0..11 -- 12 bits of byte offset within the page.
pte_t* walk(pagetable_t pagetable, uint64 va, int alloc) {
  // 如果当前虚拟地址超过了定义的虚拟地址最大值MAXVA,返回错误
  if(va >= MAXVA)
    panic("walk");
  // 三级页表的遍历
  for(int level = 2; level > 0; level--) {
  	// PX() 可以获得va的第level级页表的索引位置,范围为 0-511,取出对应的PTE
    pte_t *pte = &pagetable[PX(level, va)];
    if(*pte & PTE_V) { // PTE存在,切换页表页到下一级的页表页
      // PTE2PA是将页表条目右移10位再左移12位,可以获得下一个页表的PPN
      pagetable = (pagetable_t)PTE2PA(*pte);
    } else { // 处理PTE不存在,alloc为1,分配一个新的页表页,alloc为0,直接返回0,不进行页表分配
      if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
        return 0;
      memset(pagetable, 0, PGSIZE); // 初始化新页表
      // 新页表的物理地址转换为PTE,右移12位,再左移10位,同时PTE_V置1,放入到当前页表条目中
      *pte = PA2PTE(pagetable) | PTE_V;
    }
  }
  // 返回最后一级页表记录的PTE
  return &pagetable[PX(0, va)];
}
  1. mappages 函数
// Create PTEs for virtual addresses starting at va that refer to
// physical addresses starting at pa. va and size might not
// be page-aligned. Returns 0 on success, -1 if walk() couldn't
// allocate a needed page-table page.
int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) {
  uint64 a, last;
  pte_t *pte;

  // a = 虚拟地址 va 低12位置 0
  a = PGROUNDDOWN(va);
  // last是要分配的结束地址
  last = PGROUNDDOWN(va + size - 1);
  for(;;){
  	// 判断walk函数的结果
    if((pte = walk(pagetable, a, 1)) == 0)
      return -1;
    // 判断PTE是否存在,存在则重新分配,因为目的是要将va映射到pa,取到页表条目应该不存在,这时候为他分配
    if(*pte & PTE_V)
      panic("remap");
    // 转换物理地址为PTE,存入到当前的页表条目中
    *pte = PA2PTE(pa) | perm | PTE_V;
    // 如果到达分配结束地址,停止循环
    if(a == last)
      break;
    a += PGSIZE;
    pa += PGSIZE;
  }
  return 0;
}

参考

  1. 图1参考自MIT book-riscv-rev1
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值