* 0xFE - Unused
* 0xFF - System Calls / Kernel's User Code
*/
+#define DEBUG 1
#include <common.h>
#include <mm_phys.h>
#include <proc.h>
#define KERNEL_STACK_END 0xFD000000
#define PAGE_TABLE_ADDR 0xFD000000
#define PAGE_DIR_ADDR 0xFD3F4000
-//#define PAGE_CR3_ADDR 0xFD3F47F4
-//#define TMP_CR3_ADDR 0xFD3F47F8 // Part of core instead of temp
#define PAGE_CR3_ADDR 0xFD3F4FD0
#define TMP_CR3_ADDR 0xFD3F4FD4 // Part of core instead of temp
#define TMP_DIR_ADDR 0xFD3F5000 // Same
#define TEMP_MAP_ADDR 0xFEFF0000 // Allows 16 "temp" pages
#define NUM_TEMP_PAGES 16
-#define USE_COW 1
-
#define PF_PRESENT 0x1
#define PF_WRITE 0x2
#define PF_USER 0x4
// === IMPORTS ===
extern Uint32 gaInitPageDir[1024];
extern Uint32 gaInitPageTable[1024];
+extern void Threads_SegFault(Uint Addr);
// === PROTOTYPES ===
void MM_PreinitVirtual();
// === CODE ===
/**
* \fn void MM_PreinitVirtual()
+ * \brief Maps the fractal mappings
*/
void MM_PreinitVirtual()
{
gaInitPageDir[ 0 ] = 0;
gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((Uint)&gaInitPageDir - KERNEL_BASE) | 3;
}
+
/**
* \fn void MM_InstallVirtual()
+ * \brief Sets up the constant page mappings
*/
void MM_InstallVirtual()
{
*/
void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs)
{
- ENTER("xAddr bErrorCode", Addr, ErrorCode);
+ //ENTER("xAddr bErrorCode", Addr, ErrorCode);
// -- Check for COW --
if( gaPageDir [Addr>>22] & PF_PRESENT
&& gaPageTable[Addr>>12] & PF_COW )
{
tPAddr paddr;
- paddr = MM_DuplicatePage( Addr );
- MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF );
- gaPageTable[Addr>>12] &= PF_USER;
- gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE;
+ if(MM_GetRefCount( gaPageTable[Addr>>12] & ~0xFFF ) == 1)
+ {
+ gaPageTable[Addr>>12] &= ~PF_COW;
+ gaPageTable[Addr>>12] |= PF_PRESENT|PF_WRITE;
+ }
+ else
+ {
+ paddr = MM_DuplicatePage( Addr );
+ MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF );
+ gaPageTable[Addr>>12] &= PF_USER;
+ gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE;
+ }
+
INVLPG( Addr & ~0xFFF );
+ //LEAVE('-')
+ return;
+ }
+
+ // If it was a user, tell the thread handler
+ if(ErrorCode & 4) {
+ Threads_SegFault(Addr);
+ return ;
}
// -- Check Error Code --
MM_DumpTables(0, -1);
Panic("Page Fault at 0x%x\n", Regs->eip);
- LEAVE('-');
}
/**
const tPAddr MASK = ~0xF98;
Start >>= 12; End >>= 12;
+
+ Log("Directory Entries:");
+ for(page = Start >> 10;
+ page < (End >> 10)+1;
+ page ++)
+ {
+ if(gaPageDir[page])
+ {
+ Log(" 0x%08x-0x%08x :: 0x%08x",
+ page<<22, ((page+1)<<22)-1,
+ gaPageDir[page]&~0xFFF
+ );
+ }
+ }
+
+ Log("Table Entries:");
for(page = Start, curPos = Start<<12;
page < End;
curPos += 0x1000, page++)
|| (gaPageTable[page] & MASK) != expected)
{
if(expected) {
- Log("0x%08x-0x%08x => 0x%08x-0x%08x (%s%s%s%s)",
+ Log(" 0x%08x-0x%08x => 0x%08x-0x%08x (%s%s%s%s)",
rangeStart, curPos - 1,
gaPageTable[rangeStart>>12] & ~0xFFF,
(expected & ~0xFFF) - 1,
*/
tPAddr MM_Allocate(Uint VAddr)
{
+ tPAddr paddr;
// Check if the directory is mapped
if( gaPageDir[ VAddr >> 22 ] == 0 )
{
// Allocate directory
- gaPageDir[ VAddr >> 22 ] = MM_AllocPhys() | 3;
+ paddr = MM_AllocPhys();
+ if( paddr == 0 ) {
+ Warning("MM_Allocate - Out of Memory (Called by %p)", __builtin_return_address(0));
+ return 0;
+ }
+ // Map
+ gaPageDir[ VAddr >> 22 ] = paddr | 3;
// Mark as user
if(VAddr < MM_USER_MAX) gaPageDir[ VAddr >> 22 ] |= PF_USER;
}
// Check if the page is already allocated
else if( gaPageTable[ VAddr >> 12 ] != 0 ) {
- Warning("MM_Allocate - Allocating to used address");
+ Warning("MM_Allocate - Allocating to used address (%p)", VAddr);
return gaPageTable[ VAddr >> 12 ] & ~0xFFF;
}
// Allocate
- gaPageTable[ VAddr >> 12 ] = MM_AllocPhys() | 3;
+ paddr = MM_AllocPhys();
+ if( paddr == 0 ) {
+ Warning("MM_Allocate - Out of Memory when allocating at %p (Called by %p)",
+ VAddr, __builtin_return_address(0));
+ return 0;
+ }
+ // Map
+ gaPageTable[ VAddr >> 12 ] = paddr | 3;
// Mark as user
if(VAddr < MM_USER_MAX) gaPageTable[ VAddr >> 12 ] |= PF_USER;
// Invalidate Cache for address
INVLPG( VAddr & ~0xFFF );
- return gaPageTable[ VAddr >> 12 ] & ~0xFFF;
+ return paddr;
}
/**
}
MM_DerefPhys( gaPageDir[i] & ~0xFFF );
+ gaPageDir[i] = 0;
+ INVLPG( &gaPageTable[i*1024] );
}
+ INVLPG( gaPageDir );
-
- return *gTmpCR3;
+ return *gaPageCR3;
}
/**
Uint MM_Clone()
{
Uint i, j;
- Uint kStackBase = gCurrentThread->KernelStack - KERNEL_STACK_SIZE;
+ Uint page = 0;
+ Uint kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE;
void *tmp;
//ENTER("");
// Check if table is allocated
if( !(gaPageDir[i] & PF_PRESENT) ) {
gaTmpDir[i] = 0;
+ page += 1024;
continue;
}
// Allocate new table
gaTmpDir[i] = MM_AllocPhys() | (gaPageDir[i] & 7);
- INVLPG( &gaTmpTable[i*1024] );
+ INVLPG( &gaTmpTable[page] );
// Fill
- for( j = 0; j < 1024; j ++ )
+ for( j = 0; j < 1024; j ++, page++ )
{
- if( !(gaPageTable[i*1024+j] & PF_PRESENT) ) {
- gaTmpTable[i*1024+j] = 0;
+ if( !(gaPageTable[page] & PF_PRESENT) ) {
+ gaTmpTable[page] = 0;
continue;
}
- #if USE_COW
// Refrence old page
- MM_RefPhys( gaPageTable[i*1024+j] & ~0xFFF );
+ MM_RefPhys( gaPageTable[page] & ~0xFFF );
// Add to new table
- if(gaPageTable[i*1024+j] & PF_WRITE) {
- gaTmpTable[i*1024+j] = (gaPageTable[i*1024+j] & ~PF_WRITE) | PF_COW;
- gaPageTable[i*1024+j] = (gaPageTable[i*1024+j] & ~PF_WRITE) | PF_COW;
+ if(gaPageTable[page] & PF_WRITE) {
+ gaTmpTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW;
+ gaPageTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW;
+ INVLPG( page << 12 );
}
else
- gaTmpTable[i*1024+j] = gaPageTable[i*1024+j];
- LOG("gaTmpTable[0x%x] = 0x%x", i*1024+j, gaTmpTable[i*1024+j]);
- #else
- gaTmpTable[i*1024+j] = MM_DuplicatePage( (i*1024+j)<<12 ) | (gaPageTable[i*1024+j]&7);
- #endif
+ gaTmpTable[page] = gaPageTable[page];
}
}
if( Flags & MM_PFLAG_KERNEL ) *ent &= ~PF_USER;
else *ent |= PF_USER;
}
+
+ // Copy-On-Write
+ if( Mask & MM_PFLAG_COW )
+ {
+ if( Flags & MM_PFLAG_COW ) {
+ *ent &= ~PF_WRITE;
+ *ent |= PF_COW;
+ }
+ else {
+ *ent &= ~PF_COW;
+ *ent |= PF_WRITE;
+ }
+ }
}
/**
return TEMP_MAP_ADDR + (i << 12);
}
RELEASE( &gilTempMappings );
- Proc_Yield();
+ Threads_Yield();
}
}