diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.h Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,242 @@ +// Copyright (c) 2007-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: +// This will make sure that the changes in page tables are visible by H/W Page-Table Walk. +// Call this function when two and more consecutive entries in page table are changed. +// +// + +/** +FORCE_INLINE macro in GCC works differently from in VC and armcc. +*/ +#ifdef _MSC_VER +#define REALLY_INLINE __forceinline +#else +#ifdef __GNUC__ +#if __GNUC__ < 3 +#define REALLY_INLINE inline +#else +#define REALLY_INLINE inline __attribute__ ((always_inline)) +#endif +#else +#define REALLY_INLINE inline +#endif +#endif + +/** +This will make sure that the change in page directory is visible by H/W Page-Table Walk. +Call this function when a single entry in page directory is changed. +*/ +extern void SinglePdeUpdated(TPde* aPde); + + +extern void __fastcall DoInvalidateTLBForPage(TLinAddr aLinAddrAndAsid); +extern void DoInvalidateTLB(); + + +/** +Invalidate a single I+D TLB entry on this CPU core only. +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value. +*/ +REALLY_INLINE void __fastcall LocalInvalidateTLBForPage(TLinAddr aLinAddrAndAsid) + { + DoInvalidateTLBForPage(aLinAddrAndAsid); + } + + +#ifndef __SMP__ + +/** +Invalidate a single I+D TLB entry +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value. +*/ +REALLY_INLINE void __fastcall InvalidateTLBForPage(TLinAddr aLinAddrAndAsid) + { + DoInvalidateTLBForPage(aLinAddrAndAsid); + } + + +/** +Invalidate entire TLB +*/ +REALLY_INLINE void InvalidateTLB() + { + DoInvalidateTLB(); + } + + +#else // __SMP__ + + +#define COARSE_GRAINED_TLB_MAINTENANCE + +/** +Invalidate a single I+D TLB entry. +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value. +*/ +extern void InvalidateTLBForPage(TLinAddr aLinAddrAndAsid); + + +/** +Invalidate entire TLB +*/ +extern void InvalidateTLB(); + + +#endif // __SMP__ + + +/** +Invalidate all TLB entries which match the given ASID value +*/ +extern void InvalidateTLBForAsid(TUint aAsid); + + +FORCE_INLINE TPde* Mmu::PageDirectory(TInt aOsAsid) + { + return (TPde*)(KPageDirectoryBase+(aOsAsid<>KChunkShift); + } + + +FORCE_INLINE TPhysAddr Mmu::PdePhysAddr(TPde aPde) + { + if ((aPde&(KPdePtePresent|KPdeLargePage)) == (KPdePtePresent|KPdeLargePage)) + return aPde & KPdeLargePagePhysAddrMask; + return KPhysAddrInvalid; + } + + +FORCE_INLINE TPte Mmu::MakePteInaccessible(TPte aPte, TBool aReadOnly) + { + if(aReadOnly) + return aPte&~KPdePteWrite; + else + return aPte&~KPdePtePresent; + } + + +FORCE_INLINE TPte Mmu::MakePteAccessible(TPte aPte, TBool aWrite) + { + if((aPte&KPdePtePresent)==0) + { + aPte |= KPdePtePresent; + aPte &= ~KPdePteWrite; + } + if(aWrite) + aPte |= KPdePteWrite; + return aPte; + } + + +FORCE_INLINE TBool Mmu::IsPteReadOnly(TPte aPte) + { + __NK_ASSERT_DEBUG(aPte&KPdePtePresent); // read-only state is ambiguous if pte not present + return !(aPte&KPdePteWrite); + } + + +FORCE_INLINE TBool Mmu::IsPteInaccessible(TPte aPte) + { + return !(aPte&KPdePtePresent); + } + + +FORCE_INLINE TBool Mmu::IsPteMoreAccessible(TPte aNewPte, TPte aOldPte) + { + if(aNewPte&aOldPte&KPdePtePresent) // if ptes both present + return (aNewPte&~aOldPte)&KPdePteWrite; // check for more writable + else // else + return aNewPte&KPdePtePresent; // check for new pte being present + } + + +enum TPdeType + { + ENumPdeTypes = 1 + }; + + +enum TPteType + { + EPteTypeUserAccess = EUser, + EPteTypeWritable = EReadWrite, + EPteTypeGlobal = 1<<2, + ENumPteTypes = 8 + }; + +__ASSERT_COMPILE(EPteTypeUserAccess==(1<<0)); +__ASSERT_COMPILE(EPteTypeWritable==(1<<1)); + + +FORCE_INLINE TUint Mmu::PdeType(TMemoryAttributes /*aAttributes*/) + { + return 0; + } + + +FORCE_INLINE TUint Mmu::PteType(TMappingPermissions aPermissions, TBool aGlobal) + { + __NK_ASSERT_DEBUG(aPermissions&EUser || aGlobal); // can't have supervisor local memory + + TUint pteType = (aPermissions&(EUser|EReadWrite)); + if(aGlobal) + pteType |= EPteTypeGlobal; + + __NK_ASSERT_DEBUG(pteType