1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/moving/mcodeseg.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,454 @@
1.4 +// Copyright (c) 1995-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\mcodeseg.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "memmodel.h"
1.22 +#include "cache_maintenance.h"
1.23 +#include <demand_paging.h>
1.24 +
1.25 +_LIT(KLitUserCode,"USER$CODE");
1.26 +_LIT(KLitKernCode,"KERN$CODE");
1.27 +
1.28 +TInt MM::CreateCodeChunk(TBool aKernel)
1.29 + {
1.30 + __KTRACE_OPT(KDLL,Kern::Printf("MM::CreateCodeChunk %d",aKernel));
1.31 + Mmu& m = Mmu::Get();
1.32 + SChunkCreateInfo c;
1.33 + c.iGlobal = ETrue;
1.34 + c.iAtt = TChunkCreate::EDisconnected;
1.35 + c.iForceFixed = EFalse;
1.36 + c.iOperations = 0;
1.37 + c.iPreallocated = 0;
1.38 + c.iOwner = NULL;
1.39 +
1.40 + if (aKernel)
1.41 + {
1.42 + c.iRunAddress = m.iKernelCodeBase;
1.43 + c.iType = EKernelCode;
1.44 + c.iMaxSize = m.iMaxKernelCodeSize;
1.45 + c.iName.Set(KLitKernCode);
1.46 + }
1.47 + else
1.48 + {
1.49 + c.iRunAddress = m.iUserCodeBase;
1.50 + c.iType = EDll;
1.51 + c.iMaxSize = m.iMaxUserCodeSize;
1.52 + c.iName.Set(KLitUserCode);
1.53 + }
1.54 +
1.55 + TLinAddr runAddr;
1.56 + DMemModelChunk* pC = NULL;
1.57 + TInt r=K::TheKernelProcess->NewChunk((DChunk*&)pC, c, runAddr);
1.58 + if (r==KErrNone)
1.59 + {
1.60 + pC->SetFixedAddress(c.iRunAddress, 0);
1.61 + if (aKernel)
1.62 + MM::KernelCodeChunk = pC;
1.63 + else
1.64 + MM::UserCodeChunk = pC;
1.65 + }
1.66 + return r;
1.67 + }
1.68 +
1.69 +DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
1.70 +//
1.71 +// Create a new instance of this class.
1.72 +//
1.73 + {
1.74 +
1.75 + __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
1.76 + return new DMemModelCodeSeg;
1.77 + }
1.78 +
1.79 +
1.80 +DEpocCodeSegMemory* DEpocCodeSegMemory::New(DEpocCodeSeg* aCodeSeg)
1.81 + {
1.82 + return new DMemModelCodeSegMemory(aCodeSeg);
1.83 + }
1.84 +
1.85 +
1.86 +DMemModelCodeSegMemory::DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg)
1.87 + : DMmuCodeSegMemory(aCodeSeg)
1.88 + {
1.89 + }
1.90 +
1.91 +
1.92 +TInt DMemModelCodeSegMemory::Create(TCodeSegCreateInfo& aInfo)
1.93 + {
1.94 + TInt r = DMmuCodeSegMemory::Create(aInfo);
1.95 + if(r!=KErrNone)
1.96 + return r;
1.97 +
1.98 + Mmu& m=Mmu::Get();
1.99 +
1.100 + TInt codeSize = iPageCount<<m.iPageShift;
1.101 + TInt dataSize = iDataPageCount<<m.iPageShift;
1.102 + TInt totalSize = codeSize+dataSize;
1.103 +
1.104 + DCodeSeg::Wait();
1.105 +
1.106 + DChunk::TCommitType commitType = iIsDemandPaged ? DChunk::ECommitVirtual : DChunk::ECommitDiscontiguous;
1.107 + r=MM::UserCodeChunk->FindFree(totalSize, 0, 0);
1.108 + if (r<0)
1.109 + {
1.110 + r = KErrNoMemory;
1.111 + goto exit;
1.112 + }
1.113 + iCodeAllocBase = r;
1.114 + r = KErrNone;
1.115 +
1.116 + r=MM::UserCodeChunk->Commit(iCodeAllocBase, codeSize, commitType);
1.117 + if (r<0)
1.118 + {
1.119 + r = KErrNoMemory;
1.120 + goto exit;
1.121 + }
1.122 +
1.123 + iRamInfo.iCodeRunAddr = ((TLinAddr)MM::UserCodeChunk->Base())+iCodeAllocBase;
1.124 + iRamInfo.iCodeLoadAddr = iRamInfo.iCodeRunAddr;
1.125 +
1.126 + if (iRamInfo.iDataSize)
1.127 + {
1.128 + if(iDataPageCount)
1.129 + iRamInfo.iDataLoadAddr = iRamInfo.iCodeLoadAddr+codeSize;
1.130 + else
1.131 + iRamInfo.iDataLoadAddr = iRamInfo.iCodeLoadAddr+iRamInfo.iCodeSize;
1.132 + }
1.133 +
1.134 + if (!iIsDemandPaged)
1.135 + {
1.136 + TInt loadedSize = iRamInfo.iCodeSize+iRamInfo.iDataSize;
1.137 + memset((TAny*)(iRamInfo.iCodeLoadAddr+loadedSize), 0x03, totalSize-loadedSize);
1.138 + }
1.139 + else
1.140 + {
1.141 + if(dataSize)
1.142 + {
1.143 + r=MM::UserCodeChunk->Commit(iCodeAllocBase+codeSize, dataSize, DChunk::ECommitDiscontiguous);
1.144 + if (r<0)
1.145 + goto exit;
1.146 + memset((TAny*)(iRamInfo.iCodeLoadAddr+codeSize+iRamInfo.iDataSize), 0x03, dataSize-iRamInfo.iDataSize);
1.147 + }
1.148 + }
1.149 +
1.150 +exit:
1.151 + DCodeSeg::Signal();
1.152 + return r;
1.153 + }
1.154 +
1.155 +
1.156 +TInt DMemModelCodeSegMemory::Loaded(TCodeSegCreateInfo& aInfo)
1.157 + {
1.158 + TInt r = DMmuCodeSegMemory::Loaded(aInfo);
1.159 + if(r!=KErrNone)
1.160 + return r;
1.161 +
1.162 + Mmu& m=Mmu::Get();
1.163 + TInt pageShift = m.iPageShift;
1.164 +
1.165 + if(iIsDemandPaged)
1.166 + {
1.167 + // apply code fixups to pages which have already been loaded...
1.168 + TLinAddr loadAddr = iRamInfo.iCodeLoadAddr;
1.169 + TLinAddr loadAddrEnd = loadAddr+iRamInfo.iCodeSize;
1.170 + TLinAddr runAddr = iRamInfo.iCodeLoadAddr;
1.171 + TInt pageSize = 1<<pageShift;
1.172 + for(; loadAddr<loadAddrEnd; loadAddr+=pageSize,runAddr+=pageSize)
1.173 + {
1.174 + if(m.LinearToPhysical(loadAddr)!=KPhysAddrInvalid)
1.175 + {
1.176 + r = ApplyCodeFixupsOnLoad((TUint32*)loadAddr,runAddr);
1.177 + if(r!=KErrNone)
1.178 + return r;
1.179 + }
1.180 + }
1.181 + }
1.182 + CacheMaintenance::CodeChanged(iRamInfo.iCodeLoadAddr, iRamInfo.iCodeSize);
1.183 +
1.184 + // discard any temporary pages used to store loaded data section...
1.185 + if(iDataPageCount)
1.186 + {
1.187 + TInt codeSize = iPageCount<<pageShift;
1.188 + MM::UserCodeChunk->Decommit(iCodeAllocBase+codeSize, iDataPageCount<<pageShift);
1.189 + iDataPageCount = 0;
1.190 + //Reduce the size of the DCodeSeg now the data section has been moved
1.191 + iCodeSeg->iSize = codeSize;
1.192 + }
1.193 +
1.194 + return KErrNone;
1.195 + }
1.196 +
1.197 +
1.198 +void DMemModelCodeSegMemory::Destroy()
1.199 + {
1.200 + if(iCodeAllocBase!=KMinTInt && iDataPageCount)
1.201 + {
1.202 + Mmu& m=Mmu::Get();
1.203 + TInt dataSize = iDataPageCount<<m.iPageShift;
1.204 + TInt codeSize = iPageCount<<m.iPageShift;
1.205 + if(dataSize)
1.206 + MM::UserCodeChunk->Decommit(iCodeAllocBase+codeSize, dataSize);
1.207 + }
1.208 + }
1.209 +
1.210 +
1.211 +DMemModelCodeSegMemory::~DMemModelCodeSegMemory()
1.212 + {
1.213 + if(iCodeAllocBase!=KMinTInt)
1.214 + {
1.215 + Mmu& m=Mmu::Get();
1.216 + TInt codeSize = iPageCount<<m.iPageShift;
1.217 + DMemModelChunk::TDecommitType decommitType = iIsDemandPaged ? DChunk::EDecommitVirtual : DChunk::EDecommitNormal;
1.218 + MM::UserCodeChunk->Decommit(iCodeAllocBase, codeSize, decommitType);
1.219 + }
1.220 + }
1.221 +
1.222 +
1.223 +DMemModelCodeSeg::DMemModelCodeSeg()
1.224 +//
1.225 +// Constructor
1.226 +//
1.227 + : iCodeAllocBase(KMinTInt),
1.228 + iDataAllocBase(KMinTInt)
1.229 + {
1.230 + }
1.231 +
1.232 +DMemModelCodeSeg::~DMemModelCodeSeg()
1.233 +//
1.234 +// Destructor
1.235 +//
1.236 + {
1.237 + __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::Destruct %C", this));
1.238 + Mmu& m=Mmu::Get();
1.239 + if (!iXIP && iMemory)
1.240 + {
1.241 + SRamCodeInfo& ri=RamInfo();
1.242 + DCodeSeg::Wait();
1.243 + if (iCodeAllocBase!=KMinTInt)
1.244 + {
1.245 + TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
1.246 + if (kernel)
1.247 + MM::KernelCodeChunk->Decommit(iCodeAllocBase, iSize);
1.248 + }
1.249 + Memory()->Destroy();
1.250 + TInt data_alloc=(ri.iDataSize+ri.iBssSize+m.iPageMask)>>m.iPageShift;
1.251 + if (iDataAllocBase>=0)
1.252 + {
1.253 + MM::DllDataAllocator->Free(iDataAllocBase, data_alloc);
1.254 + }
1.255 + else if (iDataAllocBase==-1)
1.256 + {
1.257 + DMemModelProcess* p=(DMemModelProcess*)iAttachProcess;
1.258 + if (p->iExitType==EExitPending)
1.259 + {
1.260 + DMemModelChunk& c=*p->iDllDataChunk;
1.261 + TInt offset=ri.iDataRunAddr-TLinAddr(c.Base());
1.262 + c.Decommit(offset, data_alloc<<m.iPageShift);
1.263 + if (c.iSize==0)
1.264 + p->FreeDllDataChunk();
1.265 + }
1.266 + }
1.267 + DCodeSeg::Signal();
1.268 + }
1.269 + Kern::Free(iKernelData);
1.270 + DEpocCodeSeg::Destruct();
1.271 + }
1.272 +
1.273 +
1.274 +TInt DMemModelCodeSeg::DoCreateRam(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
1.275 + {
1.276 + __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateRam %C proc %O", this, aProcess));
1.277 + TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
1.278 + DMemModelProcess* p=(DMemModelProcess*)aProcess;
1.279 + Mmu& m=Mmu::Get();
1.280 + SRamCodeInfo& ri=RamInfo();
1.281 + iSize = Mmu::RoundToPageSize(ri.iCodeSize+ri.iDataSize);
1.282 + if (iSize==0)
1.283 + return KErrCorrupt;
1.284 + TInt total_data_size=ri.iDataSize+ri.iBssSize;
1.285 + TInt r=KErrNone;
1.286 + if (kernel)
1.287 + {
1.288 + r=MM::KernelCodeChunk->Allocate(iSize, 0, 0);
1.289 + if (r<0)
1.290 + return r;
1.291 + iCodeAllocBase=r;
1.292 + ri.iCodeRunAddr=(TUint32)MM::KernelCodeChunk->Base();
1.293 + ri.iCodeRunAddr+=r;
1.294 + ri.iCodeLoadAddr=ri.iCodeRunAddr;
1.295 + if (ri.iDataSize)
1.296 + ri.iDataLoadAddr=ri.iCodeLoadAddr+ri.iCodeSize;
1.297 + if (total_data_size)
1.298 + {
1.299 + iKernelData=Kern::Alloc(total_data_size);
1.300 + if (!iKernelData)
1.301 + return KErrNoMemory;
1.302 + ri.iDataRunAddr=(TLinAddr)iKernelData;
1.303 + }
1.304 + return KErrNone;
1.305 + }
1.306 +
1.307 + r = Memory()->Create(aInfo);
1.308 + if(r!=KErrNone)
1.309 + return r;
1.310 +
1.311 + r=KErrNone;
1.312 + if (total_data_size && p && p->iAttributes&DMemModelProcess::EFixedAddress)
1.313 + {
1.314 + SetAttachProcess(p);
1.315 + }
1.316 + if (total_data_size && !IsExe())
1.317 + {
1.318 + TInt data_alloc_size=Mmu::RoundToPageSize(total_data_size);
1.319 + TInt data_alloc=data_alloc_size>>m.iPageShift;
1.320 + DCodeSeg::Wait();
1.321 + if (p)
1.322 + {
1.323 + if (p->iExitType!=EExitPending)
1.324 + return KErrDied;
1.325 + }
1.326 + if (iAttachProcess)
1.327 + {
1.328 + r=KErrNone;
1.329 + if (!p->iDllDataChunk)
1.330 + r=p->CreateDllDataChunk();
1.331 + if (r==KErrNone)
1.332 + {
1.333 + DMemModelChunk& c=*p->iDllDataChunk;
1.334 + r=c.Allocate(data_alloc_size, 0, 0);
1.335 + if (r>=0)
1.336 + {
1.337 + ri.iDataRunAddr=TLinAddr(c.Base())+r;
1.338 + iDataAllocBase=-1;
1.339 + r=KErrNone;
1.340 + }
1.341 + else
1.342 + {
1.343 + if (c.iSize==0)
1.344 + p->FreeDllDataChunk();
1.345 + r=KErrNoMemory;
1.346 + }
1.347 + }
1.348 + }
1.349 + else
1.350 + {
1.351 + r=MM::DllDataAllocator->AllocConsecutive(data_alloc, ETrue);
1.352 + if (r>=0)
1.353 + MM::DllDataAllocator->Alloc(r, data_alloc);
1.354 + if (r>=0)
1.355 + {
1.356 + iDataAllocBase=r;
1.357 + ri.iDataRunAddr=m.iDataSectionEnd-((r+data_alloc)<<m.iPageShift);
1.358 + r=KErrNone;
1.359 + }
1.360 + else
1.361 + r=KErrNoMemory;
1.362 + }
1.363 + DCodeSeg::Signal();
1.364 + }
1.365 + if(r!=KErrNone)
1.366 + return r;
1.367 +
1.368 + return r;
1.369 + }
1.370 +
1.371 +
1.372 +TInt DMemModelCodeSeg::DoCreateXIP(DProcess* aProcess)
1.373 + {
1.374 + __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateXIP %C proc %O", this, aProcess));
1.375 + DMemModelProcess* p=(DMemModelProcess*)aProcess;
1.376 + TInt r=KErrNone;
1.377 + TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
1.378 + const TRomImageHeader& rih=RomInfo();
1.379 + TBool fixed=p && (p->iAttributes&DMemModelProcess::EFixedAddress);
1.380 + if (!kernel && fixed)
1.381 + {
1.382 + // XIP images with static data loaded into fixed processes are specific to a single process
1.383 + if (rih.iFlags&KRomImageFlagDataPresent)
1.384 + {
1.385 + if (rih.iTotalDataSize)
1.386 + {
1.387 + TLinAddr process_data_base=p->iDataBssRunAddress;
1.388 + TUint32 process_data_maxsize=p->iDataBssStackChunk->iMaxSize;
1.389 + if (rih.iDataBssLinearBase<process_data_base ||
1.390 + (rih.iDataBssLinearBase+rih.iTotalDataSize)>(process_data_base+process_data_maxsize))
1.391 + return KErrNotSupported;
1.392 + }
1.393 + SetAttachProcess(p);
1.394 + iDataAllocBase=-1;
1.395 + }
1.396 + }
1.397 + return r;
1.398 + }
1.399 +
1.400 +
1.401 +TInt DMemModelCodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
1.402 + {
1.403 + if (!iXIP)
1.404 + {
1.405 + TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
1.406 + if(kernel)
1.407 + {
1.408 + // Clean DCache for specified area, Invalidate ICache/BTB for specified area
1.409 + SRamCodeInfo& ri=RamInfo();
1.410 + CacheMaintenance::CodeChanged(ri.iCodeRunAddr, ri.iCodeSize);
1.411 + }
1.412 + else
1.413 + {
1.414 + TInt r = Memory()->Loaded(aInfo);
1.415 + if(r!=KErrNone)
1.416 + return r;
1.417 + }
1.418 + }
1.419 + return DEpocCodeSeg::Loaded(aInfo);
1.420 + }
1.421 +
1.422 +
1.423 +void DMemModelCodeSeg::ReadExportDir(TUint32* aDest)
1.424 + {
1.425 + __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::ReadExportDir %08x",aDest));
1.426 + if (!iXIP)
1.427 + {
1.428 + SRamCodeInfo& ri=RamInfo();
1.429 + TInt size=(ri.iExportDirCount+1)*sizeof(TLinAddr);
1.430 + kumemput32(aDest, (const TUint32*)(ri.iExportDir-sizeof(TUint32)), size);
1.431 + }
1.432 + }
1.433 +
1.434 +TBool DMemModelCodeSeg::OpenCheck(DProcess* aProcess)
1.435 + {
1.436 + return FindCheck(aProcess);
1.437 + }
1.438 +
1.439 +TBool DMemModelCodeSeg::FindCheck(DProcess* aProcess)
1.440 + {
1.441 + __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
1.442 + if (!aProcess)
1.443 + return !iAttachProcess; // can't reuse same code segment for a new instance of the process
1.444 + DMemModelProcess& p=*(DMemModelProcess*)aProcess;
1.445 + DCodeSeg* pPSeg=p.CodeSeg();
1.446 + if (iAttachProcess && iAttachProcess!=aProcess)
1.447 + return EFalse;
1.448 + if (iExeCodeSeg && iExeCodeSeg!=pPSeg)
1.449 + return EFalse;
1.450 + if (!iAttachProcess && (iMark & EMarkDataPresent))
1.451 + {
1.452 + // code seg used for moving processes, data present
1.453 + if (p.iAttributes & DMemModelProcess::EFixedAddress)
1.454 + return EFalse;
1.455 + }
1.456 + return ETrue;
1.457 + }