First public contribution.
1 // Copyright (c) 1995-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\mcodeseg.cpp
19 #include "cache_maintenance.h"
20 #include <demand_paging.h>
22 _LIT(KLitUserCode,"USER$CODE");
23 _LIT(KLitKernCode,"KERN$CODE");
25 TInt MM::CreateCodeChunk(TBool aKernel)
27 __KTRACE_OPT(KDLL,Kern::Printf("MM::CreateCodeChunk %d",aKernel));
31 c.iAtt = TChunkCreate::EDisconnected;
32 c.iForceFixed = EFalse;
39 c.iRunAddress = m.iKernelCodeBase;
40 c.iType = EKernelCode;
41 c.iMaxSize = m.iMaxKernelCodeSize;
42 c.iName.Set(KLitKernCode);
46 c.iRunAddress = m.iUserCodeBase;
48 c.iMaxSize = m.iMaxUserCodeSize;
49 c.iName.Set(KLitUserCode);
53 DMemModelChunk* pC = NULL;
54 TInt r=K::TheKernelProcess->NewChunk((DChunk*&)pC, c, runAddr);
57 pC->SetFixedAddress(c.iRunAddress, 0);
59 MM::KernelCodeChunk = pC;
61 MM::UserCodeChunk = pC;
66 DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
68 // Create a new instance of this class.
72 __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
73 return new DMemModelCodeSeg;
77 DEpocCodeSegMemory* DEpocCodeSegMemory::New(DEpocCodeSeg* aCodeSeg)
79 return new DMemModelCodeSegMemory(aCodeSeg);
83 DMemModelCodeSegMemory::DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg)
84 : DMmuCodeSegMemory(aCodeSeg)
89 TInt DMemModelCodeSegMemory::Create(TCodeSegCreateInfo& aInfo)
91 TInt r = DMmuCodeSegMemory::Create(aInfo);
97 TInt codeSize = iPageCount<<m.iPageShift;
98 TInt dataSize = iDataPageCount<<m.iPageShift;
99 TInt totalSize = codeSize+dataSize;
103 DChunk::TCommitType commitType = iIsDemandPaged ? DChunk::ECommitVirtual : DChunk::ECommitDiscontiguous;
104 r=MM::UserCodeChunk->FindFree(totalSize, 0, 0);
113 r=MM::UserCodeChunk->Commit(iCodeAllocBase, codeSize, commitType);
120 iRamInfo.iCodeRunAddr = ((TLinAddr)MM::UserCodeChunk->Base())+iCodeAllocBase;
121 iRamInfo.iCodeLoadAddr = iRamInfo.iCodeRunAddr;
123 if (iRamInfo.iDataSize)
126 iRamInfo.iDataLoadAddr = iRamInfo.iCodeLoadAddr+codeSize;
128 iRamInfo.iDataLoadAddr = iRamInfo.iCodeLoadAddr+iRamInfo.iCodeSize;
133 TInt loadedSize = iRamInfo.iCodeSize+iRamInfo.iDataSize;
134 memset((TAny*)(iRamInfo.iCodeLoadAddr+loadedSize), 0x03, totalSize-loadedSize);
140 r=MM::UserCodeChunk->Commit(iCodeAllocBase+codeSize, dataSize, DChunk::ECommitDiscontiguous);
143 memset((TAny*)(iRamInfo.iCodeLoadAddr+codeSize+iRamInfo.iDataSize), 0x03, dataSize-iRamInfo.iDataSize);
153 TInt DMemModelCodeSegMemory::Loaded(TCodeSegCreateInfo& aInfo)
155 TInt r = DMmuCodeSegMemory::Loaded(aInfo);
160 TInt pageShift = m.iPageShift;
164 // apply code fixups to pages which have already been loaded...
165 TLinAddr loadAddr = iRamInfo.iCodeLoadAddr;
166 TLinAddr loadAddrEnd = loadAddr+iRamInfo.iCodeSize;
167 TLinAddr runAddr = iRamInfo.iCodeLoadAddr;
168 TInt pageSize = 1<<pageShift;
169 for(; loadAddr<loadAddrEnd; loadAddr+=pageSize,runAddr+=pageSize)
171 if(m.LinearToPhysical(loadAddr)!=KPhysAddrInvalid)
173 r = ApplyCodeFixupsOnLoad((TUint32*)loadAddr,runAddr);
179 CacheMaintenance::CodeChanged(iRamInfo.iCodeLoadAddr, iRamInfo.iCodeSize);
181 // discard any temporary pages used to store loaded data section...
184 TInt codeSize = iPageCount<<pageShift;
185 MM::UserCodeChunk->Decommit(iCodeAllocBase+codeSize, iDataPageCount<<pageShift);
187 //Reduce the size of the DCodeSeg now the data section has been moved
188 iCodeSeg->iSize = codeSize;
195 void DMemModelCodeSegMemory::Destroy()
197 if(iCodeAllocBase!=KMinTInt && iDataPageCount)
200 TInt dataSize = iDataPageCount<<m.iPageShift;
201 TInt codeSize = iPageCount<<m.iPageShift;
203 MM::UserCodeChunk->Decommit(iCodeAllocBase+codeSize, dataSize);
208 DMemModelCodeSegMemory::~DMemModelCodeSegMemory()
210 if(iCodeAllocBase!=KMinTInt)
213 TInt codeSize = iPageCount<<m.iPageShift;
214 DMemModelChunk::TDecommitType decommitType = iIsDemandPaged ? DChunk::EDecommitVirtual : DChunk::EDecommitNormal;
215 MM::UserCodeChunk->Decommit(iCodeAllocBase, codeSize, decommitType);
220 DMemModelCodeSeg::DMemModelCodeSeg()
224 : iCodeAllocBase(KMinTInt),
225 iDataAllocBase(KMinTInt)
229 DMemModelCodeSeg::~DMemModelCodeSeg()
234 __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::Destruct %C", this));
236 if (!iXIP && iMemory)
238 SRamCodeInfo& ri=RamInfo();
240 if (iCodeAllocBase!=KMinTInt)
242 TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
244 MM::KernelCodeChunk->Decommit(iCodeAllocBase, iSize);
247 TInt data_alloc=(ri.iDataSize+ri.iBssSize+m.iPageMask)>>m.iPageShift;
248 if (iDataAllocBase>=0)
250 MM::DllDataAllocator->Free(iDataAllocBase, data_alloc);
252 else if (iDataAllocBase==-1)
254 DMemModelProcess* p=(DMemModelProcess*)iAttachProcess;
255 if (p->iExitType==EExitPending)
257 DMemModelChunk& c=*p->iDllDataChunk;
258 TInt offset=ri.iDataRunAddr-TLinAddr(c.Base());
259 c.Decommit(offset, data_alloc<<m.iPageShift);
261 p->FreeDllDataChunk();
266 Kern::Free(iKernelData);
267 DEpocCodeSeg::Destruct();
271 TInt DMemModelCodeSeg::DoCreateRam(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
273 __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateRam %C proc %O", this, aProcess));
274 TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
275 DMemModelProcess* p=(DMemModelProcess*)aProcess;
277 SRamCodeInfo& ri=RamInfo();
278 iSize = Mmu::RoundToPageSize(ri.iCodeSize+ri.iDataSize);
281 TInt total_data_size=ri.iDataSize+ri.iBssSize;
285 r=MM::KernelCodeChunk->Allocate(iSize, 0, 0);
289 ri.iCodeRunAddr=(TUint32)MM::KernelCodeChunk->Base();
291 ri.iCodeLoadAddr=ri.iCodeRunAddr;
293 ri.iDataLoadAddr=ri.iCodeLoadAddr+ri.iCodeSize;
296 iKernelData=Kern::Alloc(total_data_size);
299 ri.iDataRunAddr=(TLinAddr)iKernelData;
304 r = Memory()->Create(aInfo);
309 if (total_data_size && p && p->iAttributes&DMemModelProcess::EFixedAddress)
313 if (total_data_size && !IsExe())
315 TInt data_alloc_size=Mmu::RoundToPageSize(total_data_size);
316 TInt data_alloc=data_alloc_size>>m.iPageShift;
320 if (p->iExitType!=EExitPending)
326 if (!p->iDllDataChunk)
327 r=p->CreateDllDataChunk();
330 DMemModelChunk& c=*p->iDllDataChunk;
331 r=c.Allocate(data_alloc_size, 0, 0);
334 ri.iDataRunAddr=TLinAddr(c.Base())+r;
341 p->FreeDllDataChunk();
348 r=MM::DllDataAllocator->AllocConsecutive(data_alloc, ETrue);
350 MM::DllDataAllocator->Alloc(r, data_alloc);
354 ri.iDataRunAddr=m.iDataSectionEnd-((r+data_alloc)<<m.iPageShift);
369 TInt DMemModelCodeSeg::DoCreateXIP(DProcess* aProcess)
371 __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateXIP %C proc %O", this, aProcess));
372 DMemModelProcess* p=(DMemModelProcess*)aProcess;
374 TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
375 const TRomImageHeader& rih=RomInfo();
376 TBool fixed=p && (p->iAttributes&DMemModelProcess::EFixedAddress);
377 if (!kernel && fixed)
379 // XIP images with static data loaded into fixed processes are specific to a single process
380 if (rih.iFlags&KRomImageFlagDataPresent)
382 if (rih.iTotalDataSize)
384 TLinAddr process_data_base=p->iDataBssRunAddress;
385 TUint32 process_data_maxsize=p->iDataBssStackChunk->iMaxSize;
386 if (rih.iDataBssLinearBase<process_data_base ||
387 (rih.iDataBssLinearBase+rih.iTotalDataSize)>(process_data_base+process_data_maxsize))
388 return KErrNotSupported;
398 TInt DMemModelCodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
402 TBool kernel=( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel );
405 // Clean DCache for specified area, Invalidate ICache/BTB for specified area
406 SRamCodeInfo& ri=RamInfo();
407 CacheMaintenance::CodeChanged(ri.iCodeRunAddr, ri.iCodeSize);
411 TInt r = Memory()->Loaded(aInfo);
416 return DEpocCodeSeg::Loaded(aInfo);
420 void DMemModelCodeSeg::ReadExportDir(TUint32* aDest)
422 __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::ReadExportDir %08x",aDest));
425 SRamCodeInfo& ri=RamInfo();
426 TInt size=(ri.iExportDirCount+1)*sizeof(TLinAddr);
427 kumemput32(aDest, (const TUint32*)(ri.iExportDir-sizeof(TUint32)), size);
431 TBool DMemModelCodeSeg::OpenCheck(DProcess* aProcess)
433 return FindCheck(aProcess);
436 TBool DMemModelCodeSeg::FindCheck(DProcess* aProcess)
438 __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
440 return !iAttachProcess; // can't reuse same code segment for a new instance of the process
441 DMemModelProcess& p=*(DMemModelProcess*)aProcess;
442 DCodeSeg* pPSeg=p.CodeSeg();
443 if (iAttachProcess && iAttachProcess!=aProcess)
445 if (iExeCodeSeg && iExeCodeSeg!=pPSeg)
447 if (!iAttachProcess && (iMark & EMarkDataPresent))
449 // code seg used for moving processes, data present
450 if (p.iAttributes & DMemModelProcess::EFixedAddress)