pte.h

来源:互联网 发布:域名绑定到空间 编辑:程序博客网 时间:2024/05/21 22:40

#define PTSHIFT PGBITS            /*page table index的开始位:12*/
#define PTBITS  10                         /*page table index的位长度*/
#define PTSPAN  (1 << PTBITS << PGBITS)   /*一个page table index指向一个page table,而一个page table大小是1KB*/
#define PTMASK  BITMASK(PTSHIFT, PTBITS)  /*掩码,即过滤其他位*/
static inline unsigned pt_no (const void *va) {
  return ((uintptr_t) va & PTMASK) >> PTSHIFT;
}
va表示虚拟地址,即32位,先把page table index通过掩码过滤,然后把他移到低位。

一个page table index指向一个page table,而一个page table entry是一个虚拟地址。
一个PDE把物理地址抽取出来指向一个page table。如果PDE的present位是false,则忽略其他位。

   31                                             12 11                               0            
   +------------------------------------+------------------------+
   |         Physical Address                   |         Flags                  |           
   +------------------------------------+------------------------+
12-31位是物理地址,我们指向一个page table之前必须要把他转化为虚拟地址。

#define PTE_FLAGS 0x00000fff    /* Flag bits. */
#define PTE_ADDR  0xfffff000    /* Address bits. */
#define PTE_AVL   0x00000e00    /* Bits available for OS use. */
#define PTE_P 0x1               /* 1=present, 0=not present. */
#define PTE_W 0x2               /* 1=read/write, 0=read-only. */
#define PTE_U 0x4               /* 1=user/kernel, 0=kernel only. */
#define PTE_A 0x20              /* 1=accessed, 0=not acccessed. */
#define PTE_D 0x40              /* 1=dirty, 0=not dirty (PTEs only). */
以上是一群宏定义,他们的目的很像掩码,就是过滤其他位,把自己需要的位给抽取出来。
static inline uint32_t pde_create (uint32_t *pt) {
  ASSERT (pg_ofs (pt) == 0);
  return vtop (pt) | PTE_U | PTE_P | PTE_W;
}
pt为page table 的虚拟地址,我们前面讲到pde含有的是page table的物理地址,因此我们需要把va转换为pa,并且还要把标识位设置好。即用户进程能访问,并且present,并且能够可以写的。
static inline uint32_t *pde_get_pt (uint32_t pde) {
  ASSERT (pde & PTE_P);
  return ptov (pde & PTE_ADDR);
}
这个就和我上面讲的一样,已知pde地址,要求他指向的page table的地址,需要先用掩码把物理地址提取出来,再变成虚拟地址即可。
static inline uint32_t pte_create_kernel (void *page, bool writable) {
  ASSERT (pg_ofs (page) == 0);
  return vtop (page) | PTE_P | (writable ? PTE_W : 0);
}
这个是创建一个pte指向指定的page,就类似于pde指向pt。需要注意是这个只能被kernel所使用。