page-table的技術:
x86的page table hardware負責將每個虛擬記憶體(virtual address)對應到實體記憶體(physical address)
每個x86的page table都是邏輯上的陣列,其中包含 220 (1,048,576) 的 page table entries (PTEs)
而每個PTE包含20 bits的physical page number (PPN) 和 12 bits的flags


page table存在physical memory中的方式為two-level tree
paging hardware轉換virtual address的步驟為:


0201 // Memory layout
0202 #define EXTMEM 0x100000 // Start of extended memory
0203 #define PHYSTOP 0xE000000 // Top physical memory
0204 #define DEVSPACE 0xFE000000 // Other devices are at high addresses
0205
0206 // Key addresses for address space layout (see kmap in vm.c for layout)
0207 #define KERNBASE 0x80000000 // First kernel virtual address
0208 #define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked
0209
0210 #define V2P(a) (((uint) (a)) − KERNBASE)
0211 #define P2V(a) (((void *) (a)) + KERNBASE)
0212
0213 #define V2P_WO(x) ((x) − KERNBASE) // same as V2P, but without casts
0214 #define P2V_WO(x) ((x) + KERNBASE) // same as P2V, but without casts

// Set up kernel part of a page table.
pde_t* setupkvm(void)
{
pde_t *pgdir;
struct kmap
*k;
if((pgdir = return 0;
(pde_t*)kalloc()) == 0)
memset(pgdir, 0, PGSIZE);
if (P2V(PHYSTOP) > (void*)DEVSPACE)
panic("PHYSTOP too high");
for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
if(mappages(pgdir, k−>virt, k−>phys_end − (uint)k−>phys_start, k−>perm)
k−>phys_start, < 0) {
freevm(pgdir);
return 0; }
return pgdir;
}
// Allocate one page table for the machine for the kernel address
// space for scheduler processes.
void kvmalloc(void)
{
kpgdir = setupkvm(); switchkvm();
}
0103 typedef uint pde_t;
//...
0848 typedef uint pte_t;
1756 // Create PTEs for virtual addresses starting at va that refer to 1757 // physical addresses starting at pa. va and size might not
1758 // be page−aligned.
1759 static int
1760 mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) 1761 {
1762 char *a, *last;
1763 pte_t *pte;
1764
1765 a = (char*)PGROUNDDOWN((uint)va);
1766 last = (char*)PGROUNDDOWN(((uint)va) + size − 1);
1767 for(;;){
1768 if((pte = walkpgdir(pgdir, a, 1)) == 0)
1769 return −1;
1770 if(*pte & PTE_P)
1771 panic("remap");
1772 *pte = pa | perm | PTE_P;
1773 if(a == last)
1774 break;
1775 a += PGSIZE;
1776 pa += PGSIZE;
1777 }
1778 return 0;
1779 }









Sbrk是一個system call,能讓process增加、縮小自己的的memory




Sbrk主要以growproc(2558)來實作



x86中在Translation Look-aside Buffer (TLB) caches PTEs,當page table改變時必須將cache的entry無效化






#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
