Paging code doesn't work.
Posted: Sat Feb 18, 2006 5:35 pm
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;
}