kernel/eka/memmodel/epoc/moving/arm/xkernel.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\memmodel\epoc\moving\arm\xkernel.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "arm_mem.h"
       
    19 
       
    20 
       
    21 /********************************************
       
    22  * Thread
       
    23  ********************************************/
       
    24 
       
    25 TInt DArmPlatThread::SetupContext(SThreadCreateInfo& anInfo)
       
    26 	{
       
    27 	switch(iThreadType)
       
    28 		{
       
    29 		case EThreadSupervisor:
       
    30 		case EThreadMinimalSupervisor:
       
    31 			iNThread.SetDacr(Arm::DefaultDomainAccess);
       
    32 		case EThreadInitial:
       
    33 			break;
       
    34 		case EThreadUser:
       
    35 			{
       
    36 			DArmPlatProcess* pP=(DArmPlatProcess*)iOwningProcess;
       
    37 			iNThread.SetDacr(pP->iDacr);
       
    38 			if (pP->iAttributes & DMemModelProcess::EVariableAccess)
       
    39 				iNThread.SetAttributes(KThreadAttImplicitSystemLock|KThreadAttAddressSpace);
       
    40 #ifndef __SMP__
       
    41 			iNThread.iSpare3 /*iUserContextType*/ = NThread::EContextUndefined;
       
    42 #endif
       
    43 			break;
       
    44 			}
       
    45 		}
       
    46 	iNThread.SetAddressSpace(iOwningProcess);
       
    47 	__KTRACE_OPT(KTHREAD,Kern::Printf("Thread %O DACR %08x Attrib %02x",this,iNThread.Dacr(),iNThread.Attributes()));
       
    48 	return KErrNone;
       
    49 	}
       
    50 
       
    51 DArmPlatProcess::DArmPlatProcess()
       
    52 	: iDomain(-1), iDacr(Arm::DefaultDomainAccess|0x3)	// manager access to domain 0
       
    53 	{}
       
    54 
       
    55 DArmPlatProcess::~DArmPlatProcess()
       
    56 	{
       
    57 	__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess destruct, Domain=%d",iDomain));
       
    58 	if (iDomain>=0)
       
    59 		ArmMmu::FreeDomain(iDomain);
       
    60 	DMemModelProcess::Destruct();
       
    61 	}
       
    62 
       
    63 TInt DArmPlatProcess::GetNewChunk(DMemModelChunk*& aChunk, SChunkCreateInfo& aInfo)
       
    64 	{
       
    65 	aChunk=NULL;
       
    66 	DArmPlatChunk* pC=new DArmPlatChunk;
       
    67 	if (!pC)
       
    68 		return KErrNoMemory;
       
    69 	aChunk=pC;
       
    70 	pC->iChunkType=aInfo.iType;
       
    71 	switch(pC->iChunkType)
       
    72 		{
       
    73 		case EKernelData:
       
    74 		case EKernelStack:
       
    75 		case EKernelCode:
       
    76 		case EKernelMessage:
       
    77 			pC->iAttributes |= DMemModelChunk::EFixedAccess;
       
    78 			break;
       
    79 		case ERamDrive:
       
    80 			pC->iDomain=3;
       
    81 			pC->iAttributes |= DMemModelChunk::EFixedAccess;
       
    82 			break;
       
    83 		case EUserCode:
       
    84 		case EUserSelfModCode:
       
    85 			pC->iAttributes |= DMemModelChunk::EFixedAddress;
       
    86 			if (iDomain>=0)
       
    87 				{
       
    88 				__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create code chunk, owning process domain %d",iDomain));
       
    89 				pC->iDomain=iDomain;
       
    90 				pC->iAttributes |= DMemModelChunk::EFixedAccess;
       
    91 				}
       
    92 			break;
       
    93 		case EDll:
       
    94 			break;
       
    95 		case EUserData:
       
    96 		case EDllData:
       
    97 			if (aInfo.iGlobal && (iAttributes & DMemModelProcess::EFixedAddress || aInfo.iForceFixed))
       
    98 				{
       
    99 				TInt domain=ArmMmu::AllocDomain();
       
   100 				if (domain>=0)
       
   101 					{
       
   102 					__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create global chunk, Domain %d allocated",domain));
       
   103 					pC->iDomain=domain;
       
   104 					pC->iAttributes |= DMemModelChunk::EFixedAccess;
       
   105 					}
       
   106 				}
       
   107 			else if (!aInfo.iGlobal && iDomain>=0)
       
   108 				{
       
   109 				__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create local chunk, owning process domain %d",iDomain));
       
   110 				pC->iDomain=iDomain;
       
   111 				pC->iAttributes |= DMemModelChunk::EFixedAccess;
       
   112 				}
       
   113 			break;
       
   114 		case ESharedKernelSingle:
       
   115 		case ESharedKernelMultiple:
       
   116 		case ESharedIo:
       
   117 			break;
       
   118 		default:
       
   119 			FAULT();
       
   120 		}
       
   121 	return KErrNone;
       
   122 	}
       
   123 
       
   124 DArmPlatChunk::DArmPlatChunk()
       
   125 	: iDomain(-1)
       
   126 	{}
       
   127 
       
   128 DArmPlatChunk::~DArmPlatChunk()
       
   129 	{
       
   130 	if (!iOwningProcess && iDomain>=0)
       
   131 		{
       
   132 		__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk destruct, Domain %d freed",iDomain));
       
   133 		ArmMmu::FreeDomain(iDomain);
       
   134 		}
       
   135 	DMemModelChunk::Destruct();
       
   136 	}
       
   137 
       
   138 TInt DArmPlatChunk::SetupPermissions()
       
   139 	{
       
   140 	Mmu& m = Mmu::Get();
       
   141 	if(iChunkType==ESharedKernelSingle || iChunkType==ESharedKernelMultiple || iChunkType==ESharedIo)
       
   142 		{
       
   143 		// override map attributes for shared kernel chunks
       
   144 		TUint ma = (iMapAttr &~ EMapAttrAccessMask) | EMapAttrSupRw;
       
   145 		TPde pde;
       
   146 		TInt r = m.PdePtePermissions(ma, pde, iPtePermissions);
       
   147 		if (r != KErrNone)
       
   148 			return r;
       
   149 		iMapAttr = ma;
       
   150 		}
       
   151 	else
       
   152 		iPtePermissions=m.PtePermissions(iChunkType);
       
   153 	// PDE may need to set P bit for ECC in ARMv5 and later.
       
   154 	if (iDomain<0)
       
   155 		{
       
   156 		iPdePermissions[0]=m.PdePermissions(iChunkType,ENotRunning);
       
   157 		iPdePermissions[1]=m.PdePermissions(iChunkType,ERunningRO);
       
   158 		iPdePermissions[2]=m.PdePermissions(iChunkType,ERunningRW);
       
   159 		}
       
   160 	else
       
   161 		{
       
   162 		TPde pdePermissions = PT_PDE(iDomain);
       
   163 		iPdePermissions[0]=pdePermissions;
       
   164 		iPdePermissions[1]=pdePermissions;
       
   165 		iPdePermissions[2]=pdePermissions;
       
   166 		}
       
   167 	__KTRACE_OPT(KMMU,Kern::Printf("Chunk permissions PTE=%08x PDE0=%08x PDE1=%08x PDE2=%08x",
       
   168 				iPtePermissions,iPdePermissions[0],iPdePermissions[1],iPdePermissions[2]));
       
   169 	return KErrNone;
       
   170 	}
       
   171 
       
   172 
       
   173 // must hold process lock while iterating through thread list
       
   174 void DArmPlatProcess::AdjustDomainAccess(TUint32 aClearMask, TUint32 aSetMask)
       
   175 	{
       
   176 	__KTRACE_OPT(KMMU,Kern::Printf("Process %O AdjustDomainAccess, clear %08x set %08x",
       
   177 			this,aClearMask,aSetMask));
       
   178 	iDacr=(iDacr & ~aClearMask)|aSetMask;
       
   179 	__KTRACE_OPT(KMMU,Kern::Printf("DACR set to %08x",iDacr));
       
   180 	SDblQueLink* pLink=iThreadQ.First();
       
   181 	while (pLink!=&iThreadQ.iA)
       
   182 		{
       
   183 		DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
       
   184 		pLink=pLink->iNext;
       
   185 		pT->iNThread.ModifyDacr(aClearMask,aSetMask);
       
   186 		}
       
   187 	}
       
   188 
       
   189 // must hold process lock while iterating through thread list
       
   190 void DArmPlatProcess::AdjustThreadAttributes(TUint8 aClearMask, TUint8 aSetMask)
       
   191 	{
       
   192 	__KTRACE_OPT(KMMU,Kern::Printf("Process %O AdjustThreadAttributes, clear %02x set %02x",
       
   193 			this,aClearMask,aSetMask));
       
   194 	SDblQueLink* pLink=iThreadQ.First();
       
   195 	NKern::LockSystem();
       
   196 	while (pLink!=&iThreadQ.iA)
       
   197 		{
       
   198 		DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
       
   199 		pLink=pLink->iNext;
       
   200 		pT->iNThread.ModifyAttributes(aClearMask,aSetMask);
       
   201 		NKern::FlashSystem();
       
   202 		}
       
   203 	NKern::UnlockSystem();
       
   204 	}
       
   205 
       
   206 TInt DArmPlatProcess::AddFixedAccessChunk(DMemModelChunk *aChunk)
       
   207 	{
       
   208 	DArmPlatChunk* pC=(DArmPlatChunk*)aChunk;
       
   209 	if (pC->iChunkType==ESharedKernelSingle || pC->iChunkType==ESharedIo)
       
   210 		{
       
   211 		if (iDomain<0)
       
   212 			return KErrGeneral;
       
   213 		pC->iDomain = iDomain;
       
   214 		TInt r = pC->SetupPermissions();
       
   215 		__ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::EAddFixedBadPerm));
       
   216 		}
       
   217 
       
   218 	__KTRACE_OPT(KMMU,Kern::Printf("Add fixed access chunk, domain=%d",pC->iDomain));
       
   219 
       
   220 	// if this is one of process's local chunks, nothing to do
       
   221 	if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
       
   222 		{
       
   223 		AdjustDomainAccess(0,2<<(pC->iDomain<<1));	// grant manager access to chunk's domain
       
   224 		}
       
   225 	return KErrNone;
       
   226 	}
       
   227 
       
   228 TInt DArmPlatProcess::RemoveFixedAccessChunk(DMemModelChunk *aChunk)
       
   229 	{
       
   230 	DArmPlatChunk* pC=(DArmPlatChunk*)aChunk;
       
   231 	__KTRACE_OPT(KMMU,Kern::Printf("Remove fixed access chunk, domain=%d",pC->iDomain));
       
   232 	if (pC->iChunkType==ESharedKernelSingle || pC->iChunkType==ESharedIo)
       
   233 		{
       
   234 		if (iDomain<0)
       
   235 			return KErrGeneral;
       
   236 		pC->iDomain = -1;
       
   237 		TInt r = pC->SetupPermissions();
       
   238 		__ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::ERemoveFixedBadPerm));
       
   239 		return KErrNone;
       
   240 		}
       
   241 
       
   242 	// if this is one of process's local chunks, nothing to do
       
   243 	if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
       
   244 		{
       
   245 		AdjustDomainAccess(2<<(pC->iDomain<<1),0);	// remove manager access to chunk's domain
       
   246 		}
       
   247 	return KErrNone;
       
   248 	}
       
   249 
       
   250 void DArmPlatProcess::CheckForFixedAccess()
       
   251 	{
       
   252 	TInt domain=ArmMmu::AllocDomain();
       
   253 	if (domain>=0)
       
   254 		{
       
   255 		__KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess create, Domain %d allocated",domain));
       
   256 		iDomain=domain;
       
   257 		iDacr |= (2<<(domain<<1));	// grant manager access to allocated domain
       
   258 		iDacr &= ~2;				// demote domain 0 to client access
       
   259 		}
       
   260 	}
       
   261 
       
   262 void DArmPlatProcess::DoAttributeChange()
       
   263 	{
       
   264 	// Called when a process changes from fixed to variable access or vice-versa.
       
   265 	TBool variable=iAttributes & EVariableAccess;
       
   266 	if (variable)
       
   267 		{
       
   268 		// process changing from fixed access to variable access
       
   269 		__KTRACE_OPT(KMMU,Kern::Printf("Process %O becomes variable access",this));
       
   270 		AdjustThreadAttributes(0,KThreadAttImplicitSystemLock|KThreadAttAddressSpace);
       
   271 		AdjustDomainAccess(0,2);		// promote domain 0 to manager access
       
   272 		}
       
   273 	else
       
   274 		{
       
   275 		// process changing from variable access to fixed access
       
   276 		__KTRACE_OPT(KMMU,Kern::Printf("Process %O becomes fixed access",this));
       
   277 		AdjustDomainAccess(2,0);		// demote domain 0 to client access
       
   278 		AdjustThreadAttributes(KThreadAttImplicitSystemLock|KThreadAttAddressSpace,0);
       
   279 		}
       
   280 	}
       
   281 
       
   282 TIpcExcTrap::TExcLocation TIpcExcTrap::ExcLocation(DThread* /*aThread*/, TAny* aContext)
       
   283 	{
       
   284 	TArmExcInfo& info=*(TArmExcInfo*)aContext;
       
   285 
       
   286 	if (info.iExcCode==EArmExceptionDataAbort)
       
   287 		{
       
   288 		TLinAddr va=(TLinAddr)info.iFaultAddress;
       
   289 		if (va>=iRemoteBase && (va-iRemoteBase)<iSize)
       
   290 			return EExcRemote;
       
   291 		if (iLocalBase && va>=iLocalBase && (va-iLocalBase)<iSize)
       
   292 			return EExcLocal;
       
   293 		}
       
   294 	return EExcUnknown;
       
   295 	}