zircon/kernel/arch/x86/page_tables/page_tables.cc
/*
 * @brief Split the given large page into smaller pages
 */
@brief Split the given large page into smaller pages
@brief Split the given large page into smaller pages
zx_status_t X86PageTableBase::SplitLargePage(PageTableLevel level, vaddr_t vaddr,
                                             volatile pt_entry_t* pte, ConsistencyManager* cm) {
  DEBUG_ASSERT_MSG(level != PT_L, "tried splitting PT_L");
  LTRACEF_LEVEL(2, "splitting table %p at level %d\n", pte, level);
  DEBUG_ASSERT(IS_PAGE_PRESENT(*pte) && IS_LARGE_PAGE(*pte));
  volatile pt_entry_t* m = AllocatePageTable();
  if (m == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }
  paddr_t paddr_base = paddr_from_pte(level, *pte);
  PtFlags flags = split_flags(level, *pte & X86_LARGE_FLAGS_MASK);
  DEBUG_ASSERT(page_aligned(level, vaddr));
  vaddr_t new_vaddr = vaddr;
  paddr_t new_paddr = paddr_base;
  size_t ps = page_size(lower_level(level));
  for (int i = 0; i < NO_OF_PT_ENTRIES; i++) {
    volatile pt_entry_t* e = m + i;
    UpdateEntry(cm, lower_level(level), new_vaddr, e, new_paddr, flags, false );
    new_vaddr += ps;
    new_paddr += ps;
  }
  DEBUG_ASSERT(new_vaddr == vaddr + page_size(level));
  flags = intermediate_flags();
  UpdateEntry(cm, level, vaddr, pte, X86_VIRT_TO_PHYS(m), flags, true );
  pages_++;
  return ZX_OK;
}
zx_status_t X86PageTableBase :: SplitLargePage ( PageTableLevel level , vaddr_t vaddr , volatile pt_entry_t * pte , ConsistencyManager * cm ) { DEBUG_ASSERT_MSG ( level != PT_L , " " ) ; LTRACEF_LEVEL ( 2 , " \n " , pte , level ) ; DEBUG_ASSERT ( IS_PAGE_PRESENT ( * pte ) && IS_LARGE_PAGE ( * pte ) ) ; volatile pt_entry_t * m = AllocatePageTable ( ) ; if ( m == nullptr ) { return ZX_ERR_NO_MEMORY ; } paddr_t paddr_base = paddr_from_pte ( level , * pte ) ; PtFlags flags = split_flags ( level , * pte & X86_LARGE_FLAGS_MASK ) ; DEBUG_ASSERT ( page_aligned ( level , vaddr ) ) ; vaddr_t new_vaddr = vaddr ; paddr_t new_paddr = paddr_base ; size_t ps = page_size ( lower_level ( level ) ) ; for ( int i = 0 ; i < NO_OF_PT_ENTRIES ; i ++ ) { volatile pt_entry_t * e = m + i ; UpdateEntry ( cm , lower_level ( level ) , new_vaddr , e , new_paddr , flags , false ) ; new_vaddr += ps ; new_paddr += ps ; } DEBUG_ASSERT ( new_vaddr == vaddr + page_size ( level ) ) ; flags = intermediate_flags ( ) ; UpdateEntry ( cm , level , vaddr , pte , X86_VIRT_TO_PHYS ( m ) , flags , true ) ; pages_ ++ ; return ZX_OK ; }
@brief Split the given large page into smaller pages
@brief Split the given large page into smaller pages
// If this is a PDP_L (i.e. huge page), flags will include the // PS bit still, so the new PD entries will be large pages. /* was_terminal */ /* was_terminal */