1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,242 @@
1.4 +// Copyright (c) 2007-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 +// This will make sure that the changes in page tables are visible by H/W Page-Table Walk.
1.18 +// Call this function when two and more consecutive entries in page table are changed.
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 +FORCE_INLINE macro in GCC works differently from in VC and armcc.
1.24 +*/
1.25 +#ifdef _MSC_VER
1.26 +#define REALLY_INLINE __forceinline
1.27 +#else
1.28 +#ifdef __GNUC__
1.29 +#if __GNUC__ < 3
1.30 +#define REALLY_INLINE inline
1.31 +#else
1.32 +#define REALLY_INLINE inline __attribute__ ((always_inline))
1.33 +#endif
1.34 +#else
1.35 +#define REALLY_INLINE inline
1.36 +#endif
1.37 +#endif
1.38 +
1.39 +/**
1.40 +This will make sure that the change in page directory is visible by H/W Page-Table Walk.
1.41 +Call this function when a single entry in page directory is changed.
1.42 +*/
1.43 +extern void SinglePdeUpdated(TPde* aPde);
1.44 +
1.45 +
1.46 +extern void __fastcall DoInvalidateTLBForPage(TLinAddr aLinAddrAndAsid);
1.47 +extern void DoInvalidateTLB();
1.48 +
1.49 +
1.50 +/**
1.51 +Invalidate a single I+D TLB entry on this CPU core only.
1.52 +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
1.53 +*/
1.54 +REALLY_INLINE void __fastcall LocalInvalidateTLBForPage(TLinAddr aLinAddrAndAsid)
1.55 + {
1.56 + DoInvalidateTLBForPage(aLinAddrAndAsid);
1.57 + }
1.58 +
1.59 +
1.60 +#ifndef __SMP__
1.61 +
1.62 +/**
1.63 +Invalidate a single I+D TLB entry
1.64 +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
1.65 +*/
1.66 +REALLY_INLINE void __fastcall InvalidateTLBForPage(TLinAddr aLinAddrAndAsid)
1.67 + {
1.68 + DoInvalidateTLBForPage(aLinAddrAndAsid);
1.69 + }
1.70 +
1.71 +
1.72 +/**
1.73 +Invalidate entire TLB
1.74 +*/
1.75 +REALLY_INLINE void InvalidateTLB()
1.76 + {
1.77 + DoInvalidateTLB();
1.78 + }
1.79 +
1.80 +
1.81 +#else // __SMP__
1.82 +
1.83 +
1.84 +#define COARSE_GRAINED_TLB_MAINTENANCE
1.85 +
1.86 +/**
1.87 +Invalidate a single I+D TLB entry.
1.88 +@param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
1.89 +*/
1.90 +extern void InvalidateTLBForPage(TLinAddr aLinAddrAndAsid);
1.91 +
1.92 +
1.93 +/**
1.94 +Invalidate entire TLB
1.95 +*/
1.96 +extern void InvalidateTLB();
1.97 +
1.98 +
1.99 +#endif // __SMP__
1.100 +
1.101 +
1.102 +/**
1.103 +Invalidate all TLB entries which match the given ASID value
1.104 +*/
1.105 +extern void InvalidateTLBForAsid(TUint aAsid);
1.106 +
1.107 +
1.108 +FORCE_INLINE TPde* Mmu::PageDirectory(TInt aOsAsid)
1.109 + {
1.110 + return (TPde*)(KPageDirectoryBase+(aOsAsid<<KPageDirectoryShift));
1.111 + }
1.112 +
1.113 +
1.114 +FORCE_INLINE TPde* Mmu::PageDirectoryEntry(TInt aOsAsid, TLinAddr aAddress)
1.115 + {
1.116 + return PageDirectory(aOsAsid) + (aAddress>>KChunkShift);
1.117 + }
1.118 +
1.119 +
1.120 +FORCE_INLINE TPhysAddr Mmu::PdePhysAddr(TPde aPde)
1.121 + {
1.122 + if ((aPde&(KPdePtePresent|KPdeLargePage)) == (KPdePtePresent|KPdeLargePage))
1.123 + return aPde & KPdeLargePagePhysAddrMask;
1.124 + return KPhysAddrInvalid;
1.125 + }
1.126 +
1.127 +
1.128 +FORCE_INLINE TPte Mmu::MakePteInaccessible(TPte aPte, TBool aReadOnly)
1.129 + {
1.130 + if(aReadOnly)
1.131 + return aPte&~KPdePteWrite;
1.132 + else
1.133 + return aPte&~KPdePtePresent;
1.134 + }
1.135 +
1.136 +
1.137 +FORCE_INLINE TPte Mmu::MakePteAccessible(TPte aPte, TBool aWrite)
1.138 + {
1.139 + if((aPte&KPdePtePresent)==0)
1.140 + {
1.141 + aPte |= KPdePtePresent;
1.142 + aPte &= ~KPdePteWrite;
1.143 + }
1.144 + if(aWrite)
1.145 + aPte |= KPdePteWrite;
1.146 + return aPte;
1.147 + }
1.148 +
1.149 +
1.150 +FORCE_INLINE TBool Mmu::IsPteReadOnly(TPte aPte)
1.151 + {
1.152 + __NK_ASSERT_DEBUG(aPte&KPdePtePresent); // read-only state is ambiguous if pte not present
1.153 + return !(aPte&KPdePteWrite);
1.154 + }
1.155 +
1.156 +
1.157 +FORCE_INLINE TBool Mmu::IsPteInaccessible(TPte aPte)
1.158 + {
1.159 + return !(aPte&KPdePtePresent);
1.160 + }
1.161 +
1.162 +
1.163 +FORCE_INLINE TBool Mmu::IsPteMoreAccessible(TPte aNewPte, TPte aOldPte)
1.164 + {
1.165 + if(aNewPte&aOldPte&KPdePtePresent) // if ptes both present
1.166 + return (aNewPte&~aOldPte)&KPdePteWrite; // check for more writable
1.167 + else // else
1.168 + return aNewPte&KPdePtePresent; // check for new pte being present
1.169 + }
1.170 +
1.171 +
1.172 +enum TPdeType
1.173 + {
1.174 + ENumPdeTypes = 1
1.175 + };
1.176 +
1.177 +
1.178 +enum TPteType
1.179 + {
1.180 + EPteTypeUserAccess = EUser,
1.181 + EPteTypeWritable = EReadWrite,
1.182 + EPteTypeGlobal = 1<<2,
1.183 + ENumPteTypes = 8
1.184 + };
1.185 +
1.186 +__ASSERT_COMPILE(EPteTypeUserAccess==(1<<0));
1.187 +__ASSERT_COMPILE(EPteTypeWritable==(1<<1));
1.188 +
1.189 +
1.190 +FORCE_INLINE TUint Mmu::PdeType(TMemoryAttributes /*aAttributes*/)
1.191 + {
1.192 + return 0;
1.193 + }
1.194 +
1.195 +
1.196 +FORCE_INLINE TUint Mmu::PteType(TMappingPermissions aPermissions, TBool aGlobal)
1.197 + {
1.198 + __NK_ASSERT_DEBUG(aPermissions&EUser || aGlobal); // can't have supervisor local memory
1.199 +
1.200 + TUint pteType = (aPermissions&(EUser|EReadWrite));
1.201 + if(aGlobal)
1.202 + pteType |= EPteTypeGlobal;
1.203 +
1.204 + __NK_ASSERT_DEBUG(pteType<ENumPteTypes);
1.205 +
1.206 + return pteType;
1.207 + }
1.208 +
1.209 +
1.210 +FORCE_INLINE TBool Mmu::CheckPteTypePermissions(TUint aPteType, TUint aAccessPermissions)
1.211 + {
1.212 + aAccessPermissions &= EUser|EReadWrite;
1.213 + return (aPteType&aAccessPermissions)==aAccessPermissions;
1.214 + }
1.215 +
1.216 +
1.217 +FORCE_INLINE TMappingPermissions Mmu::PermissionsFromPteType(TUint aPteType)
1.218 + {
1.219 + return (TMappingPermissions)(aPteType&(EPteTypeUserAccess|EPteTypeWritable));
1.220 + }
1.221 +
1.222 +extern void __fastcall UserWriteFault(TLinAddr aAddr);
1.223 +extern void __fastcall UserReadFault(TLinAddr aAddr);
1.224 +
1.225 +
1.226 +/**
1.227 +Indicate whether a PDE entry maps a page table.
1.228 +
1.229 +@param aPde The PDE entry in question.
1.230 +*/
1.231 +FORCE_INLINE TBool Mmu::PdeMapsPageTable(TPde aPde)
1.232 + {
1.233 + return (aPde & KPdeLargePage) == 0;
1.234 + }
1.235 +
1.236 +
1.237 +/**
1.238 +Indicate whether a PDE entry maps a section.
1.239 +
1.240 +@param aPde The PDE entry in question.
1.241 +*/
1.242 +FORCE_INLINE TBool Mmu::PdeMapsSection(TPde aPde)
1.243 + {
1.244 + return (aPde & KPdeLargePage) != 0;
1.245 + }