pt_entry* vmmngr_ptable_lookup_entry(ptable* p, virtual_addr addr)
{
	if (p)
		return &p->entries[PAGE_TABLE_INDEX(addr)];

	set_last_error(EINVAL, VMEM_BAD_ARGUMENT, EO_VMMNGR);
	return 0;
}
Exemple #2
0
inline pt_entry * vmmngr_ptable_lookup_entry(ptable * p, virtual_addr addr)
{
	if (p)
	{
		return &p->m_entries[ PAGE_TABLE_INDEX(addr) ];
	}

	return 0;
}
Exemple #3
0
void vmmngr_free_page(virtual_addr addr)
{
	pt_entry * pte;

	pte = (pt_entry *) ((uint32_t) vmmngr_get_ptable_address(addr) + PAGE_TABLE_INDEX(addr));

	pmmngr_free_block((void *) pt_entry_pfn(*pte));

	pt_entry_del_attrib(pte, I86_PTE_PRESENT);
}
Exemple #4
0
int vmmngr_alloc_page(virtual_addr virt)
{
	pdirectory * pd = (pdirectory *) PAGE_DIRECTORY_ADDRESS;
	pd_entry * pde = &pd->m_entries[PAGE_DIRECTORY_INDEX(virt)];

	if ((!pd) || (!pde))
	{
		return 0;
	}

	if (!pd_entry_is_present(*pde))
	{
		ptable *newpt = pmmngr_alloc_block();

		if (!newpt)
		{
			return 0;
		}

		*pde = (pd_entry) 0;

		pd_entry_add_attrib(pde, I86_PDE_PRESENT);
		pd_entry_add_attrib(pde, I86_PDE_WRITABLE);
		pd_entry_set_frame(pde, (physical_addr) newpt);

		memset(vmmngr_get_ptable_address(virt), 0, sizeof(ptable));

	}

	ptable * pt = vmmngr_get_ptable_address(virt);

	pt_entry *pte = &pt->m_entries[PAGE_TABLE_INDEX(virt)];

	if  (pt_entry_is_present(*pte))
	{
		return 1;
	}

	if (!vmmngr_commit_page(pte))
	{
		return 0;
	}

	return 1;	
}
Exemple #5
0
void vmmngr_map_page(void * phys, void * virt)
{
	pageinfo pginf = vmmngr_virt_to_page_index(virt);
	pdirectory * page_directory = kernel_page_dir; //vmmngr_get_directory();

	pd_entry * e = &page_directory->m_entries[PAGE_DIRECTORY_INDEX((uint32_t) virt)];
	if (!pd_entry_is_present(*e))
	{
		ptable * new_table = (ptable *) pmmngr_alloc_block();
		if (!new_table)
		{
			return;
		}

		ptable * virtual_table = (ptable *) (0xFFC00000 + (pginf.pagetable * 0x1000));
		pd_entry * entry = &kernel_page_dir->m_entries[pginf.pagetable];

		pd_entry_add_attrib(entry, I86_PDE_PRESENT);
		pd_entry_add_attrib(entry, I86_PDE_WRITABLE);
		pd_entry_set_frame(entry, (physical_addr) new_table);

		memset(virtual_table, 0, sizeof(ptable));
		pt_entry * page = &virtual_table->m_entries[pginf.page];
		pt_entry_set_frame(page, (physical_addr) phys);
		pt_entry_add_attrib(page, I86_PTE_PRESENT);
		pt_entry_add_attrib(page, I86_PTE_WRITABLE);
		return;

		
	}

	ptable * table = (ptable *) PAGE_GET_PHYSICAL_ADDRESS(e);

	pt_entry * page = &table->m_entries[PAGE_TABLE_INDEX((uint32_t) virt)];

	pt_entry_set_frame(page, (physical_addr) phys);
	pt_entry_add_attrib(page, I86_PTE_PRESENT);
	pt_entry_add_attrib(page, I86_PTE_WRITABLE);
}
Exemple #6
0
void vmmngr_initialize(physical_addr dir_address)
{
	int i = 0;
	int frame = 0;
	int virt = 0;

	ptable * table = (ptable *) pmmngr_alloc_block();
	if (!table)
	{
		return;
	}

	ptable * table2 = (ptable *) pmmngr_alloc_block();
	if (!table2)
	{
		pmmngr_free_block(table);
		return;
	}	

	memset(table, 0, sizeof(ptable));

	for (i = 0, frame = 0x0, virt = 0x00000000; i < 1024; ++i, frame+=4096, virt+=4096)
	{
		pt_entry page = 0;
		pt_entry_add_attrib(&page, I86_PTE_PRESENT);
		pt_entry_set_frame(&page, frame);

		table->m_entries[PAGE_TABLE_INDEX(virt)] = page;
	}

	for (i = 0, frame = 0x0, virt = 0xc0000000; i < 1024; ++i, frame+=4096, virt+=4096)
	{
		pt_entry page = 0;
		pt_entry_add_attrib(&page, I86_PTE_PRESENT);
		pt_entry_set_frame(&page, frame);

		table2->m_entries[PAGE_TABLE_INDEX(virt)] = page;
	}

	pdirectory * dir = (pdirectory *) dir_address;// pmmngr_alloc_block();

	if (!dir)
	{
		pmmngr_free_block(table);
		pmmngr_free_block(table2);
		return;
	}

	memset(dir, 0, sizeof(pdirectory));

	pd_entry * entry = &dir->m_entries[PAGE_DIRECTORY_INDEX(0x00000000)];
	pd_entry_add_attrib(entry, I86_PDE_PRESENT);
	pd_entry_add_attrib(entry, I86_PDE_WRITABLE);
	pd_entry_set_frame(entry, (physical_addr) table);

	pd_entry * entry2 = &dir->m_entries[PAGE_DIRECTORY_INDEX(0xc0000000)];
	pd_entry_add_attrib(entry2, I86_PDE_PRESENT);
	pd_entry_add_attrib(entry2, I86_PDE_WRITABLE);
	pd_entry_set_frame(entry2, (physical_addr) table2);

	pd_entry * entry3 = &dir->m_entries[PAGE_DIRECTORY_INDEX(0xFFC00000)];
	pd_entry_add_attrib(entry3, I86_PDE_PRESENT);
	pd_entry_add_attrib(entry3, I86_PDE_WRITABLE);
	pd_entry_set_frame(entry3, (physical_addr) dir);

	vmmngr_switch_pdirectory(dir);
	pmmngr_paging_enable(1);

}
Exemple #7
0
void do_page_fault (process_t     *proc,
		    unsigned int   linear_addr,
		    long           error_code)
{
  page_frame_t       *new_page, *page_frame;
  unsigned int        phys_frame_addr;
  pagetable_entry_t  *pte;
  int                 pf_ok;


  //Only handle usermode writes to present pages (not present ones later (pagein))
  //if ((error_code & PAGE_FAULT_P) &&
  //    (error_code & PAGE_FAULT_RW) &&
  //    (error_code & PAGE_FAULT_US))
  
  if (error_code & PAGE_FAULT_P) {
    
    //
    // CHECK IF WE REALLY SHOULD COPY THIS
    //  (with vm_blocks)
    //

    pf_ok = 0;

    //Only write pagefaults handled
    if (error_code & PAGE_FAULT_RW) {
      
      if ((linear_addr >= proc->vm_data.vm_start) &&
	  (linear_addr < proc->vm_data.vm_end) &&
	  (proc->vm_data.vm_flags & VM_READWRITE))
	pf_ok = 1;
      
      if ((linear_addr >= proc->vm_stack.vm_start) &&
	  (linear_addr < proc->vm_stack.vm_end) &&
	  (proc->vm_stack.vm_flags & VM_READWRITE))
	pf_ok = 1;
      
      if ((linear_addr >= proc->vm_kernel_stack.vm_start) &&
	  (linear_addr < proc->vm_kernel_stack.vm_end) &&
	  (proc->vm_kernel_stack.vm_flags & VM_READWRITE))
	pf_ok = 1;
    }


    if (!pf_ok)
    {
      printf ("*real* page fault (out of bounds), should terminate task!\n");
      printf ("present=%s, write=%s, usermode=%s, address=0x%x, dir=0x%x\n",
	      ((int) error_code & PAGE_FAULT_P) ? "true" : "false",
	      ((int) error_code & PAGE_FAULT_RW) ? "true" : "false",
	      ((int) error_code & PAGE_FAULT_US) ? "true" : "false",
	      linear_addr,
	      (int) (proc->tss.cr3));
      
      printf ("data start 0x%x, data end 0x%x, flags 0x%x\n",
	      (int) proc->vm_data.vm_start,
	      (int) proc->vm_data.vm_end,
	      (int) proc->vm_data.vm_flags);

      printf ("stack start 0x%x, stack end 0x%x, flags 0x%x\n",
	      (int) proc->vm_stack.vm_start,
	      (int) proc->vm_stack.vm_end,
	      (int) proc->vm_stack.vm_flags);

      while(1);
    }


    //Get dir
    pte = (pagetable_entry_t *) proc->tss.cr3;

    //Get table from dir
    pte = (pagetable_entry_t *) PTE_TO_PHYSICAL(pte[PAGE_DIR_INDEX(linear_addr)]);
    
    //Get page from table
    phys_frame_addr = PTE_TO_PHYSICAL(pte[PAGE_TABLE_INDEX(linear_addr)]);
 
    //Check use count of this page frame
    page_frame = &page_frames[PHYS_TO_FRAME_NR (phys_frame_addr)];
    
    if (page_frame->count > 1)
    {
      //Page in use by others, we need to copy
      new_page = get_free_page();

      if (new_page == NULL)
	panic ("Can't COW, no free pages!");

      //Copy page
      //printf ("COW(copy, 0x%x->0x%x)\n", phys_frame_addr, new_page->page_frame_nr * PAGE_SIZE);
 
      copy_page (phys_frame_addr, new_page->page_frame_nr * PAGE_SIZE);

      //Remap pagetable
      map_page (proc, new_page->page_frame_nr * PAGE_SIZE, 
		linear_addr & PHYS_PAGE_MASK, PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE);
    
      //Decrease use count
      page_frame->count--;

    } else if (page_frame->count == 1)
    {
      //The page is not in use by others, just remap
      //printf ("COW(remap, 0x%x)\n", linear_addr);
 
      //Remap pagetable
      map_page (proc, phys_frame_addr, 
		linear_addr & PHYS_PAGE_MASK, PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE);
  
    } else
    {
      printf ("Page frame has invalid use count!\n");
      while (1);
    }

    //Schedule next process
    schedule();

  } else {

    printf ("*real* page fault (page not present), should terminate task!\n");
 
    printf ("present=%s, write=%s, usermode=%s, address=0x%x, dir=0x%x\n",
	    ((int) error_code & PAGE_FAULT_P) ? "true" : "false",
	    ((int) error_code & PAGE_FAULT_RW) ? "true" : "false",
	    ((int) error_code & PAGE_FAULT_US) ? "true" : "false",
	    linear_addr,
	    (int) (proc->tss.cr3));
 
    printf ("data start 0x%x, data end 0x%x, flags 0x%x\n",
	      (int) proc->vm_data.vm_start,
	      (int) proc->vm_data.vm_end,
	      (int) proc->vm_data.vm_flags);

    printf ("stack start 0x%x, stack end 0x%x, flags 0x%x\n",
	    (int) proc->vm_stack.vm_start,
	    (int) proc->vm_stack.vm_end,
	    (int) proc->vm_stack.vm_flags);

    while(1);
  }
}