I've been rewriting my operating system (in C++ )to provide full virtual memory support, but it seems I'm falling at the first hurdle. I try to map the pages, but the processor page-faults with a page not present error, even though I have mapped the page ???
Here's my virtual.cpp, containing paging init code and the MemMapPage method
Code: Select all
int VirtualMemManager::Init()
{
m_pageDirectory=(DWORD*)defPageManager.AllocatePage();
DWORD* firstPageTable=(DWORD*)defPageManager.AllocatePage();
if (!m_pageDirectory || !firstPageTable)
{
defConsole.Write("Out of memory in VirtualMemManager::Init");
}
DWORD address=0;
for (int i=0; i<1024; i++)
{
firstPageTable[i]=address | 7;
address+=4096;
}
m_pageDirectory[0]=(DWORD)firstPageTable | 7;
//Map it to itself so we can keep track of physical addresses of tables and the directory.
//Pretty much required for MemMapRange and friends
m_pageDirectory[1023]=(DWORD)m_pageDirectory | 7;
for (int i=1; i<1023; i++)
{
m_pageDirectory[i]=0;
}
//Put page directory address in cr3
setcr3((DWORD)m_pageDirectory);
defConsole.Print("pageDirectory = %u\n",m_pageDirectory);
//Enable paging in the control register
setcr0(getcr0() | 0x80000000);
return true;
}
//Maps a page of virtual memory to a page of physical memory
int VirtualMemManager::MemMapPage(DWORD virtualAddress,DWORD physicalAddress)
{
DWORD* address=(DWORD*)m_pageDirectory[1023];
int dirEntry=(virtualAddress >> 22);
int tableEntry=(virtualAddress >> 12)-((virtualAddress >> 22)*1024);
defConsole.Print("dirEntry = %d\ntableEntry = %d\n",dirEntry,tableEntry);
DWORD* pt=NULL;
//Get the directory entry of the virtual address, going through the mapped page directory
if (address[dirEntry] == 0)
{
DWORD page=defPageManager.AllocatePage();
defConsole.Write("New page table is being created\n");
defConsole.Print("page = %u\n",page);
address[dirEntry]= page | 7;
pt=(DWORD*)(address[dirEntry] & 0xFFFFF000);
}
pt=(DWORD*)(address[dirEntry] & 0xFFFFF000);
defConsole.Print("pt = %u\n",pt);
pt[tableEntry]=physicalAddress | 7;
asm volatile("invlpg %0" :: "m"(virtualAddress));
return true;
}
Here's my test for the MemMapPage function
Code: Select all
for (int i=0; i<1024; i++)
{
MemMapPage(0xC0000000+(i*4096),physPageManager.AllocatePage());
DWORD* a=(DWORD*)0xC0000000+(i*4096);
*a=0xDEADBEEF;
}
asm("sti");
CloudNine