#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
*/
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 ) == 0)
+ {
+ 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('-');
+ //LEAVE('-')
return;
}
MM_DumpTables(0, -1);
Panic("Page Fault at 0x%x\n", Regs->eip);
- LEAVE('-');
}
/**
*/
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;
}
/**
Uint MM_Clone()
{
Uint i, j;
- Uint kStackBase = gCurrentThread->KernelStack - KERNEL_STACK_SIZE;
+ Uint kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE;
void *tmp;
//ENTER("");
continue;
}
- #if USE_COW
// Refrence old page
MM_RefPhys( gaPageTable[i*1024+j] & ~0xFFF );
// Add to new table
}
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
}
}
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();
}
}