Example #1
0
bool ArchMemory::mapPage(uint32 virtual_page, uint32 physical_page, uint32 user_access)
{
  RESOLVEMAPPING(page_dir_pointer_table_,virtual_page);

  if (page_dir_pointer_table_[pdpte_vpn].present == 0)
  {
    uint32 pd_ppn = PageManager::instance()->allocPPN();
    page_directory = (PageDirEntry*) getIdentAddressOfPPN(pd_ppn);
    insertPD(pdpte_vpn, pd_ppn);
  }

  if (page_directory[pde_vpn].pt.present == 0)
  {
    insertPT(page_directory, pde_vpn, PageManager::instance()->allocPPN());
  }
  assert(page_directory[pde_vpn].page.size == 0);

  PageTableEntry *pte_base = (PageTableEntry *) getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
  if(pte_base[pte_vpn].present == 0)
  {
    pte_base[pte_vpn].writeable = 1;
    pte_base[pte_vpn].user_access = user_access;
    pte_base[pte_vpn].page_ppn = physical_page;
    pte_base[pte_vpn].present = 1;
    return true;
  }

  assert(false);
  return false;
}
Example #2
0
uint32 ArchMemory::get_PPN_Of_VPN_In_KernelMapping(uint32 virtual_page, size_t *physical_page, uint32 *physical_pte_page)
{
  PageDirPointerTableEntry *pdpt = kernel_page_directory_pointer_table;
  RESOLVEMAPPING(pdpt, virtual_page);
  if (pdpt[pdpte_vpn].present)
  {
    if (page_directory[pde_vpn].pt.present)
    {
      if (page_directory[pde_vpn].page.size)
      {
        if (physical_page)
          *physical_page = page_directory[pde_vpn].page.page_ppn;
        return (PAGE_SIZE*PAGE_TABLE_ENTRIES);
      }
      else
      {
        if (physical_pte_page)
          *physical_pte_page = page_directory[pde_vpn].pt.page_table_ppn;
        PageTableEntry *pte_base = (PageTableEntry *) getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
        if (pte_base[pte_vpn].present)
        {
          if (physical_page)
            *physical_page = pte_base[pte_vpn].page_ppn;
          return PAGE_SIZE;
        }
      }
    }
  }
  return 0;
}
Example #3
0
void ArchMemory::unmapKernelPage(uint32 virtual_page)
{
  PageDirPointerTableEntry *pdpt = kernel_page_directory_pointer_table;
  RESOLVEMAPPING(pdpt, virtual_page);
  assert(pdpt[pdpte_vpn].present);
  assert(page_directory[pde_vpn].pt.present && page_directory[pde_vpn].pt.size == 0);
  PageTableEntry *pte_base = (PageTableEntry *) getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
  assert(pte_base[pte_vpn].present);
  pte_base[pte_vpn].present = 0;
  pte_base[pte_vpn].writeable = 0;
  PageManager::instance()->freePPN(pte_base[pte_vpn].page_ppn);
  asm volatile ("movl %%cr3, %%eax; movl %%eax, %%cr3;" ::: "%eax");
}
Example #4
0
void ArchMemory::unmapPage(uint32 virtual_page)
{
  RESOLVEMAPPING(page_dir_pointer_table_,virtual_page);

  assert(page_dir_pointer_table_[pdpte_vpn].present);
  assert(!page_directory[pde_vpn].page.size);

  PageTableEntry *pte_base = (PageTableEntry *) getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
  assert(pte_base[pte_vpn].present);

  pte_base[pte_vpn].present = 0;
  PageManager::instance()->freePPN(pte_base[pte_vpn].page_ppn);
  ((uint64*)pte_base)[pte_vpn] = 0; // for easier debugging

  checkAndRemovePT(page_dir_pointer_table_[pdpte_vpn].page_directory_ppn, pde_vpn);
}
Example #5
0
pointer ArchMemory::checkAddressValid(uint32 vaddress_to_check)
{
  RESOLVEMAPPING(page_dir_pointer_table_, vaddress_to_check / PAGE_SIZE);
  if (page_dir_pointer_table_[pdpte_vpn].present)
  {
    if (page_directory[pde_vpn].pt.present)
    {
      if (page_directory[pde_vpn].page.size)
        return getIdentAddressOfPPN(page_directory[pde_vpn].page.page_ppn,PAGE_SIZE * PAGE_TABLE_ENTRIES) | (vaddress_to_check % (PAGE_SIZE * PAGE_TABLE_ENTRIES));

      PageTableEntry *pte_base = (PageTableEntry *) getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
      if (pte_base[pte_vpn].present)
        return getIdentAddressOfPPN(pte_base[pte_vpn].page_ppn) | (vaddress_to_check % PAGE_SIZE);
    }
  }
  return 0;
}
Example #6
0
extern "C" inline void printPageFaultInfo(size_t address, size_t error)
{
  //--------Start "just for Debugging"-----------
  const bool present = error & FLAG_PF_PRESENT;
  const bool userspace = error & FLAG_PF_USER;
  const bool writing = error & FLAG_PF_RDWR;
  const bool reserved = error & FLAG_PF_RSVD;
  const bool caused_by = error & FLAG_PF_INSTR_FETCH;


  debug(PAGEFAULT, "Address: %x, Present: %d, Writing: %d, Userspace: %d, Rsvc: %d, caused by: %s fetch"
        " - currentThread: %p %d"":%s, switch_to_userspace_: %d\n",
        address, present, writing, userspace, reserved,  caused_by ? "instruction" : "operand",
        currentThread, currentThread->getTID(), currentThread->getName(), currentThread->switch_to_userspace_);

  const Stabs2DebugInfo* deb = kernel_debug_info;
  assert(currentThread->kernel_registers_ && "every thread needs kernel registers");
  ArchThreadRegisters* registers_ = currentThread->kernel_registers_;
  if (error & FLAG_PF_USER)
  {
    assert(currentThread->loader_ && "User Threads need to have a Loader");
    assert(currentThread->user_registers_ && (currentThread->user_registers_->cr3 == currentThread->kernel_registers_->cr3 &&
           "User and Kernel CR3 register values differ, this most likely is a bug!"));
    deb = currentThread->loader_->getDebugInfos();
    registers_ = currentThread->user_registers_;
  }
  if(deb && registers_->eip)
  {
    debug(PAGEFAULT, "This pagefault was probably caused by:");
    deb->printCallInformation(registers_->eip);
  }

  if(!address)
  {
    debug(PAGEFAULT, "Maybe you're dereferencing a null-pointer!\n");
  }
  if (error)
  {
    if (present)
    {
      debug(PAGEFAULT, "We got a pagefault even though the page mapping is present\n");
      debug(PAGEFAULT, "%s tried to %s address %x\n", userspace ? "A userprogram" : "Some kernel code",
            writing ? "write to" : "read from", address);

      RESOLVEMAPPING(currentThread->loader_->arch_memory_.getRootOfPagingStructure(), address / PAGE_SIZE);

      if (page_directory[pde_vpn].pt.present)
      {
        if (page_directory[pde_vpn].page.size)
        {
          debug(PAGEFAULT, "Page 0x%zx is a 4MiB Page\n", address / PAGE_SIZE);
          debug(PAGEFAULT, "Page 0x%zx Flags are: writeable:%d, userspace_accessible:%d,\n", address / PAGE_SIZE,
                page_directory[pde_vpn].page.writeable, page_directory[pde_vpn].page.user_access);
        }
        else
        {
          PageTableEntry *pte_base = (PageTableEntry *) ArchMemory::getIdentAddressOfPPN(page_directory[pde_vpn].pt.page_table_ppn);
          debug(PAGEFAULT, "Page 0x%zx is a 4KiB Page\n", address / PAGE_SIZE);
          debug(PAGEFAULT, "Page 0x%zx Flags are: present:%zu, writeable:%zu, userspace_accessible:%zu,\n", address / PAGE_SIZE,
                pte_base[pte_vpn].present, pte_base[pte_vpn].writeable, pte_base[pte_vpn].user_access);
        }
      }
      else
        debug(PAGEFAULT, "WTF? PDE non-present but Exception present flag was set\n");
    }
    else
    {
      if (address >= 2U*1024U*1024U*1024U)
      {
        debug(PAGEFAULT, "The virtual page we accessed was not mapped to a physical page\n");
        if (userspace)
        {
          debug(PAGEFAULT, "WARNING: Your Userspace Programm tried to read from an unmapped address >2GiB\n");
          debug(PAGEFAULT, "WARNING: Most likey there is an pointer error somewhere\n");
        }
        else
        {
          // remove this error check if your implementation swaps out kernel pages
          debug(PAGEFAULT, "WARNING: This is unusual for addresses above 2Gb, unless you are swapping kernel pages\n");
          debug(PAGEFAULT, "WARNING: Most likey there is an pointer error somewhere\n");
        }
      }
      else
      {
        //debug(PAGEFAULT, "The virtual page we accessed was not mapped to a physical page\n");
        //debug(PAGEFAULT, "this is normal and the Loader will propably take care of it now\n");
      }
    }
  }
  ArchThreads::printThreadRegisters(currentThread, false);
}