X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fmm_virt.c;h=970e957541562dec39c14c37c08a14b9e0a096e6;hb=17aac974ab83a3521f2b49b8de33ae05a00fbe07;hp=424547ac17e1eb38b90d92d6c34959c757c89444;hpb=b04d5d338a1d6df261e74675247f59395603ede3;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 424547ac..970e9575 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -16,12 +16,7 @@ #include #include -#if USE_PAE -# define TAB 21 -# define DIR 30 -#else -# define TAB 22 -#endif +#define TAB 22 #define KERNEL_STACKS 0xF0000000 #define KERNEL_STACK_SIZE 0x00008000 @@ -61,11 +56,7 @@ #define INVLPG(addr) __asm__ __volatile__ ("invlpg (%0)"::"r"(addr)) -#if USE_PAE -typedef Uint64 tTabEnt; -#else typedef Uint32 tTabEnt; -#endif // === IMPORTS === extern void _UsertextEnd, _UsertextBase; @@ -116,11 +107,7 @@ struct sPageInfo { */ void MM_PreinitVirtual(void) { - #if USE_PAE - gaInitPageDir[ ((PAGE_TABLE_ADDR >> TAB)-3*512+3)*2 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3; - #else gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3; - #endif INVLPG( PAGE_TABLE_ADDR ); } @@ -132,23 +119,6 @@ void MM_InstallVirtual(void) { int i; - #if USE_PAE - // --- Pre-Allocate kernel tables - for( i = KERNEL_BASE >> TAB; i < 1024*4; i ++ ) - { - if( gaPAE_PageDir[ i ] ) continue; - - // Skip stack tables, they are process unique - if( i > KERNEL_STACKS >> TAB && i < KERNEL_STACKS_END >> TAB) { - gaPAE_PageDir[ i ] = 0; - continue; - } - // Preallocate table - gaPAE_PageDir[ i ] = MM_AllocPhys() | 3; - INVLPG( &gaPAE_PageTable[i*512] ); - memset( &gaPAE_PageTable[i*512], 0, 0x1000 ); - } - #else // --- Pre-Allocate kernel tables for( i = KERNEL_BASE>>22; i < 1024; i ++ ) { @@ -163,7 +133,6 @@ void MM_InstallVirtual(void) INVLPG( &gaPageTable[i*1024] ); memset( &gaPageTable[i*1024], 0, 0x1000 ); } - #endif // Unset kernel on the User Text pages for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) { @@ -176,11 +145,7 @@ void MM_InstallVirtual(void) */ void MM_FinishVirtualInit(void) { - #if USE_PAE - gaInitPDPT[ 0 ] = 0; - #else gaInitPageDir[ 0 ] = 0; - #endif } /** @@ -210,19 +175,23 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE; } + Log_Debug("MMVirt", "COW for %p (%P)", Addr, gaPageTable[Addr>>12]); + INVLPG( Addr & ~0xFFF ); return; } + __asm__ __volatile__ ("pushf; andw $0xFEFF, 0(%esp); popf"); + Proc_GetCurThread()->bInstrTrace = 0; + // If it was a user, tell the thread handler if(ErrorCode & 4) { - Warning("%s %s %s memory%s", - (ErrorCode&4?"User":"Kernel"), + Log_Warning("MMVirt", "User %s %s memory%s", (ErrorCode&2?"write to":"read from"), (ErrorCode&1?"bad/locked":"non-present"), (ErrorCode&16?" (Instruction Fetch)":"") ); - Warning("User Pagefault: Instruction at %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr); + Log_Warning("MMVirt", "Instruction %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr); __asm__ __volatile__ ("sti"); // Restart IRQs #if 1 Error_Backtrace(Regs->eip, Regs->ebp); @@ -238,8 +207,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) Warning("Reserved Bits Trashed!"); else { - Warning("%s %s %s memory%s", - (ErrorCode&4?"User":"Kernel"), + Warning("Kernel %s %s memory%s", (ErrorCode&2?"write to":"read from"), (ErrorCode&1?"bad/locked":"non-present"), (ErrorCode&16?" (Instruction Fetch)":"") @@ -280,6 +248,7 @@ void MM_DumpTables(tVAddr Start, tVAddr End) { tVAddr rangeStart = 0; tPAddr expected = 0; + void *expected_node = NULL, *tmpnode = NULL; tVAddr curPos; Uint page; const tPAddr MASK = ~0xF78; @@ -309,19 +278,21 @@ void MM_DumpTables(tVAddr Start, tVAddr End) { if( !(gaPageDir[curPos>>22] & PF_PRESENT) || !(gaPageTable[page] & PF_PRESENT) - || (gaPageTable[page] & MASK) != expected) + || (gaPageTable[page] & MASK) != expected + || (tmpnode=NULL,MM_GetPageNode(expected, &tmpnode), tmpnode != expected_node)) { if(expected) { - Log(" 0x%08x => 0x%08x - 0x%08x (%s%s%s%s%s)", + tPAddr orig = gaPageTable[rangeStart>>12]; + Log(" 0x%08x => 0x%08x - 0x%08x (%s%s%s%s%s) %p", 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" : "-"), - gaPageTable[page] & MASK, expected + (orig & PF_NOPAGE ? "P" : "-"), + (orig & PF_COW ? "C" : "-"), + (orig & PF_GLOBAL ? "G" : "-"), + (orig & PF_USER ? "U" : "-"), + (orig & PF_WRITE ? "W" : "-"), + expected_node ); expected = 0; } @@ -329,20 +300,24 @@ void MM_DumpTables(tVAddr Start, tVAddr End) if( !(gaPageTable[curPos>>12] & PF_PRESENT) ) continue; expected = (gaPageTable[page] & MASK); + MM_GetPageNode(expected, &expected_node); rangeStart = curPos; } if(expected) expected += 0x1000; } if(expected) { - Log("0x%08x => 0x%08x - 0x%08x (%s%s%s%s)", + tPAddr orig = gaPageTable[rangeStart>>12]; + Log("0x%08x => 0x%08x - 0x%08x (%s%s%s%s%s) %p", rangeStart, - gaPageTable[rangeStart>>12] & ~0xFFF, + orig & ~0xFFF, curPos - rangeStart, - (expected & PF_NOPAGE ? "p" : "-"), - (expected & PF_COW ? "C" : "-"), - (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_node ); expected = 0; } @@ -463,7 +438,10 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) // 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; @@ -546,6 +524,10 @@ tPAddr MM_Clone(void) // 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 ); @@ -698,18 +680,11 @@ tVAddr MM_NewKStack(void) * \fn tVAddr MM_NewWorkerStack() * \brief Creates a new worker stack */ -tVAddr MM_NewWorkerStack() +tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) { - Uint esp, ebp; - Uint oldstack; Uint base, addr; - int i, j; - Uint *tmpPage; - tPAddr pages[WORKER_STACK_SIZE>>12]; - - // Get the old ESP and EBP - __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); - __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); + tVAddr tmpPage; + tPAddr page; // TODO: Thread safety // Find a free worker stack address @@ -759,44 +734,22 @@ tVAddr MM_NewWorkerStack() // Mapping Time! for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 ) - //for( addr = WORKER_STACK_SIZE; addr; addr -= 0x1000 ) { - pages[ addr >> 12 ] = MM_AllocPhys(); - gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; + page = MM_AllocPhys(); + gaTmpTable[ (base + addr) >> 12 ] = page | 3; } *gpTmpCR3 = 0; // Release the temp mapping lock Mutex_Release(&glTempFractal); - - // Copy the old stack - oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1); - esp = oldstack - esp; // ESP as an offset in the stack - - // Make `base` be the top of the stack - base += WORKER_STACK_SIZE; - - i = (WORKER_STACK_SIZE>>12) - 1; - // Copy the contents of the old stack to the new one, altering the addresses - // `addr` is refering to bytes from the stack base (mem downwards) - for(addr = 0; addr < esp; addr += 0x1000) - { - Uint *stack = (Uint*)( oldstack-(addr+0x1000) ); - tmpPage = (void*)MM_MapTemp( pages[i] ); - // Copy old stack - for(j = 0; j < 1024; j++) - { - // Possible Stack address? - if(oldstack-esp < stack[j] && stack[j] < oldstack) - tmpPage[j] = base - (oldstack - stack[j]); - else // Seems not, best leave it alone - tmpPage[j] = stack[j]; - } - MM_FreeTemp((tVAddr)tmpPage); - i --; - } + + // NOTE: Max of 1 page + // `page` is the last allocated page from the previious for loop + tmpPage = MM_MapTemp( page ); + memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize); + MM_FreeTemp(tmpPage); //Log("MM_NewWorkerStack: RETURN 0x%x", base); - return base; + return base + WORKER_STACK_SIZE; } /** @@ -897,6 +850,9 @@ tPAddr MM_DuplicatePage(tVAddr VAddr) // 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); @@ -1033,6 +989,10 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) 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) {