Paging

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
McZ

Paging

Post by McZ »

I have tried to create a function to map a virtual address to a physical address but I can't get it to work and my brain has overloaded and crashed... so it would be nice if someone could spot something I missed

Here is my code to map a virtual address (vaddr) to a physical address (paddr)

Code: Select all

int setPageTableEntry( struct PageDirectory_t *pd, unsigned long vaddr, unsigned long paddr, unsigned int flags )
{
   kprintf("vaddr 0x%X paddr 0x%X", (unsigned)vaddr, (unsigned int)ALIGN_4KB(paddr));
   unsigned int pdentry = ((vaddr/1024)/1024)/4;

   kprintf("pdentry %i", pdentry);

   /* Page directory entry */
   struct PageEntry_t *pde = &pd->Entry[pdentry];
   struct PageDirectory_t *pt = NULL;

   if( pde->flags & PEF_NOT_SET )
   {
      if( flags & PEF_NO_ALLOC )
         return 0;

      /* Needs to allocate a new PageTable */
      /* Not implemented yet */
      return 0;
   }
   else if( !(pde->flags & PEF_NOT_SET) )
   {
      pt = (struct PageDirectory_t *)(unsigned long)(pde->address << 11);
   }
   else
      return 0;

   /* Page table entry */
   unsigned int ptentry = (vaddr / 4096) % 1024;
   struct PageEntry_t *pte = &pt->Entry[ptentry];

   kprintf("ptentry %i", ptentry);

   if( flags & PEF_CLEAR )
      memset( pte, 0, sizeof(struct PageEntry_t) );

   if( pte->flags & PEF_NOT_SET )
      pte->flags &= ~PEF_NOT_SET;

   pte->flags       |= 0x7FF & flags;
   pte->address    = paddr >> 11;

   return 1;
}
here is some code how I use it

Code: Select all

for( vaddr=0; vaddr<SIZE_4MB; vaddr+=4096 )
{
   setPageTableEntry( &g_KernelPageDirectory, vaddr, vaddr, PEF_PRESENT | PEF_SUPERVISOR | PEF_READWRITE | PEF_CLEAR | PEF_NO_ALLOC);
   setPageTableEntry( &g_KernelPageDirectory, (0xC0000000 + vaddr), vaddr, PEF_PRESENT | PEF_SUPERVISOR | PEF_READWRITE | PEF_CLEAR | PEF_NO_ALLOC);
}
The problem is that if I don't have this loop bochs just resets and the bochsout.txt says I got a page fault

so if I have my old loop first it works..

Code: Select all

   for( vaddr=0; vaddr<SIZE_4MB; vaddr += 4096 )
   {
      g_LowPageTable.Entry[vaddr / 4096].flags = 0x3;
      g_LowPageTable.Entry[vaddr / 4096].address = (vaddr >> 11);

      g_KernelPageTable.Entry[vaddr / 4096].flags = 0x3;
      g_KernelPageTable.Entry[vaddr / 4096].address = (vaddr >> 11);
   }
why does it work if I run the above loop before I run the loop wit h my code?
proxy

Re:Paging

Post by proxy »

the most obvious thing i can think of is that you are not flushing the tlb entries when you update the page directory/page tables. You need to do so when you either add new pages or remove old ones.

proxy
McZ

Re:Paging

Post by McZ »

flush tlb? I havn't seen anything about that so I don't know what it is (and I will google for it) but I assume I don't do anything with the TLB anywhere so how come it works when I don't use my new function?

EDIT: I read a bit about flushing TLB but still don't know why I need it because I want to set the initial pages in paging paging is NOT already enabled it will be enabled after I have set cr3 which is after I have set the pagetable entries
Post Reply