Page 1 of 1

Paging code doesn't work.

Posted: Sat Feb 18, 2006 5:35 pm
by guest
When I try to run this code in my OS, it gives me a PF when I try to write to 0x80000000. And yes, I tested if SAFE_BASE is 4K aligned.

Code: Select all

//////////////////////////////////////////////////////////////
//   Internal AUX Functions
void KeMapAddress(unsigned long* pagetable, unsigned long* virtaddr, unsigned long* physaddr, unsigned long flags)
{
   unsigned long offset = (unsigned long)virtaddr / 4096 ;
   *(pagetable + offset) = (unsigned long)physaddr | flags;
}

void KeFillPageDirectory(unsigned long* pagedirectory, unsigned long* pagetable, unsigned long dpl)
{
   unsigned long flags;
   if(dpl == 0)
      flags = 3;
   else
      flags = 6;
   unsigned long index = 0;
   for(;index < 1024;index++)
      *(pagedirectory+index) = ( (unsigned long)pagetable + (index * 1024)) | flags;
}

void KeInitPageTable(unsigned long* pagetable)
{
   memset(pagetable, 0, 0x00400000);
}

void KeInitPageDirectory(unsigned long* pagedirectory)
{
   memset(pagedirectory, 0, 0x4000);
}

//////////////////////////////////////////////////////////////////////
//   Exports
void KeCreatePageTable(unsigned long* pagetable, void* usrmem, unsigned long length, 
                  void* usrstack, unsigned long stacklen,
                  void* usrcode, unsigned long codelen,
                  unsigned long dpl)
{
   const unsigned long rwpflag = dpl == 0 ? 3 : 6;
   const unsigned long rpflag = dpl == 0 ? 1 : 5;

   void* virtaddr = 0;
   void* physaddr = 0;
   ////////////////////////////////////////////////////////////////////
   //   
   for(;(unsigned long)virtaddr < (unsigned long)&end; virtaddr+=4096, physaddr+=4096)
      KeMapAddress(pagetable, virtaddr ,physaddr , rwpflag);

   
   for(virtaddr=KePageDirAddr,physaddr=KePageDirAddr;
         (unsigned long)virtaddr < ((unsigned long)KePageTableAddr+0x00100000); virtaddr+=4096, physaddr+=4096)
      KeMapAddress(pagetable, virtaddr, physaddr, dpl == 0 ? rwpflag : rpflag);

   for(virtaddr=KeUsrPageDirAddr,physaddr=KeUsrPageDirAddr;
         (unsigned long)virtaddr < ((unsigned long)KeUsrPageTableAddr+0x00100000); virtaddr += 4096, physaddr+=4096)
      KeMapAddress(pagetable, virtaddr, physaddr, dpl == 0 ? rwpflag : rpflag);

   if(codelen != 0)
      for(virtaddr=(unsigned long*)0x60000000,physaddr = usrcode;
            (unsigned long)virtaddr < (0x60000000+codelen);virtaddr+=4096,physaddr+=4096)
         KeMapAddress(pagetable, virtaddr, physaddr, rpflag);

   if(dpl != 0 && stacklen != 0)
      for(virtaddr=(unsigned long*)0x70000000,physaddr = usrstack ;
         (unsigned long)virtaddr < (0x70000000+stacklen);physaddr+=4096,virtaddr+=4096)
         KeMapAddress(pagetable, virtaddr, physaddr, rwpflag);

   if(length != 0)
      for(virtaddr=(unsigned long*)0x80000000,physaddr = usrmem ;
            (unsigned long)virtaddr < (0x80000000 + length); virtaddr+=4096, physaddr+=4096)
            KeMapAddress(pagetable, virtaddr, physaddr, rwpflag);
}

void KeInitPaging(void)
{

   unsigned long *pagetable = (unsigned long*)PAGETABLEADDR;
   unsigned long *pagedir = (unsigned long*)PAGEDIRADDR;
   KePageTableAddr = (unsigned long*)PAGETABLEADDR;
   KePageDirAddr = (unsigned long*)PAGEDIRADDR;
   KeUsrPageTableAddr = (unsigned long*)USRPAGETABLEADDR;
   KeUsrPageDirAddr = (unsigned long*)USRPAGEDIRADDR;


   KeInitPageTable(pagetable);
   KeInitPageDirectory(pagedir);
   KeCreatePageTable(pagetable,SAFE_BASE,0x02000000,NULL,0,NULL,0,0); 
   KeFillPageDirectory(pagedir,pagetable,0);
   KeWriteCR3((unsigned long)pagedir);
   KeWriteCR0(0x80000000 | KeReadCR0());


   *((unsigned long*)0x80000000) = (unsigned long)SAFE_BASE;
   *((unsigned long*)0x80000004) = 0x02000000;
}   

Re:Paging code doesn't work.

Posted: Sun Feb 19, 2006 4:18 am
by Pype.Clicker
if you're running in bochs or QEMU, you may want to use the "xp /64 0xcafebabe" command (where "cafebabe" is the physical address of pagetables and page directory) to check everything is in place as you expect it to be ...