pagetable_t is a pointer points to 512 PTEs. page tables are physical memory, initialized by kalloc(). The *pte stores physical memory.
How to find the address of PTE given virtual address
*// 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..39 — 9 bits of level-1 index.*
*// 12..20 — 9 bits of level-0 index.*
*// 0..12 — 12 bits of byte offset within the page.*
static pte_t *
walk(pagetable_t *pagetable*, uint64 *va*, int *alloc*)
{
if(va >= MAXVA)
panic(“walk”);
for(int level = 2; level > 0; level—) {
pte_t *pte = &pagetable[PX(level, va)];
if(*pte & PTE_V) {
pagetable = (pagetable_t)PTE2PA(*pte);
} else {
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
return 0;
memset(pagetable, 0, PGSIZE);
*pte = PA2PTE(pagetable) | PTE_V;
}
}
return &pagetable[PX(0, va)];
}
pagetable = (pde_t)kalloc())
Above code creates the level_X page table directly from physical memory, and set to pte.
How to map page.
*// 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.*intmappages(pagetable_t*pagetable*, uint64 *va*, uint64 *size*, uint64 *pa*,int*perm*){ uint64 a, last;pte_t*pte; a =PGROUNDDOWN(va); last =PGROUNDDOWN(va + size -1);for(;;){if((pte =walk(pagetable, a,1)) ==0)return-1;if(*pte & PTE_V)panic("remap");*pte =PA2PTE(pa)| perm | PTE_V;if(a == last)break; a += PGSIZE; pa += PGSIZE; }return0;}