Esempio n. 1
0
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);
}
Esempio n. 2
0
/**
 * \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;
			}
		}
	}
}