kernel/eka/memmodel/epoc/moving/arm/xmmu.cpp
branchRCL_3
changeset 87 2f92ad2dc5db
parent 36 538db54a451d
child 109 b3a1d9898418
equal deleted inserted replaced
81:e7d2d738d3c2 87:2f92ad2dc5db
   442 		__KTRACE_OPT(KMMU,Kern::Printf("Address invalid"));
   442 		__KTRACE_OPT(KMMU,Kern::Printf("Address invalid"));
   443 		}
   443 		}
   444 	return phys;
   444 	return phys;
   445 	}
   445 	}
   446 
   446 
       
   447 
   447 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TPhysAddr* aPhysicalPageList)
   448 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TPhysAddr* aPhysicalPageList)
   448 //Returns the list of physical pages belonging to the specified memory space.
   449 //Returns the list of physical pages belonging to the specified memory space.
   449 //Checks these pages belong to a chunk marked as being trusted. 
   450 //Checks these pages belong to a chunk marked as being trusted. 
   450 //Locks these pages so they can not be moved by e.g. ram defragmenation.
   451 //Locks these pages so they can not be moved by e.g. ram defragmentation.
   451 	{
   452 	{
   452 	SPageInfo* pi = NULL;
   453 	SPageInfo* pi = NULL;
   453 	DChunk* chunk = NULL;
   454 	DChunk* chunk = NULL;
   454 	TInt err = KErrNone;
   455 	TInt err = KErrNone;
       
   456 
       
   457 	__NK_ASSERT_DEBUG(MM::MaxPagesInOneGo == 32);	// Needs to be a power of 2.
       
   458 	TUint flashMask = MM::MaxPagesInOneGo - 1;
   455 	
   459 	
   456 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize));
   460 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize));
   457 
   461 
   458 	TUint32* pageList = aPhysicalPageList;
   462 	TUint32* pageList = aPhysicalPageList;
   459 	TInt pagesInList = 0;				//The number of pages we put in the list so far
   463 	TInt pagesInList = 0;				//The number of pages we put in the list so far
   472 		if(pagesLeftInChunk>pagesLeft)
   476 		if(pagesLeftInChunk>pagesLeft)
   473 			pagesLeftInChunk = pagesLeft;
   477 			pagesLeftInChunk = pagesLeft;
   474 		
   478 		
   475 		pagesLeft -= pagesLeftInChunk;
   479 		pagesLeft -= pagesLeftInChunk;
   476 
   480 
   477 		TPte* pt = SafePageTableFromPde(*pdePtr++);
   481 		TPte* pPte = SafePageTableFromPde(*pdePtr++);
   478 		if(!pt) { err = KErrNotFound; goto fail; }// Cannot get page table.
   482 		if(!pPte) 
   479 
   483 			{// Cannot get page table. 
   480 		pt += pageIndex;
   484 			err = KErrNotFound; 
       
   485 			goto fail; 
       
   486 			}
       
   487 		
       
   488 		pPte += pageIndex;
   481 
   489 
   482 		for(;pagesLeftInChunk--;)
   490 		for(;pagesLeftInChunk--;)
   483 			{
   491 			{
   484 			TPhysAddr phys = (*pt++ & KPteSmallPageAddrMask);
   492 			TPhysAddr phys = (*pPte++ & KPteSmallPageAddrMask);
   485 			pi =  SPageInfo::SafeFromPhysAddr(phys);
   493 			pi =  SPageInfo::SafeFromPhysAddr(phys);
   486 			if(!pi)	{ err = KErrNotFound; goto fail; }// Invalid address
   494 			if(!pi)	
   487 
   495 				{// Invalid address
       
   496 				err = KErrNotFound; 
       
   497 				goto fail; 
       
   498 				}
       
   499 			
   488 			__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()));
   500 			__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()));
   489 			if (chunk==NULL)
   501 			if (chunk == NULL)
   490 				{//This is the first page. Check 'trusted' bit.
   502 				{//This is the first page. Check 'trusted' bit.
   491 				if (pi->Type()!= SPageInfo::EChunk)
   503 				if (pi->Type()!= SPageInfo::EChunk)
   492 					{ err = KErrAccessDenied; goto fail; }// The first page do not belong to chunk.	
   504 					{// The first page does not belong to a chunk.
       
   505 					err = KErrAccessDenied;
       
   506 					goto fail;
       
   507 					}
   493 
   508 
   494 				chunk = (DChunk*)pi->Owner();
   509 				chunk = (DChunk*)pi->Owner();
   495 				if ( (chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk)== 0) )
   510 				if ((chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk) == 0))
   496 					{ err = KErrAccessDenied; goto fail; } // Not a trusted chunk
   511 					{// Not a trusted chunk
       
   512 					err = KErrAccessDenied;
       
   513 					goto fail;
       
   514 					}
   497 				}
   515 				}
   498 			pi->Lock();
   516 			pi->Lock();
   499 
   517 
   500 			*pageList++ = phys;
   518 			*pageList++ = phys;
   501 			if ( (++pagesInList&127) == 0) //release system lock temporarily on every 512K
   519 
       
   520 			if(!(++pagesInList & flashMask))
       
   521 				{
   502 				NKern::FlashSystem();
   522 				NKern::FlashSystem();
       
   523 				}
   503 			}
   524 			}
   504 		pageIndex = 0;
   525 		pageIndex = 0;
   505 		}
   526 		}
   506 
   527 
   507 	if (pi->Type()!= SPageInfo::EChunk)
   528 	if (pi->Type() != SPageInfo::EChunk)
   508 		{ err = KErrAccessDenied; goto fail; }// The last page do not belong to chunk.	
   529 		{// The last page does not belong to a chunk.
       
   530 		err = KErrAccessDenied;
       
   531 		goto fail;
       
   532 		}
   509 
   533 
   510 	if (chunk && (chunk != (DChunk*)pi->Owner()))
   534 	if (chunk && (chunk != (DChunk*)pi->Owner()))
   511 		{ err = KErrArgument; goto fail; }//The first & the last page do not belong to the same chunk.
   535 		{//The first & the last page do not belong to the same chunk.
       
   536 		err = KErrArgument;
       
   537 		goto fail;
       
   538 		}
   512 
   539 
   513 	NKern::UnlockSystem();
   540 	NKern::UnlockSystem();
   514 	MmuBase::Signal();
   541 	MmuBase::Signal();
   515 	return KErrNone;
   542 	return KErrNone;
   516 
   543 
   520 	MmuBase::Signal();
   547 	MmuBase::Signal();
   521 	ReleasePagesFromDMA(aPhysicalPageList, pagesInList);
   548 	ReleasePagesFromDMA(aPhysicalPageList, pagesInList);
   522 	return err;
   549 	return err;
   523 	}
   550 	}
   524 
   551 
       
   552 
   525 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)
   553 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)
   526 // Unlocks physical pages.
   554 // Unlocks physical pages.
   527 // @param aPhysicalPageList - points to the list of physical pages that should be released.
   555 // @param aPhysicalPageList - points to the list of physical pages that should be released.
   528 // @param aPageCount		- the number of physical pages in the list.
   556 // @param aPageCount		- the number of physical pages in the list.
   529 	{
   557 	{
   530 	NKern::LockSystem();
   558 	NKern::LockSystem();
   531 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount));
   559 	__KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount));
   532 
   560 
       
   561 	TUint flashMask = MM::MaxPagesInOneGo - 1;
   533 	while (aPageCount--)
   562 	while (aPageCount--)
   534 		{
   563 		{
   535 		SPageInfo* pi =  SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++);
   564 		SPageInfo* pi =  SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++);
   536 		if(!pi)
   565 		if(!pi)
   537 			{
   566 			{
   538 			NKern::UnlockSystem();
   567 			NKern::UnlockSystem();
   539 			return KErrArgument;
   568 			return KErrArgument;
   540 			}
   569 			}
   541 		__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   570 		__KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount()));
   542 		pi->Unlock();
   571 		pi->Unlock();
       
   572 
       
   573 		if(!(aPageCount & flashMask))
       
   574 			{
       
   575 			NKern::FlashSystem();
       
   576 			}
   543 		}
   577 		}
   544 	NKern::UnlockSystem();
   578 	NKern::UnlockSystem();
   545 	return KErrNone;
   579 	return KErrNone;
   546 	}
   580 	}
       
   581 
   547 
   582 
   548 
   583 
   549 void ArmMmu::Init1()
   584 void ArmMmu::Init1()
   550 	{
   585 	{
   551 	__KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("ArmMmu::Init1"));
   586 	__KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("ArmMmu::Init1"));