diff -r 000000000000 -r a41df078684a kernel/eka/include/memmodel/epoc/moving/memmodel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/memmodel/epoc/moving/memmodel.h Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,438 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\include\memmodel\epoc\moving\memmodel.h +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +#ifndef __MEMMODEL_H__ +#define __MEMMODEL_H__ +#include + +/******************************************** + * Deterministic Scheduler Implementation + ********************************************/ + +/** +@internalComponent +*/ +#define TheCurrentAddressSpace ((DMemModelProcess*&)TheScheduler.iAddressSpace) + +/** +@internalComponent +*/ +#define TheCurrentVMProcess ((DMemModelProcess*&)TheScheduler.iExtras[0]) + +/** +@internalComponent +*/ +#define TheCurrentDataSectionProcess ((DMemModelProcess*&)TheScheduler.iExtras[1]) + +/** +@internalComponent +*/ +#define TheCompleteDataSectionProcess ((DMemModelProcess*&)TheScheduler.iExtras[2]) + +/** +@internalComponent +*/ +#define FlushProgress ((TInt&)TheScheduler.iExtras[3]) + + +/******************************************** + * Process Control Block + ********************************************/ +/** +@internalComponent +*/ +const TInt KMaxChunksInProcess=16; + +class DMemModelChunk; +/** +@internalComponent +*/ +class DMemModelProcess : public DEpocProcess + { +public: + void Destruct(); +public: + virtual TInt DoCreate(TBool aKernelProcess, TProcessCreateInfo& aInfo); + virtual TInt NewChunk(DChunk*& aChunk, SChunkCreateInfo& anInfo, TLinAddr& aRunAddr); + virtual TInt AddChunk(DChunk* aChunk,TBool isReadOnly); + virtual TInt NewShPool(DShPool*& aPool, TShPoolCreateInfo& aInfo); + virtual TInt CreateDataBssStackArea(TProcessCreateInfo& aInfo); + virtual TInt MapCodeSeg(DCodeSeg* aCodeSeg); + virtual void UnmapCodeSeg(DCodeSeg* aCodeSeg); + virtual void RemoveDllData(); + virtual void FinalRelease(); +public: + virtual TInt GetNewChunk(DMemModelChunk*& aChunk, SChunkCreateInfo& anInfo)=0; + virtual TInt AddFixedAccessChunk(DMemModelChunk *aChunk)=0; + virtual TInt RemoveFixedAccessChunk(DMemModelChunk *aChunk)=0; + virtual void CheckForFixedAccess()=0; + virtual void DoAttributeChange()=0; +public: + TInt AddChunk(DMemModelChunk* aChunk, TLinAddr& aDataSectionBase, TBool isReadOnly); + TInt AllocateDataSectionBase(DMemModelChunk& aChunk, TUint& aBase); + TUint8* DataSectionBase(DMemModelChunk* aChunk); + void RemoveChunk(DMemModelChunk *aChunk); + void DoRemoveChunk(TInt aIndex); + TInt ChunkIndex(DMemModelChunk* aChunk,TInt& aPos); + TInt CreateDllDataChunk(); + void FreeDllDataChunk(); + TInt CommitDllData(TLinAddr aBase, TInt aSize); + void DecommitDllData(TLinAddr aBase, TInt aSize); +public: + enum TMemModelProcessAttributes + { + EFixedAddress=1, + EMoving=0x40000000, + EVariableAccess=0x20000000, +// EMovingCode=0x10000000, NEVER USED + EVariableCode=0x04000000, + EMMProcessAttributesMask = EFixedAddress|EMoving|EVariableAccess|EVariableCode, + }; + + struct SChunkInfo + { + TLinAddr iDataSectionBase; + DMemModelChunk *iChunk; + TInt16 iAccessCount; + TInt16 isReadOnly; + }; + + TInt iNumChunks; + SChunkInfo iChunks[KMaxChunksInProcess]; + TInt iNumMovingChunks; + TInt iNumNonFixedAccessChunks; + TInt iNumNonFixedAccessCodeChunks; + DMemModelChunk* iDllDataChunk; +public: + friend class Monitor; + }; + + +/******************************************** + * Chunk Control Block + ********************************************/ +/** +@internalComponent +*/ +class DMemModelChunk : public DChunk + { +public: + /** + @see DChunk::TChunkAttributes for generic attribute flags + */ + enum TMemModelChunkAttributes + { + EFixedAccess =0x80000000, + EFixedAddress =0x40000000, + EPrivate =0x10000000, + ECode =0x08000000, + + EMMChunkAttributesMask = EFixedAccess | EFixedAddress | EPrivate | ECode, + }; + + enum TChunkState {ENotRunning=0, ERunningRO=1, ERunningRW=2}; +public: + DMemModelChunk(); + void Destruct(); +public: + virtual TInt Close(TAny* aPtr); + virtual TInt DoCreate(SChunkCreateInfo& anInfo); + virtual TInt Adjust(TInt aNewSize); + virtual TInt AdjustDoubleEnded(TInt aBottom, TInt aTop); + virtual TInt CheckAccess(); + virtual TInt Commit(TInt anOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0); + virtual TInt Allocate(TInt aSize, TInt aGuard=0, TInt aAlign=0); + TInt Decommit(TInt anOffset, TInt aSize); + virtual TInt Lock(TInt anOffset, TInt aSize); + virtual TInt Unlock(TInt anOffset, TInt aSize); + virtual TInt Address(TInt aOffset, TInt aSize, TLinAddr& aKernelAddress); + virtual TInt PhysicalAddress(TInt aOffset, TInt aSize, TLinAddr& aKernelAddress, TUint32& aPhysicalAddress, TUint32* aPhysicalPageList=NULL); + virtual void BTracePrime(TInt aCategory); + virtual void Substitute(TInt aOffset, TPhysAddr aOldAddr, TPhysAddr aNewAddr); + virtual TUint8* Base(DProcess* aProcess); + inline TUint8* Base() const { return DChunk::Base(); } +public: + TInt Decommit(TInt aOffset, TInt aSize, TDecommitType aDecommitType); + TInt FindFree(TInt aSize, TInt aGuard, TInt aAlign); + void SetFixedAddress(TLinAddr anAddr, TInt anInitialSize); + TInt Reserve(TInt anInitialSize); + TUint32 ApplyTopLevelPermissions(TChunkState aChunkState); + TUint32 MoveToRunAddress(TLinAddr aLinearAddr,TChunkState aChunkState); + TUint32 MoveToHomeSection(); + TZonePageType GetPageType(); +protected: + TInt DoCommit(TInt aOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0); + void DoDecommit(TInt aOffset, TInt aSize, TDecommitType aDecommitType=EDecommitNormal); +private: + void ClaimInitialPages(); + TInt ExpandHomeRegion(TInt anOffset, TInt aSize); + TLinAddr AllocateHomeAddress(TInt aSize); + void DeallocateHomeAddress(); + TLinAddr ReallocateHomeAddress(TInt aNewSize); + TInt DoAllocate(TInt aSize, TInt aGuard, TInt aAlign, TBool aCommit); +private: + virtual TInt SetupPermissions()=0; + virtual void AddPde(TInt anOffset)=0; + virtual void RemovePde(TInt anOffset)=0; + virtual void MoveHomePdes(TLinAddr anOldAddr, TLinAddr aNewAddr)=0; + virtual void MoveCurrentPdes(TLinAddr anOldAddr, TLinAddr aNewAddr)=0; +public: + TChunkState iChunkState; + TPte iPtePermissions; + TPde iPdePermissions[3]; // indexed by iChunkState + TInt iHomeRegionOffset; + TInt iHomeRegionSize; + TLinAddr iHomeRegionBase; + TLinAddr iHomeBase; + TInt iNumPdes; + TPde* iPdes; + TPde* iHomePdes; + TUint32* iPdeBitMap; + TBitMapAllocator* iPageBitMap; + TBitMapAllocator* iPermanentPageBitMap; +public: + friend class Monitor; + }; + + +/******************************************** + * Code segment + ********************************************/ + +class DMemModelCodeSegMemory : public DMmuCodeSegMemory + { +public: + DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg); + ~DMemModelCodeSegMemory(); + TInt Create(TCodeSegCreateInfo& aInfo); + TInt Loaded(TCodeSegCreateInfo& aInfo); + void Destroy(); + }; + +/** +@internalComponent +*/ +class DMemModelCodeSeg: public DEpocCodeSeg + { +public: + DMemModelCodeSeg(); + virtual ~DMemModelCodeSeg(); + virtual TInt DoCreateRam(TCodeSegCreateInfo& aInfo, DProcess* aProcess); + virtual TInt DoCreateXIP(DProcess* aProcess); + virtual TInt Loaded(TCodeSegCreateInfo& aInfo); + virtual void ReadExportDir(TUint32* aDest); + virtual TBool FindCheck(DProcess* aProcess); + virtual TBool OpenCheck(DProcess* aProcess); + inline DMemModelCodeSegMemory* Memory() + { return (DMemModelCodeSegMemory*)iMemory; } +public: + TInt iCodeAllocBase; + TInt iDataAllocBase; + TAny* iKernelData; // only for kernel modules + }; + + +/******************************************** + * MMU stuff + ********************************************/ + +typedef void (*TCopyPageFn)(TLinAddr aDest, TLinAddr aSrc); + +/** +@internalComponent +*/ +class Mmu : public MmuBase + { +public: + enum TFlushFlags { + EFlushDTLB=0x01, + EFlushDCache=0x02, + EFlushITLB=0x04, + EFlushICache=0x08, + EFlushDDecommit=0x80000000, + EFlushDPermChg=0x20000000, // =DProcess::EVariableAccess + EFlushDMove=0x40000000, // =DProcess::EMoving + EFlushIPermChg=0x04000000, // =DProcess::EVariableCode + EFlushIMove=0x10000000, // =DProcess::EMovingCode + EFlushInheritMask=EFlushDPermChg|EFlushDMove|EFlushIPermChg|EFlushIMove, + }; + + enum TPanic + { + EBadInitialPageAddr, + EAssignPageTableInvalidUsage, + EUserCodeAllocatorCreateFailed, + EDllDataAllocatorCreateFailed, + ERomUserDataAddressInvalid, + ERomUserDataSizeInvalid, + ERomLinearAddressInvalid, + ERemapPageFailed, + ERemapPageTableFailed, + ENoCopyPageFunction, + EFixupXPTFailed, + ECacheMaintenance, + EDefragDisablePageFailed, + EDefragFaultWhilstFMHeld, + EDefragKernelChunkNoPageTable, + }; + +public: + inline TPde& PDE(TLinAddr aAddr) + {return *(((TPde*)iPdeBase)+(aAddr>>iChunkShift));} + + // virtual - inherited/overridden from MmuBase + virtual void Init1(); +// virtual void Init2(); + virtual void DoInit2(); +// virtual TBool PteIsPresent(TPte aPte)=0; +// virtual TPhysAddr PtePhysAddr(TPte aPte, TInt aPteIndex)=0; +// virtual TPhysAddr PdePhysAddr(TLinAddr aAddr)=0; + virtual void SetupInitialPageInfo(SPageInfo* aPageInfo, TLinAddr aChunkAddr, TInt aPdeIndex); + virtual void SetupInitialPageTableInfo(TInt aId, TLinAddr aChunkAddr, TInt aNumPtes); + virtual void AssignPageTable(TInt aId, TInt aUsage, TAny* aObject, TLinAddr aAddr, TPde aPdePerm); + virtual TInt UnassignPageTable(TLinAddr aAddr); +// virtual void BootstrapPageTable(TInt aXptId, TPhysAddr aXptPhys, TInt aId, TPhysAddr aPhysAddr)=0; + virtual TInt PageTableId(TLinAddr aAddr); +// virtual TInt BootPageTableId(TLinAddr aAddr, TPhysAddr& aPtPhys)=0; +// virtual void ClearPageTable(TInt aId, TInt aFirstIndex=0)=0; +// virtual TPhysAddr LinearToPhysical(TLinAddr aAddr)=0; +// virtual TInt LinearToPhysical(TLinAddr aAddr, TInt aSize, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList=NULL)=0; +// virtual void MapRamPages(TInt aId, SPageInfo::TType aType, TAny* aPtr, TUint32 aOffset, const TPhysAddr* aPageList, TInt aNumPages, TPte aPtePerm)=0; +// virtual void MapPhysicalPages(TInt aId, SPageInfo::TType aType, TAny* aPtr, TUint32 aOffset, TPhysAddr aPhysAddr, TInt aNumPages, TPte aPtePerm)=0; +// virtual TInt UnmapPages(TInt aId, TUint32 aAddr, TInt aNumPages, TPhysAddr* aPageList, TBool aSetPagesFree, TInt& aNumPtes, TInt& aNumFree, DProcess* aProcess)=0; +// virtual void ClearRamDrive(TLinAddr aStart)=0; +// virtual TInt PdePtePermissions(TUint& aMapAttr, TPde& aPde, TPte& aPte)=0; +// virtual void Map(TLinAddr aLinAddr, TPhysAddr aPhysAddr, TInt aSize, TPde aPdePerm, TPte aPtePerm, TInt aMapShift)=0; +// virtual void Unmap(TLinAddr aLinAddr, TInt aSize)=0; +// virtual void InitShadowPageTable(TInt aId, TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0; +// virtual void InitShadowPage(TPhysAddr aShadowPhys, TLinAddr aRomAddr)=0; +// virtual void DoUnmapShadowPage(TInt aId, TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0; +// virtual TInt UnassignShadowPageTable(TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0; +// virtual void DoFreezeShadowPage(TInt aId, TLinAddr aRomAddr)=0; +// virtual void FlushShadow(TLinAddr aRomAddr)=0; +// virtual void AssignShadowPageTable(TInt aId, TLinAddr aRomAddr)=0; +// virtual void ClearPages(TInt aNumPages, TPhysAddr* aPageList)=0; + virtual TPte PtePermissions(TChunkType aChunkType)=0; + virtual TInt MoveKernelPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest); + virtual TInt MoveCodeSegMemoryPage(DMemModelCodeSegMemory* aCodeSegMemory, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest); + virtual TInt MoveCodeChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest); + virtual TInt MoveDataChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest); + + // pure virtual - new in Mmu + virtual void DoAssignPageTable(TInt aId, TLinAddr aAddr, TPde aPdePerm)=0; + virtual void RemapPageTable(TPhysAddr aOld, TPhysAddr aNewId, TLinAddr aAddr)=0; + virtual void DoUnassignPageTable(TLinAddr aAddr)=0; + virtual void MoveChunk(TLinAddr anInitAddr, TUint aSize, TLinAddr aFinalAddr, TPde aPermissions)=0; + virtual void MoveChunk(TLinAddr anInitAddr, TLinAddr aFinalAddr, TInt aNumPdes)=0; + virtual void ApplyTopLevelPermissions(TLinAddr anAddr, TUint aChunkSize, TPde aPermissions)=0; + virtual void ApplyPagePermissions(TInt aId, TInt aPageOffset, TInt aNumPages, TPte aPtePerm)=0; + virtual void SyncCodeMappings()=0; + virtual void GenericFlush(TUint32 aMask)=0; + virtual TPde PdePermissions(TChunkType aChunkType, TInt aChunkState)=0; + virtual TInt UnlockRamCachePages(TUint8* volatile & aBase, TInt aFirstPage, TInt aNumPages)=0; + virtual TInt LockRamCachePages(TUint8* volatile & aBase, TInt aFirstPage, TInt aNumPages)=0; + virtual void MapVirtual(TInt aId, TInt aNumPages)=0; + virtual TInt UnmapVirtual(TInt aId, TUint32 aAddr, TInt aNumPages, TPhysAddr* aPageList, TBool aSetPagesFree, TInt& aNumPtes, TInt& aNumFree, DProcess* aProcess)=0; + virtual TLinAddr MapTemp(TPhysAddr aPage, TBool aCached)=0; + virtual TLinAddr MapSecondTemp(TPhysAddr aPage, TBool aCached)=0; + virtual void UnmapTemp()=0; + virtual void UnmapSecondTemp()=0; + virtual void RemapKernelPage(TInt aId, TLinAddr aSrc, TLinAddr aDest, TPhysAddr aNewPhys, TPte aPtePerm)=0; + virtual TInt PreparePagesForDMA(TLinAddr aAddr, TInt aSize, TPhysAddr* aPhysicalPageList)=0; + virtual TInt ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)=0; + +public: + TInt GetPageTableId(TLinAddr aAddr); +public: + inline static Mmu& Get() + {return *(Mmu*)TheMmu;} + inline void CopyPageForRemap(TLinAddr aDest, TLinAddr aSrc) + {iCopyPageFn(aDest, aSrc);} + static void Panic(TPanic aPanic); +public: + TLinAddr iDataSectionBase; // lowest data section address + TLinAddr iDllDataBase; // start of DLL static data area + TLinAddr iDataSectionEnd; // highest data section address + 1 + TInt iMaxDllDataSize; + TLinAddr iUserCodeBase; + TInt iMaxUserCodeSize; + TLinAddr iKernelCodeBase; + TInt iMaxKernelCodeSize; + TLinAddr iPdeBase; + TPte iUserCodeLoadPtePerm; + TPte iKernelCodePtePerm; + TUint32* iHomePdeMap; + TCopyPageFn iCopyPageFn; + TPte* iSecondTempPte; // second PTE used for temporary mappings + TLinAddr iSecondTempAddr; // address corresponding to iSecondTempPte + }; + + +/******************************************** + * Functions/Data defined in memory model + ********************************************/ + +/** +@internalComponent +*/ +class MM + { +public: + enum TMemModelPanic + { + EUserCodeNotFixed=0, + EClaimInitialPagesBadPageTable=1, + EFreeInvalidDomain=2, + EFreeDomainNotAllocated=3, + EFixedChunkMoving=4, + EChunkDecommitNoPageTable=5, + ECommitInvalidDllDataAddress=6, + EDecommitInvalidDllDataAddress=7, + EPdeAlreadyInUse=8, + EPteAlreadyInUse=9, + EMmuMapNoPageTable=10, + EUnmapBadAlignment=11, + EBootstrapPageTableBadAddr=12, + EAddFixedBadPerm=13, + ERemoveFixedBadPerm=14, + EUnexpectedPageType=15, + EOperationNotImplemented=16, + ECodeAddressOutOfRange=17, + ETempMappingAlreadyInUse=18, + EChunkRemapNoPageTable=19, + EChunkRemapWrongPageTable=20, + }; + + static void Panic(TMemModelPanic aPanic); +public: + static void Init1(); + static TAny* CurrentAddress(DThread* aThread, const TAny* aAddress, TInt aSize, TBool aWrite); + static void StartCrashDebugger(); + static TInt CreateCodeChunk(TBool aKernel); +public: + static TInt MaxPagesInOneGo; + static DMemModelChunk* SvStackChunk; + static DMemModelChunk* TheRamDriveChunk; + static DMemModelChunk* UserCodeChunk; + static DMemModelChunk* KernelCodeChunk; + static TBitMapAllocator* DllDataAllocator; + }; + +#endif