os/kernelhwsrv/kernel/eka/memmodel/epoc/moving/arm/xkernel.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	}