kernel/vm.c
// the provided pagetable need not to be a valid PT.
// (i.e it could be an empty page)
the provided pagetable need not to be a valid PT.
the provided pagetable need not to be a valid PT .
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)];
}
static pte_t * walk ( pagetable_t pagetable , uint64 va , int alloc ) { if ( va >= MAXVA ) panic ( " " ) ; 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 ) ] ; }
the provided pagetable need not to be a valid PT.
the provided pagetable need not to be a valid PT .
// get a pointer to the pte found by using the // 9 bits at the corresponding level. // get the address of the PT pointed by pte // the required page hasn't been allocated, so allocate it. // the page could not be allocated // fill the new page with 0 (allocated in the if statement) // pagetable holds the address of the 4096-byte page, // since PTEs are page-aligned, we can remove the  // 12-bit offset and make this PTE point to this page. // also make the PTE valid. // pagetable is the address of the new PT page. // i.e. *pte = PA2PTE(pa) | perm | PTE_V; // we've reached level = 0, the loop doesn't include level 0. // walk only creates the necessary mappings, it is up to the caller // to make the returned PTE point to a specific page obtained with kalloc.