void Multiboot_FreeModules(const int ModuleCount, tBootModule *Modules) { for( int i = 0; i < ModuleCount; i ++ ) { Uint ofs = Modules[i].PBase % PAGE_SIZE; Uint nPages = (Modules[i].Size+ofs+PAGE_SIZE-1) / PAGE_SIZE; MM_UnmapHWPages(Modules[i].Base, nPages); MM_UnmapHWPages(Modules[i].ArgString, 2); // TODO: handle previous freeing of this page for( int pg = 0; pg < nPages; pg ++ ) MM_DerefPhys( Modules[i].PBase + pg*PAGE_SIZE ); } free(Modules); }
/** * \brief Clone a page from an entry * \param Ent Pointer to the entry in the PML4/PDP/PD/PT * \param NextLevel Pointer to contents of the entry * \param Addr Dest address * \note Used in COW */ 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); } if( MM_GetRefCount( curpage ) == 1 ) { *Ent &= ~PF_COW; *Ent |= PF_PRESENT|PF_WRITE; #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage); #endif } else { void *tmp; tPAddr paddr; if( !(paddr = MM_AllocPhys()) ) { Threads_SegFault(Addr); return ; } ASSERT(paddr != curpage); tmp = MM_MapTemp(paddr); memcpy( tmp, NextLevel, 0x1000 ); MM_FreeTemp( tmp ); #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr); #endif MM_DerefPhys( curpage ); *Ent &= PF_USER; *Ent |= paddr|PF_PRESENT|PF_WRITE; bCopied = 1; } INVLPG( (tVAddr)NextLevel ); // 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; if( bCopied ) MM_RefPhys( dp[i] & PADDR_MASK ); if( dp[i] & PF_WRITE ) { dp[i] &= ~PF_WRITE; dp[i] |= PF_COW; } } } }