1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/moving/arm/xkernel.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,295 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\memmodel\epoc\moving\arm\xkernel.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "arm_mem.h"
1.22 +
1.23 +
1.24 +/********************************************
1.25 + * Thread
1.26 + ********************************************/
1.27 +
1.28 +TInt DArmPlatThread::SetupContext(SThreadCreateInfo& anInfo)
1.29 + {
1.30 + switch(iThreadType)
1.31 + {
1.32 + case EThreadSupervisor:
1.33 + case EThreadMinimalSupervisor:
1.34 + iNThread.SetDacr(Arm::DefaultDomainAccess);
1.35 + case EThreadInitial:
1.36 + break;
1.37 + case EThreadUser:
1.38 + {
1.39 + DArmPlatProcess* pP=(DArmPlatProcess*)iOwningProcess;
1.40 + iNThread.SetDacr(pP->iDacr);
1.41 + if (pP->iAttributes & DMemModelProcess::EVariableAccess)
1.42 + iNThread.SetAttributes(KThreadAttImplicitSystemLock|KThreadAttAddressSpace);
1.43 +#ifndef __SMP__
1.44 + iNThread.iSpare3 /*iUserContextType*/ = NThread::EContextUndefined;
1.45 +#endif
1.46 + break;
1.47 + }
1.48 + }
1.49 + iNThread.SetAddressSpace(iOwningProcess);
1.50 + __KTRACE_OPT(KTHREAD,Kern::Printf("Thread %O DACR %08x Attrib %02x",this,iNThread.Dacr(),iNThread.Attributes()));
1.51 + return KErrNone;
1.52 + }
1.53 +
1.54 +DArmPlatProcess::DArmPlatProcess()
1.55 + : iDomain(-1), iDacr(Arm::DefaultDomainAccess|0x3) // manager access to domain 0
1.56 + {}
1.57 +
1.58 +DArmPlatProcess::~DArmPlatProcess()
1.59 + {
1.60 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess destruct, Domain=%d",iDomain));
1.61 + if (iDomain>=0)
1.62 + ArmMmu::FreeDomain(iDomain);
1.63 + DMemModelProcess::Destruct();
1.64 + }
1.65 +
1.66 +TInt DArmPlatProcess::GetNewChunk(DMemModelChunk*& aChunk, SChunkCreateInfo& aInfo)
1.67 + {
1.68 + aChunk=NULL;
1.69 + DArmPlatChunk* pC=new DArmPlatChunk;
1.70 + if (!pC)
1.71 + return KErrNoMemory;
1.72 + aChunk=pC;
1.73 + pC->iChunkType=aInfo.iType;
1.74 + switch(pC->iChunkType)
1.75 + {
1.76 + case EKernelData:
1.77 + case EKernelStack:
1.78 + case EKernelCode:
1.79 + case EKernelMessage:
1.80 + pC->iAttributes |= DMemModelChunk::EFixedAccess;
1.81 + break;
1.82 + case ERamDrive:
1.83 + pC->iDomain=3;
1.84 + pC->iAttributes |= DMemModelChunk::EFixedAccess;
1.85 + break;
1.86 + case EUserCode:
1.87 + case EUserSelfModCode:
1.88 + pC->iAttributes |= DMemModelChunk::EFixedAddress;
1.89 + if (iDomain>=0)
1.90 + {
1.91 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create code chunk, owning process domain %d",iDomain));
1.92 + pC->iDomain=iDomain;
1.93 + pC->iAttributes |= DMemModelChunk::EFixedAccess;
1.94 + }
1.95 + break;
1.96 + case EDll:
1.97 + break;
1.98 + case EUserData:
1.99 + case EDllData:
1.100 + if (aInfo.iGlobal && (iAttributes & DMemModelProcess::EFixedAddress || aInfo.iForceFixed))
1.101 + {
1.102 + TInt domain=ArmMmu::AllocDomain();
1.103 + if (domain>=0)
1.104 + {
1.105 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create global chunk, Domain %d allocated",domain));
1.106 + pC->iDomain=domain;
1.107 + pC->iAttributes |= DMemModelChunk::EFixedAccess;
1.108 + }
1.109 + }
1.110 + else if (!aInfo.iGlobal && iDomain>=0)
1.111 + {
1.112 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk create local chunk, owning process domain %d",iDomain));
1.113 + pC->iDomain=iDomain;
1.114 + pC->iAttributes |= DMemModelChunk::EFixedAccess;
1.115 + }
1.116 + break;
1.117 + case ESharedKernelSingle:
1.118 + case ESharedKernelMultiple:
1.119 + case ESharedIo:
1.120 + break;
1.121 + default:
1.122 + FAULT();
1.123 + }
1.124 + return KErrNone;
1.125 + }
1.126 +
1.127 +DArmPlatChunk::DArmPlatChunk()
1.128 + : iDomain(-1)
1.129 + {}
1.130 +
1.131 +DArmPlatChunk::~DArmPlatChunk()
1.132 + {
1.133 + if (!iOwningProcess && iDomain>=0)
1.134 + {
1.135 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatChunk destruct, Domain %d freed",iDomain));
1.136 + ArmMmu::FreeDomain(iDomain);
1.137 + }
1.138 + DMemModelChunk::Destruct();
1.139 + }
1.140 +
1.141 +TInt DArmPlatChunk::SetupPermissions()
1.142 + {
1.143 + Mmu& m = Mmu::Get();
1.144 + if(iChunkType==ESharedKernelSingle || iChunkType==ESharedKernelMultiple || iChunkType==ESharedIo)
1.145 + {
1.146 + // override map attributes for shared kernel chunks
1.147 + TUint ma = (iMapAttr &~ EMapAttrAccessMask) | EMapAttrSupRw;
1.148 + TPde pde;
1.149 + TInt r = m.PdePtePermissions(ma, pde, iPtePermissions);
1.150 + if (r != KErrNone)
1.151 + return r;
1.152 + iMapAttr = ma;
1.153 + }
1.154 + else
1.155 + iPtePermissions=m.PtePermissions(iChunkType);
1.156 + // PDE may need to set P bit for ECC in ARMv5 and later.
1.157 + if (iDomain<0)
1.158 + {
1.159 + iPdePermissions[0]=m.PdePermissions(iChunkType,ENotRunning);
1.160 + iPdePermissions[1]=m.PdePermissions(iChunkType,ERunningRO);
1.161 + iPdePermissions[2]=m.PdePermissions(iChunkType,ERunningRW);
1.162 + }
1.163 + else
1.164 + {
1.165 + TPde pdePermissions = PT_PDE(iDomain);
1.166 + iPdePermissions[0]=pdePermissions;
1.167 + iPdePermissions[1]=pdePermissions;
1.168 + iPdePermissions[2]=pdePermissions;
1.169 + }
1.170 + __KTRACE_OPT(KMMU,Kern::Printf("Chunk permissions PTE=%08x PDE0=%08x PDE1=%08x PDE2=%08x",
1.171 + iPtePermissions,iPdePermissions[0],iPdePermissions[1],iPdePermissions[2]));
1.172 + return KErrNone;
1.173 + }
1.174 +
1.175 +
1.176 +// must hold process lock while iterating through thread list
1.177 +void DArmPlatProcess::AdjustDomainAccess(TUint32 aClearMask, TUint32 aSetMask)
1.178 + {
1.179 + __KTRACE_OPT(KMMU,Kern::Printf("Process %O AdjustDomainAccess, clear %08x set %08x",
1.180 + this,aClearMask,aSetMask));
1.181 + iDacr=(iDacr & ~aClearMask)|aSetMask;
1.182 + __KTRACE_OPT(KMMU,Kern::Printf("DACR set to %08x",iDacr));
1.183 + SDblQueLink* pLink=iThreadQ.First();
1.184 + while (pLink!=&iThreadQ.iA)
1.185 + {
1.186 + DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
1.187 + pLink=pLink->iNext;
1.188 + pT->iNThread.ModifyDacr(aClearMask,aSetMask);
1.189 + }
1.190 + }
1.191 +
1.192 +// must hold process lock while iterating through thread list
1.193 +void DArmPlatProcess::AdjustThreadAttributes(TUint8 aClearMask, TUint8 aSetMask)
1.194 + {
1.195 + __KTRACE_OPT(KMMU,Kern::Printf("Process %O AdjustThreadAttributes, clear %02x set %02x",
1.196 + this,aClearMask,aSetMask));
1.197 + SDblQueLink* pLink=iThreadQ.First();
1.198 + NKern::LockSystem();
1.199 + while (pLink!=&iThreadQ.iA)
1.200 + {
1.201 + DArmPlatThread* pT=_LOFF(pLink,DArmPlatThread,iProcessLink);
1.202 + pLink=pLink->iNext;
1.203 + pT->iNThread.ModifyAttributes(aClearMask,aSetMask);
1.204 + NKern::FlashSystem();
1.205 + }
1.206 + NKern::UnlockSystem();
1.207 + }
1.208 +
1.209 +TInt DArmPlatProcess::AddFixedAccessChunk(DMemModelChunk *aChunk)
1.210 + {
1.211 + DArmPlatChunk* pC=(DArmPlatChunk*)aChunk;
1.212 + if (pC->iChunkType==ESharedKernelSingle || pC->iChunkType==ESharedIo)
1.213 + {
1.214 + if (iDomain<0)
1.215 + return KErrGeneral;
1.216 + pC->iDomain = iDomain;
1.217 + TInt r = pC->SetupPermissions();
1.218 + __ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::EAddFixedBadPerm));
1.219 + }
1.220 +
1.221 + __KTRACE_OPT(KMMU,Kern::Printf("Add fixed access chunk, domain=%d",pC->iDomain));
1.222 +
1.223 + // if this is one of process's local chunks, nothing to do
1.224 + if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
1.225 + {
1.226 + AdjustDomainAccess(0,2<<(pC->iDomain<<1)); // grant manager access to chunk's domain
1.227 + }
1.228 + return KErrNone;
1.229 + }
1.230 +
1.231 +TInt DArmPlatProcess::RemoveFixedAccessChunk(DMemModelChunk *aChunk)
1.232 + {
1.233 + DArmPlatChunk* pC=(DArmPlatChunk*)aChunk;
1.234 + __KTRACE_OPT(KMMU,Kern::Printf("Remove fixed access chunk, domain=%d",pC->iDomain));
1.235 + if (pC->iChunkType==ESharedKernelSingle || pC->iChunkType==ESharedIo)
1.236 + {
1.237 + if (iDomain<0)
1.238 + return KErrGeneral;
1.239 + pC->iDomain = -1;
1.240 + TInt r = pC->SetupPermissions();
1.241 + __ASSERT_ALWAYS(r==KErrNone, MM::Panic(MM::ERemoveFixedBadPerm));
1.242 + return KErrNone;
1.243 + }
1.244 +
1.245 + // if this is one of process's local chunks, nothing to do
1.246 + if (pC->iDomain!=iDomain && !(iAttributes&ESupervisor))
1.247 + {
1.248 + AdjustDomainAccess(2<<(pC->iDomain<<1),0); // remove manager access to chunk's domain
1.249 + }
1.250 + return KErrNone;
1.251 + }
1.252 +
1.253 +void DArmPlatProcess::CheckForFixedAccess()
1.254 + {
1.255 + TInt domain=ArmMmu::AllocDomain();
1.256 + if (domain>=0)
1.257 + {
1.258 + __KTRACE_OPT(KMMU,Kern::Printf("DArmPlatProcess create, Domain %d allocated",domain));
1.259 + iDomain=domain;
1.260 + iDacr |= (2<<(domain<<1)); // grant manager access to allocated domain
1.261 + iDacr &= ~2; // demote domain 0 to client access
1.262 + }
1.263 + }
1.264 +
1.265 +void DArmPlatProcess::DoAttributeChange()
1.266 + {
1.267 + // Called when a process changes from fixed to variable access or vice-versa.
1.268 + TBool variable=iAttributes & EVariableAccess;
1.269 + if (variable)
1.270 + {
1.271 + // process changing from fixed access to variable access
1.272 + __KTRACE_OPT(KMMU,Kern::Printf("Process %O becomes variable access",this));
1.273 + AdjustThreadAttributes(0,KThreadAttImplicitSystemLock|KThreadAttAddressSpace);
1.274 + AdjustDomainAccess(0,2); // promote domain 0 to manager access
1.275 + }
1.276 + else
1.277 + {
1.278 + // process changing from variable access to fixed access
1.279 + __KTRACE_OPT(KMMU,Kern::Printf("Process %O becomes fixed access",this));
1.280 + AdjustDomainAccess(2,0); // demote domain 0 to client access
1.281 + AdjustThreadAttributes(KThreadAttImplicitSystemLock|KThreadAttAddressSpace,0);
1.282 + }
1.283 + }
1.284 +
1.285 +TIpcExcTrap::TExcLocation TIpcExcTrap::ExcLocation(DThread* /*aThread*/, TAny* aContext)
1.286 + {
1.287 + TArmExcInfo& info=*(TArmExcInfo*)aContext;
1.288 +
1.289 + if (info.iExcCode==EArmExceptionDataAbort)
1.290 + {
1.291 + TLinAddr va=(TLinAddr)info.iFaultAddress;
1.292 + if (va>=iRemoteBase && (va-iRemoteBase)<iSize)
1.293 + return EExcRemote;
1.294 + if (iLocalBase && va>=iLocalBase && (va-iLocalBase)<iSize)
1.295 + return EExcLocal;
1.296 + }
1.297 + return EExcUnknown;
1.298 + }