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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\memmodel\epoc\moving\arm\xkernel.cpp
21 /********************************************
23 ********************************************/
25 TInt DArmPlatThread::SetupContext(SThreadCreateInfo& anInfo)
29 case EThreadSupervisor:
30 case EThreadMinimalSupervisor:
31 iNThread.SetDacr(Arm::DefaultDomainAccess);
36 DArmPlatProcess* pP=(DArmPlatProcess*)iOwningProcess;
37 iNThread.SetDacr(pP->iDacr);
38 if (pP->iAttributes & DMemModelProcess::EVariableAccess)
39 iNThread.SetAttributes(KThreadAttImplicitSystemLock|KThreadAttAddressSpace);
41 iNThread.iSpare3 /*iUserContextType*/ = NThread::EContextUndefined;
46 iNThread.SetAddressSpace(iOwningProcess);
47 __KTRACE_OPT(KTHREAD,Kern::Printf("Thread %O DACR %08x Attrib %02x",this,iNThread.Dacr(),iNThread.Attributes()));
51 DArmPlatProcess::DArmPlatProcess()
52 : iDomain(-1), iDacr(Arm::DefaultDomainAccess|0x3) // manager access to domain 0
55 DArmPlatProcess::~DArmPlatProcess()
57 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess destruct, Domain=%d",iDomain));
59 ArmMmu::FreeDomain(iDomain);
60 DMemModelProcess::Destruct();
63 TInt DArmPlatProcess::GetNewChunk(DMemModelChunk*& aChunk, SChunkCreateInfo& aInfo)
66 DArmPlatChunk* pC=new DArmPlatChunk;
70 pC->iChunkType=aInfo.iType;
71 switch(pC->iChunkType)
77 pC->iAttributes |= DMemModelChunk::EFixedAccess;
81 pC->iAttributes |= DMemModelChunk::EFixedAccess;
84 case EUserSelfModCode:
85 pC->iAttributes |= DMemModelChunk::EFixedAddress;
88 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create code chunk, owning process domain %d",iDomain));
90 pC->iAttributes |= DMemModelChunk::EFixedAccess;
97 if (aInfo.iGlobal && (iAttributes & DMemModelProcess::EFixedAddress || aInfo.iForceFixed))
99 TInt domain=ArmMmu::AllocDomain();
102 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create global chunk, Domain %d allocated",domain));
104 pC->iAttributes |= DMemModelChunk::EFixedAccess;
107 else if (!aInfo.iGlobal && iDomain>=0)
109 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create local chunk, owning process domain %d",iDomain));
111 pC->iAttributes |= DMemModelChunk::EFixedAccess;
114 case ESharedKernelSingle:
115 case ESharedKernelMultiple:
124 DArmPlatChunk::DArmPlatChunk()
128 DArmPlatChunk::~DArmPlatChunk()
130 if (!iOwningProcess && iDomain>=0)
132 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk destruct, Domain %d freed",iDomain));
133 ArmMmu::FreeDomain(iDomain);
135 DMemModelChunk::Destruct();
138 TInt DArmPlatChunk::SetupPermissions()
141 if(iChunkType==ESharedKernelSingle || iChunkType==ESharedKernelMultiple || iChunkType==ESharedIo)
143 // override map attributes for shared kernel chunks
144 TUint ma = (iMapAttr &~ EMapAttrAccessMask) | EMapAttrSupRw;
146 TInt r = m.PdePtePermissions(ma, pde, iPtePermissions);
152 iPtePermissions=m.PtePermissions(iChunkType);
153 // PDE may need to set P bit for ECC in ARMv5 and later.
156 iPdePermissions[0]=m.PdePermissions(iChunkType,ENotRunning);
157 iPdePermissions[1]=m.PdePermissions(iChunkType,ERunningRO);
158 iPdePermissions[2]=m.PdePermissions(iChunkType,ERunningRW);
162 TPde pdePermissions = PT_PDE(iDomain);
163 iPdePermissions[0]=pdePermissions;
164 iPdePermissions[1]=pdePermissions;
165 iPdePermissions[2]=pdePermissions;
167 __KTRACE_OPT(KMMU,Kern::Printf("Chunk permissions PTE=%08x PDE0=%08x PDE1=%08x PDE2=%08x",
168 iPtePermissions,iPdePermissions[0],iPdePermissions[1],iPdePermissions[2]));
173 // must hold process lock while iterating through thread list
174 void DArmPlatProcess::AdjustDomainAccess(TUint32 aClearMask, TUint32 aSetMask)
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)
183 DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
185 pT->iNThread.ModifyDacr(aClearMask,aSetMask);
189 // must hold process lock while iterating through thread list
190 void DArmPlatProcess::AdjustThreadAttributes(TUint8 aClearMask, TUint8 aSetMask)
192 __KTRACE_OPT(KMMU,Kern::Printf("Process %O AdjustThreadAttributes, clear %02x set %02x",
193 this,aClearMask,aSetMask));
194 SDblQueLink* pLink=iThreadQ.First();
196 while (pLink!=&iThreadQ.iA)
198 DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
200 pT->iNThread.ModifyAttributes(aClearMask,aSetMask);
201 NKern::FlashSystem();
203 NKern::UnlockSystem();
206 TInt DArmPlatProcess::AddFixedAccessChunk(DMemModelChunk *aChunk)
208 DArmPlatChunk* pC=(DArmPlatChunk*)aChunk;
209 if (pC->iChunkType==ESharedKernelSingle || pC->iChunkType==ESharedIo)
213 pC->iDomain = iDomain;
214 TInt r = pC->SetupPermissions();
215 __ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::EAddFixedBadPerm));
218 __KTRACE_OPT(KMMU,Kern::Printf("Add fixed access chunk, domain=%d",pC->iDomain));
220 // if this is one of process's local chunks, nothing to do
221 if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
223 AdjustDomainAccess(0,2<<(pC->iDomain<<1)); // grant manager access to chunk's domain
228 TInt DArmPlatProcess::RemoveFixedAccessChunk(DMemModelChunk *aChunk)
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)
237 TInt r = pC->SetupPermissions();
238 __ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::ERemoveFixedBadPerm));
242 // if this is one of process's local chunks, nothing to do
243 if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
245 AdjustDomainAccess(2<<(pC->iDomain<<1),0); // remove manager access to chunk's domain
250 void DArmPlatProcess::CheckForFixedAccess()
252 TInt domain=ArmMmu::AllocDomain();
255 __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess create, Domain %d allocated",domain));
257 iDacr |= (2<<(domain<<1)); // grant manager access to allocated domain
258 iDacr &= ~2; // demote domain 0 to client access
262 void DArmPlatProcess::DoAttributeChange()
264 // Called when a process changes from fixed to variable access or vice-versa.
265 TBool variable=iAttributes & EVariableAccess;
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
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);
282 TIpcExcTrap::TExcLocation TIpcExcTrap::ExcLocation(DThread* /*aThread*/, TAny* aContext)
284 TArmExcInfo& info=*(TArmExcInfo*)aContext;
286 if (info.iExcCode==EArmExceptionDataAbort)
288 TLinAddr va=(TLinAddr)info.iFaultAddress;
289 if (va>=iRemoteBase && (va-iRemoteBase)<iSize)
291 if (iLocalBase && va>=iLocalBase && (va-iLocalBase)<iSize)