X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fmm_virt.c;h=511803cceb0fed6c2e03dfd0bf867a37c1252082;hb=7aa331d83b8dd23d3ca7530fa582cec528df274a;hp=1bb890c60abc499ec31ecf39615987e402764a51;hpb=91b827b426e90f73486303fdac17c2686dba53dc;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index 1bb890c6..511803cc 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -8,6 +8,7 @@ #include #include #include +#include // === CONSTANTS === #define PHYS_BITS 52 // TODO: Move out @@ -64,13 +65,13 @@ void MM_InitVirt(void); void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable ); int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs); void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected); -void MM_DumpTables(tVAddr Start, tVAddr End); +//void MM_DumpTables(tVAddr Start, tVAddr End); int MM_GetPageEntryPtr(tVAddr Addr, BOOL bTemp, BOOL bAllocate, BOOL bLargePage, tPAddr **Pointer); int MM_MapEx(tVAddr VAddr, tPAddr PAddr, BOOL bTemp, BOOL bLarge); // int MM_Map(tVAddr VAddr, tPAddr PAddr); void MM_Unmap(tVAddr VAddr); void MM_int_ClearTableLevel(tVAddr VAddr, int LevelBits, int MaxEnts); -void MM_ClearUser(void); +//void MM_ClearUser(void); int MM_GetPageEntry(tVAddr Addr, tPAddr *Phys, Uint *Flags); // === GLOBALS === @@ -80,7 +81,7 @@ tPAddr gMM_ZeroPage; // === CODE === void MM_InitVirt(void) { - Log_Debug("MMVirt", "&PAGEMAPLVL4(0) = %p", &PAGEMAPLVL4(0)); +// Log_Debug("MMVirt", "&PAGEMAPLVL4(0) = %p", &PAGEMAPLVL4(0)); // MM_DumpTables(0, -1L); } @@ -99,6 +100,8 @@ void MM_FinishVirtualInit(void) void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable ) { tPAddr curpage = *Ent & PADDR_MASK; + int bCopied = 0; + if( MM_GetRefCount( curpage ) <= 0 ) { Log_KernelPanic("MMVirt", "Page %P still marked COW, but unreferenced", curpage); } @@ -106,6 +109,7 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable { *Ent &= ~PF_COW; *Ent |= PF_PRESENT|PF_WRITE; + Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage); } else { @@ -123,23 +127,28 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable memcpy( tmp, NextLevel, 0x1000 ); MM_FreeTemp( (tVAddr)tmp ); -// Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr); + Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr); MM_DerefPhys( curpage ); *Ent &= PF_USER; *Ent |= paddr|PF_PRESENT|PF_WRITE; + + bCopied = 1; } INVLPG( (tVAddr)NextLevel ); - // Mark COW on pages + // Mark COW on contents if it's a PDPT, Dir or Table if(bTable) { Uint64 *dp = NextLevel; int i; for( i = 0; i < 512; i ++ ) { - if( !(dp[i] & PF_PRESENT) ) continue; - MM_RefPhys( dp[i] & PADDR_MASK ); + if( !(dp[i] & PF_PRESENT) ) + continue; + + if( bCopied ) + MM_RefPhys( dp[i] & PADDR_MASK ); if( dp[i] & PF_WRITE ) { dp[i] &= ~PF_WRITE; dp[i] |= PF_COW; @@ -153,6 +162,25 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable */ int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) { +// Log_Debug("MMVirt", "Addr = %p, ErrorCode = %x", Addr, ErrorCode); + + // Catch reserved bits first + if( ErrorCode & 0x8 ) + { + Log_Warning("MMVirt", "Reserved bits trashed!"); + Log_Warning("MMVirt", "PML4 Ent = %P", PAGEMAPLVL4(Addr>>39)); + if( !(PAGEMAPLVL4(Addr>>39) & PF_PRESENT) ) goto print_done; + Log_Warning("MMVirt", "PDP Ent = %P", PAGEDIRPTR(Addr>>30)); + if( !(PAGEDIRPTR(Addr>>30) & PF_PRESENT) ) goto print_done; + Log_Warning("MMVirt", "PDir Ent = %P", PAGEDIR(Addr>>21)); + if( !(PAGEDIR(Addr>>21) & PF_PRESENT) ) goto print_done; + Log_Warning("MMVirt", "PTable Ent = %P", PAGETABLE(Addr>>12)); + if( !(PAGETABLE(Addr>>12) & PF_PRESENT) ) goto print_done; + print_done: + + for(;;); + } + // TODO: Implement Copy-on-Write #if 1 if( PAGEMAPLVL4(Addr>>39) & PF_PRESENT @@ -201,6 +229,7 @@ int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) Warning("User Pagefault: Instruction at %04x:%p accessed %p", Regs->CS, Regs->RIP, Addr); __asm__ __volatile__ ("sti"); // Restart IRQs + Error_Backtrace(Regs->RIP, Regs->RBP); Threads_SegFault(Addr); return 0; } @@ -231,12 +260,13 @@ int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected) { #define CANOICAL(addr) ((addr)&0x800000000000?(addr)|0xFFFF000000000000:(addr)) - LogF("%6llx %6llx %6llx %016llx => ", - MM_GetPhysAddr( (tVAddr)&PAGEDIRPTR(RangeStart>>30) ), - MM_GetPhysAddr( (tVAddr)&PAGEDIR(RangeStart>>21) ), - MM_GetPhysAddr( (tVAddr)&PAGETABLE(RangeStart>>12) ), - CANOICAL(RangeStart) - ); + LogF("%016llx => ", CANOICAL(RangeStart)); +// LogF("%6llx %6llx %6llx %016llx => ", +// MM_GetPhysAddr( (tVAddr)&PAGEDIRPTR(RangeStart>>30) ), +// MM_GetPhysAddr( (tVAddr)&PAGEDIR(RangeStart>>21) ), +// MM_GetPhysAddr( (tVAddr)&PAGETABLE(RangeStart>>12) ), +// CANOICAL(RangeStart) +// ); if( gMM_ZeroPage && (PAGETABLE(RangeStart>>12) & PADDR_MASK) == gMM_ZeroPage ) LogF("%13s", "zero" ); else @@ -413,7 +443,7 @@ int MM_MapEx(tVAddr VAddr, tPAddr PAddr, BOOL bTemp, BOOL bLarge) tPAddr *ent; int rv; - ENTER("xVAddr xPAddr", VAddr, PAddr); + ENTER("pVAddr PPAddr", VAddr, PAddr); // Get page pointer (Allow allocating) rv = MM_GetPageEntryPtr(VAddr, bTemp, 1, bLarge, &ent); @@ -647,6 +677,58 @@ Uint MM_GetFlags(tVAddr VAddr) return ret; } +/** + * \brief Check if the provided buffer is valid + * \return Boolean valid + */ +int MM_IsValidBuffer(tVAddr Addr, size_t Size) +{ + int bIsUser; + Uint64 pml4, pdp, dir, tab; + + Size += Addr & (PAGE_SIZE-1); + Addr &= ~(PAGE_SIZE-1); + Addr &= ((1UL << 48)-1); // Clap to address space + + pml4 = Addr >> 39; + pdp = Addr >> 30; + dir = Addr >> 21; + tab = Addr >> 12; + + if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; + if( !(PAGEDIRPTR(pdp) & 1) ) return 0; + if( !(PAGEDIR(dir) & 1) ) return 0; + if( !(PAGETABLE(tab) & 1) ) return 0; + + bIsUser = !!(PAGETABLE(tab) & PF_USER); + + while( Size >= PAGE_SIZE ) + { + if( (tab & 511) == 0 ) + { + dir ++; + if( ((dir >> 9) & 511) == 0 ) + { + pdp ++; + if( ((pdp >> 18) & 511) == 0 ) + { + pml4 ++; + if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; + } + if( !(PAGEDIRPTR(pdp) & 1) ) return 0; + } + if( !(PAGEDIR(dir) & 1) ) return 0; + } + + if( !(PAGETABLE(tab) & 1) ) return 0; + if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0; + + tab ++; + Size -= PAGE_SIZE; + } + return 1; +} + // --- Hardware Mappings --- /** * \brief Map a range of hardware pages @@ -665,6 +747,8 @@ tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) } if( num >= 0 ) continue; +// Log_Debug("MMVirt", "Mapping %i pages to %p (base %P)", Number, ret-Number*0x1000, PAddr); + PAddr += 0x1000 * Number; while( Number -- ) @@ -678,7 +762,7 @@ tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) return ret; } - Log_KernelPanic("MM", "TODO: Implement MM_MapHWPages"); + Log_Error("MM", "MM_MapHWPages - No space for %i pages", Number); return 0; } @@ -810,28 +894,31 @@ tPAddr MM_Clone(void) { // Skip addresses: // 320 0xFFFFA.... - Kernel Stacks - if( i == 320 ) continue; + if( i == MM_KSTACK_BASE>>39 ) continue; // 509 0xFFFFFE0.. - Fractal mapping - if( i == 508 ) continue; + if( i == MM_FRACTAL_BASE>>39 ) continue; // 510 0xFFFFFE8.. - Temp fractal mapping - if( i == 509 ) continue; + if( i == MM_TMPFRAC_BASE>>39 ) continue; TMPMAPLVL4(i) = PAGEMAPLVL4(i); if( TMPMAPLVL4(i) & 1 ) MM_RefPhys( TMPMAPLVL4(i) & PADDR_MASK ); } + + // Mark Per-Process data as COW + TMPMAPLVL4(MM_PPD_BASE>>39) |= PF_COW; + TMPMAPLVL4(MM_PPD_BASE>>39) &= ~PF_WRITE; // #5 Set fractal mapping - TMPMAPLVL4(508) = ret | 3; // Main - TMPMAPLVL4(509) = 0; // Temp + TMPMAPLVL4(MM_FRACTAL_BASE>>39) = ret | 3; // Main + TMPMAPLVL4(MM_TMPFRAC_BASE>>39) = 0; // Temp // #6 Create kernel stack // tThread->KernelStack is the top // There is 1 guard page below the stack kstackbase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; - Log("MM_Clone: kstackbase = %p", kstackbase); - + // Clone stack TMPMAPLVL4(MM_KSTACK_BASE >> PML4_SHIFT) = 0; for( i = 1; i < KERNEL_STACK_SIZE/0x1000; i ++ ) { @@ -839,9 +926,6 @@ tPAddr MM_Clone(void) tVAddr tmpmapping; MM_MapEx(kstackbase+i*0x1000, phys, 1, 0); - Log_Debug("MM", "MM_Clone: Cloning stack page %p from %P to %P", - kstackbase+i*0x1000, MM_GetPhysAddr( kstackbase+i*0x1000 ), phys - ); tmpmapping = MM_MapTemp(phys); if( MM_GetPhysAddr( kstackbase+i*0x1000 ) ) memcpy((void*)tmpmapping, (void*)(kstackbase+i*0x1000), 0x1000); @@ -867,7 +951,7 @@ void MM_int_ClearTableLevel(tVAddr VAddr, int LevelBits, int MaxEnts) Uint64 * const table_bases[] = {&PAGETABLE(0), &PAGEDIR(0), &PAGEDIRPTR(0), &PAGEMAPLVL4(0)}; Uint64 *table = table_bases[(LevelBits-12)/9] + (VAddr >> LevelBits); int i; - Log("MM_int_ClearTableLevel: (VAddr=%p, LevelBits=%i, MaxEnts=%i)", VAddr, LevelBits, MaxEnts); +// Log("MM_int_ClearTableLevel: (VAddr=%p, LevelBits=%i, MaxEnts=%i)", VAddr, LevelBits, MaxEnts); for( i = 0; i < MaxEnts; i ++ ) { // Skip non-present tables