kernel/eka/memmodel/epoc/multiple/arm/xmmu.cpp
branchRCL_3
changeset 87 2f92ad2dc5db
parent 31 56f325a607ea
child 109 b3a1d9898418
child 110 c734af59ce98
equal deleted inserted replaced
81:e7d2d738d3c2 87:2f92ad2dc5db
   363 		aPhysicalAddress = physStart;
   363 		aPhysicalAddress = physStart;
   364 		return KErrNone;
   364 		return KErrNone;
   365 		}
   365 		}
   366 	}
   366 	}
   367 
   367 
       
   368 
   368 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TInt aOsAsid, TPhysAddr* aPhysicalPageList)
   369 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TInt aOsAsid, TPhysAddr* aPhysicalPageList)
   369 //Returns the list of physical pages belonging to the specified memory space.
   370 //Returns the list of physical pages belonging to the specified memory space.
   370 //Checks these pages belong to a chunk marked as being trusted. 
   371 //Checks these pages belong to a chunk marked as being trusted. 
   371 //Locks these pages so they can not be moved by e.g. ram defragmenation.
   372 //Locks these pages so they can not be moved by e.g. ram defragmentation.
   372 	{
   373 	{
   373 	SPageInfo* pi = NULL;
   374 	SPageInfo* pi = NULL;
   374 	DChunk* chunk = NULL;
   375 	DChunk* chunk = NULL;
   375 	TInt err = KErrNone;
   376 	TInt err = KErrNone;
       
   377 
       
   378 	__NK_ASSERT_DEBUG(MM::MaxPagesInOneGo == 32);	// Needs to be a power of 2.
       
   379 	TUint flashMask = MM::MaxPagesInOneGo - 1;
   376 	
   380 	
   377 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize,aOsAsid));
   381 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize,aOsAsid));
   378 
   382 
   379 	TUint32* pageList = aPhysicalPageList;
   383 	TUint32* pageList = aPhysicalPageList;
   380 	TInt pagesInList = 0;				//The number of pages we put in the list so far
   384 	TInt pagesInList = 0;				//The number of pages we put in the list so far
   386 
   390 
   387 
   391 
   388 	MmuBase::Wait(); 	// RamAlloc Mutex for accessing page/directory tables.
   392 	MmuBase::Wait(); 	// RamAlloc Mutex for accessing page/directory tables.
   389 	NKern::LockSystem();// SystemlLock for accessing SPageInfo objects.
   393 	NKern::LockSystem();// SystemlLock for accessing SPageInfo objects.
   390 
   394 
       
   395 	// Get the page directory entry that maps aLinAddr.
       
   396 	// If the address is in the global region check whether this asid maps
       
   397 	// global pdes (i.e. the LSB of iAsidInfo is set), if not find the pde from 
       
   398 	// the kernel's initial page directory.
   391 	TPde* pdePtr = (pdeIndex<(iLocalPdSize>>2) || (iAsidInfo[aOsAsid]&1)) ? PageDirectory(aOsAsid) : ::InitPageDirectory;
   399 	TPde* pdePtr = (pdeIndex<(iLocalPdSize>>2) || (iAsidInfo[aOsAsid]&1)) ? PageDirectory(aOsAsid) : ::InitPageDirectory;
   392 	pdePtr += pdeIndex;//This points to the first pde 
   400 	pdePtr += pdeIndex;//This points to the first pde 
   393 
   401 
   394 	while(pagesLeft)
   402 	while(pagesLeft)
   395 		{
   403 		{
   397 		if(pagesLeftInChunk>pagesLeft)
   405 		if(pagesLeftInChunk>pagesLeft)
   398 			pagesLeftInChunk = pagesLeft;
   406 			pagesLeftInChunk = pagesLeft;
   399 		
   407 		
   400 		pagesLeft -= pagesLeftInChunk;
   408 		pagesLeft -= pagesLeftInChunk;
   401 
   409 
   402 		TPte* pt = SafePageTableFromPde(*pdePtr++);
   410 		TPte* pPte = SafePageTableFromPde(*pdePtr++);
   403 		if(!pt) { err = KErrNotFound; goto fail; }// Cannot get page table.
   411 		if(!pPte) 
       
   412 			{// Cannot get page table. 
       
   413 			err = KErrNotFound; 
       
   414 			goto fail; 
       
   415 			}
   404 		
   416 		
   405 		pt += pageIndex;
   417 		pPte += pageIndex;
   406 
   418 
   407 		for(;pagesLeftInChunk--;)
   419 		for(;pagesLeftInChunk--;)
   408 			{
   420 			{// This pte must be of type ArmV6 small page, the pde type will 
   409 			TPhysAddr phys = (*pt++ & KPteSmallPageAddrMask);
   421 			// have already been checked by SafePageTableFromPde().
       
   422 			__NK_ASSERT_DEBUG((*pPte & KArmV6PteTypeMask) >= KArmV6PteSmallPage);
       
   423 			TPhysAddr phys = (*pPte++ & KPteSmallPageAddrMask);
   410 			pi =  SPageInfo::SafeFromPhysAddr(phys);
   424 			pi =  SPageInfo::SafeFromPhysAddr(phys);
   411 			if(!pi)	{ err = KErrNotFound; goto fail; }// Invalid address
   425 			if(!pi)	
       
   426 				{// Invalid address
       
   427 				err = KErrNotFound; 
       
   428 				goto fail; 
       
   429 				}
   412 			
   430 			
   413 			__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: PA:%x T:%x S:%x O:%x C:%x",phys, pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   431 			__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: PA:%x T:%x S:%x O:%x C:%x",phys, pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   414 			if (chunk==NULL)
   432 			if (chunk == NULL)
   415 				{//This is the first page. Check 'trusted' bit.
   433 				{//This is the first page. Check 'trusted' bit.
   416 				if (pi->Type()!= SPageInfo::EChunk)
   434 				if (pi->Type()!= SPageInfo::EChunk)
   417 					{ err = KErrAccessDenied; goto fail; }// The first page do not belong to chunk.	
   435 					{// The first page does not belong to a chunk.
       
   436 					err = KErrAccessDenied;
       
   437 					goto fail;
       
   438 					}
   418 
   439 
   419 				chunk = (DChunk*)pi->Owner();
   440 				chunk = (DChunk*)pi->Owner();
   420 				if ( (chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk)== 0) )
   441 				if ((chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk) == 0))
   421 					{ err = KErrAccessDenied; goto fail; }// Not a trusted chunk
   442 					{// Not a trusted chunk
       
   443 					err = KErrAccessDenied;
       
   444 					goto fail;
       
   445 					}
   422 				}
   446 				}
   423 			pi->Lock();
   447 			pi->Lock();
   424 
   448 
   425 			*pageList++ = phys;
   449 			*pageList++ = phys;
   426 			if ( (++pagesInList&127) == 0) //release system lock temporarily on every 512K
   450 
       
   451 			if(!(++pagesInList & flashMask))
       
   452 				{
   427 				NKern::FlashSystem();
   453 				NKern::FlashSystem();
       
   454 				}
   428 			}
   455 			}
   429 		pageIndex = 0;
   456 		pageIndex = 0;
   430 		}
   457 		}
   431 
   458 
   432 	if (pi->Type()!= SPageInfo::EChunk)
   459 	if (pi->Type() != SPageInfo::EChunk)
   433 		{ err = KErrAccessDenied; goto fail; }// The last page do not belong to chunk.	
   460 		{// The last page does not belong to a chunk.
       
   461 		err = KErrAccessDenied;
       
   462 		goto fail;
       
   463 		}
   434 
   464 
   435 	if (chunk && (chunk != (DChunk*)pi->Owner()))
   465 	if (chunk && (chunk != (DChunk*)pi->Owner()))
   436 		{ err = KErrArgument; goto fail; }//The first & the last page do not belong to the same chunk.
   466 		{//The first & the last page do not belong to the same chunk.
       
   467 		err = KErrArgument;
       
   468 		goto fail;
       
   469 		}
   437 
   470 
   438 	NKern::UnlockSystem();
   471 	NKern::UnlockSystem();
   439 	MmuBase::Signal();
   472 	MmuBase::Signal();
   440 	return KErrNone;
   473 	return KErrNone;
   441 
   474 
   445 	MmuBase::Signal();
   478 	MmuBase::Signal();
   446 	ReleasePagesFromDMA(aPhysicalPageList, pagesInList);
   479 	ReleasePagesFromDMA(aPhysicalPageList, pagesInList);
   447 	return err;
   480 	return err;
   448 	}
   481 	}
   449 
   482 
       
   483 
   450 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)
   484 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)
   451 // Unlocks physical pages.
   485 // Unlocks physical pages.
   452 // @param aPhysicalPageList - points to the list of physical pages that should be released.
   486 // @param aPhysicalPageList - points to the list of physical pages that should be released.
   453 // @param aPageCount		- the number of physical pages in the list.
   487 // @param aPageCount		- the number of physical pages in the list.
   454 	{
   488 	{
   455 	NKern::LockSystem();
   489 	NKern::LockSystem();
   456 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount));
   490 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount));
   457 
   491 
       
   492 	TUint flashMask = MM::MaxPagesInOneGo - 1;
   458 	while (aPageCount--)
   493 	while (aPageCount--)
   459 		{
   494 		{
   460 		SPageInfo* pi =  SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++);
   495 		SPageInfo* pi =  SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++);
   461 		if(!pi)
   496 		if(!pi)
   462 			{
   497 			{
   463 			NKern::UnlockSystem();
   498 			NKern::UnlockSystem();
   464 			return KErrArgument;
   499 			return KErrArgument;
   465 			}
   500 			}
   466 		__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   501 		__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   467 		pi->Unlock();
   502 		pi->Unlock();
       
   503 
       
   504 		if(!(aPageCount & flashMask))
       
   505 			{
       
   506 			NKern::FlashSystem();
       
   507 			}
   468 		}
   508 		}
   469 	NKern::UnlockSystem();
   509 	NKern::UnlockSystem();
   470 	return KErrNone;
   510 	return KErrNone;
   471 	}
   511 	}
       
   512 
   472 
   513 
   473 TPhysAddr ArmMmu::LinearToPhysical(TLinAddr aLinAddr, TInt aOsAsid)
   514 TPhysAddr ArmMmu::LinearToPhysical(TLinAddr aLinAddr, TInt aOsAsid)
   474 //
   515 //
   475 // Find the physical address corresponding to a given linear address in a specified OS
   516 // Find the physical address corresponding to a given linear address in a specified OS
   476 // address space. Call with system locked.
   517 // address space. Call with system locked.