// === IMPORTS ===
extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
extern void VM8086_GPF(tRegs *Regs);
-extern void Threads_Dump(void);
+extern void Threads_Dump(void);
extern void Threads_Fault(int Num);
extern int GetCPUNum(void);
+extern void MM_DumpTables(tVAddr, tVAddr);
// === PROTOTYPES ===
void __stack_chk_fail(void);
// === GLOBALS ===
const char *csaERROR_NAMES[] = {
"Divide By Zero", "Debug", "NMI Exception", "INT3",
- "INTO", "Out of Bounds", "Invalid Opcode", "Coprocessor not avaliable",
+ "INTO Instr - Overflow", "BOUND Instr - Out of Bounds", "Invalid Opcode", "Coprocessor not avaliable",
"Double Fault", "Coprocessor Segment Overrun", "Bad TSS", "Segment Not Present",
"Stack Fault Exception", "GPF", "#PF", "Reserved",
"Floating Point Exception", "Alignment Check Exception", "Machine Check Exception", "Reserved",
csaERROR_NAMES[Regs->int_num], Regs->err_code);
Log_Warning("Arch", "at CS:EIP %04x:%08x",
Regs->cs, Regs->eip);
+ MM_DumpTables(0, KERNEL_BASE);
switch( Regs->int_num )
{
// Division by Zero
Uint32 gaSuperBitmap[1024]; // Blocks of 1024 Pages
Uint32 gaPageBitmap[1024*1024/32]; // Individual pages
int *gaPageReferences;
+void **gaPageNodes = (void*)MM_PAGENODE_BASE;
#define REFENT_PER_PAGE (0x1000/sizeof(gaPageReferences[0]))
// === CODE ===
if(gaPageBitmap[ PAddr / 32 ] == 0)
gaSuperBitmap[ PAddr >> 10 ] &= ~(1 << ((PAddr >> 5)&31));
}
+
+ if( MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) )
+ {
+ gaPageNodes[PAddr] = NULL;
+ // TODO: Free Node Page when fully unused
+ }
// Release spinlock
Mutex_Release( &glPhysAlloc );
return gaPageReferences[ PAddr ];
}
+int MM_SetPageNode(tPAddr PAddr, void *Node)
+{
+ tVAddr block_addr;
+
+ if( MM_GetRefCount(PAddr) == 0 ) return 1;
+
+ PAddr /= PAGE_SIZE;
+
+ block_addr = (tVAddr) &gaPageNodes[PAddr];
+ block_addr &= ~(PAGE_SIZE-1);
+
+ if( !MM_GetPhysAddr( block_addr ) )
+ {
+ if( !MM_Allocate( block_addr ) ) {
+ Log_Warning("PMem", "Unable to allocate Node page");
+ return -1;
+ }
+ memset( (void*)block_addr, 0, PAGE_SIZE );
+ }
+
+ gaPageNodes[PAddr] = Node;
+ return 0;
+}
+
+int MM_GetPageNode(tPAddr PAddr, void **Node)
+{
+ if( MM_GetRefCount(PAddr) == 0 ) {
+ return 1;
+ }
+ if( !MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) {
+ *Node = NULL;
+ return 0;
+ }
+ *Node = gaPageNodes[PAddr];
+ return 0;
+}
+
gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE;
}
+ Log_Debug("MMVirt", "COW for %p", Addr);
+
INVLPG( Addr & ~0xFFF );
return;
}
// If it was a user, tell the thread handler
if(ErrorCode & 4) {
- Warning("%s %s %s memory%s",
+ Log_Warning("MMVirt", "%s %s %s memory%s",
(ErrorCode&4?"User":"Kernel"),
(ErrorCode&2?"write to":"read from"),
(ErrorCode&1?"bad/locked":"non-present"),
|| (gaPageTable[page] & MASK) != expected)
{
if(expected) {
+ tPAddr orig = gaPageTable[rangeStart>>12];
Log(" 0x%08x => 0x%08x - 0x%08x (%s%s%s%s%s)",
rangeStart,
- gaPageTable[rangeStart>>12] & ~0xFFF,
+ orig & ~0xFFF,
curPos - rangeStart,
- (expected & PF_NOPAGE ? "P" : "-"),
- (expected & PF_COW ? "C" : "-"),
- (expected & PF_GLOBAL ? "G" : "-"),
- (expected & PF_USER ? "U" : "-"),
- (expected & PF_WRITE ? "W" : "-")
+ (orig & PF_NOPAGE ? "P" : "-"),
+ (orig & PF_COW ? "C" : "-"),
+ (orig & PF_GLOBAL ? "G" : "-"),
+ (orig & PF_USER ? "U" : "-"),
+ (orig & PF_WRITE ? "W" : "-")
);
expected = 0;
}
// Check if the directory is mapped
if( gaPageDir[ VAddr >> 22 ] == 0 )
{
- gaPageDir[ VAddr >> 22 ] = MM_AllocPhys() | 3;
+ tPAddr tmp = MM_AllocPhys();
+ if( tmp == 0 )
+ return 0;
+ gaPageDir[ VAddr >> 22 ] = tmp | 3;
// Mark as user
if(VAddr < MM_USER_MAX) gaPageDir[ VAddr >> 22 ] |= PF_USER;
// Create Directory Table
*gpTmpCR3 = MM_AllocPhys() | 3;
+ if( *gpTmpCR3 == 3 ) {
+ *gpTmpCR3 = 0;
+ return 0;
+ }
INVLPG( gaTmpDir );
//LOG("Allocated Directory (%x)", *gpTmpCR3);
memsetd( gaTmpDir, 0, 1024 );
// Allocate new page
ret = MM_AllocPhys();
+ if( !ret ) {
+ return 0;
+ }
// Write-lock the page (to keep data constistent), saving its R/W state
wasRO = (gaPageTable[VAddr >> 12] & PF_WRITE ? 0 : 1);
if(Pages == 1 && MaxBits >= PHYS_BITS)
{
phys = MM_AllocPhys();
+ if( !phys ) {
+ *PhysAddr = 0;
+ LEAVE_RET('i', 0);
+ }
*PhysAddr = phys;
ret = MM_MapHWPages(phys, 1);
if(ret == 0) {
// Map ROM Area
for(i=0xA0;i<0x100;i++) {
MM_Map( i * 0x1000, i * 0x1000 );
- // MM_SetFlags( i * 0x1000, MM_PFLAG_RO, MM_PFLAG_RO ); // Set Read Only
}
Log_Debug("VM8086", "ROM area mapped");
MM_Map( 0, 0 ); // IVT / BDA
for(i=1;i<0x9F;i++) {
MM_Map( i * 0x1000, i * 0x1000 );
MM_DerefPhys( i * 0x1000 ); // Above
- if(MM_GetRefCount(i*0x1000))
+ while(MM_GetRefCount(i*0x1000))
MM_DerefPhys( i * 0x1000 ); // Phys setup
}
MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA
{
State->IP = *(Uint16*)(KERNEL_BASE+4*Interrupt);
State->CS = *(Uint16*)(KERNEL_BASE+4*Interrupt+2);
+
+// Log_Debug("VM8086", "Software interrupt %i to %04x:%04x", Interrupt, State->CS, State->IP);
Mutex_Acquire( &glVM8086_Process );