os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.h
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // This will make sure that the changes in page tables are visible by H/W Page-Table Walk.  
    15 // Call this function when two and more consecutive entries in page table are changed.
    16 // 
    17 //
    18 
    19 /**
    20 FORCE_INLINE macro in GCC works differently from in VC and armcc.
    21 */
    22 #ifdef _MSC_VER
    23 #define REALLY_INLINE __forceinline
    24 #else
    25 #ifdef __GNUC__
    26 #if __GNUC__ < 3
    27 #define REALLY_INLINE inline
    28 #else
    29 #define REALLY_INLINE inline __attribute__ ((always_inline))
    30 #endif
    31 #else
    32 #define REALLY_INLINE inline
    33 #endif
    34 #endif
    35 
    36 /**	
    37 This will make sure that the change in page directory is visible by H/W Page-Table Walk.  
    38 Call this function when a single entry in page directory is changed.
    39 */
    40 extern void SinglePdeUpdated(TPde* aPde);
    41 
    42 
    43 extern void __fastcall DoInvalidateTLBForPage(TLinAddr aLinAddrAndAsid);
    44 extern void DoInvalidateTLB();
    45 
    46 
    47 /**
    48 Invalidate a single I+D TLB entry on this CPU core only.
    49 @param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
    50 */
    51 REALLY_INLINE void __fastcall LocalInvalidateTLBForPage(TLinAddr aLinAddrAndAsid)
    52 	{
    53 	DoInvalidateTLBForPage(aLinAddrAndAsid);
    54 	}
    55 
    56 
    57 #ifndef __SMP__
    58 
    59 /**
    60 Invalidate a single I+D TLB entry
    61 @param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
    62 */
    63 REALLY_INLINE void __fastcall InvalidateTLBForPage(TLinAddr aLinAddrAndAsid)
    64 	{
    65 	DoInvalidateTLBForPage(aLinAddrAndAsid);
    66 	}
    67 
    68 
    69 /**
    70 Invalidate entire TLB
    71 */
    72 REALLY_INLINE void InvalidateTLB()
    73 	{
    74 	DoInvalidateTLB();
    75 	}
    76 
    77 
    78 #else // __SMP__
    79 
    80 
    81 #define COARSE_GRAINED_TLB_MAINTENANCE
    82 
    83 /**
    84 Invalidate a single I+D TLB entry.
    85 @param aLinAddrAndAsid Virtual address of a page of memory ORed with the ASID value.
    86 */
    87 extern void InvalidateTLBForPage(TLinAddr aLinAddrAndAsid);
    88 
    89 
    90 /**
    91 Invalidate entire TLB
    92 */
    93 extern void InvalidateTLB();
    94 
    95 
    96 #endif // __SMP__
    97 
    98 
    99 /**
   100 Invalidate all TLB entries which match the given ASID value
   101 */
   102 extern void InvalidateTLBForAsid(TUint aAsid);
   103 
   104 
   105 FORCE_INLINE TPde* Mmu::PageDirectory(TInt aOsAsid)
   106 	{
   107 	return (TPde*)(KPageDirectoryBase+(aOsAsid<<KPageDirectoryShift));
   108 	}
   109 
   110 
   111 FORCE_INLINE TPde* Mmu::PageDirectoryEntry(TInt aOsAsid, TLinAddr aAddress)
   112 	{
   113 	return PageDirectory(aOsAsid) + (aAddress>>KChunkShift);
   114 	}
   115 
   116 
   117 FORCE_INLINE TPhysAddr Mmu::PdePhysAddr(TPde aPde)
   118 	{
   119 	if ((aPde&(KPdePtePresent|KPdeLargePage)) == (KPdePtePresent|KPdeLargePage))
   120 		return aPde & KPdeLargePagePhysAddrMask;
   121 	return KPhysAddrInvalid;
   122 	}
   123 
   124 
   125 FORCE_INLINE TPte Mmu::MakePteInaccessible(TPte aPte, TBool aReadOnly)
   126 	{
   127 	if(aReadOnly)
   128 		return aPte&~KPdePteWrite;
   129 	else
   130 		return aPte&~KPdePtePresent;
   131 	}
   132 
   133 
   134 FORCE_INLINE TPte Mmu::MakePteAccessible(TPte aPte, TBool aWrite)
   135 	{
   136 	if((aPte&KPdePtePresent)==0)
   137 		{
   138 		aPte |= KPdePtePresent;
   139 		aPte &= ~KPdePteWrite;
   140 		}
   141 	if(aWrite)
   142 		aPte |= KPdePteWrite;
   143 	return aPte;
   144 	}
   145 
   146 
   147 FORCE_INLINE TBool Mmu::IsPteReadOnly(TPte aPte)
   148 	{
   149 	__NK_ASSERT_DEBUG(aPte&KPdePtePresent); // read-only state is ambiguous if pte not present
   150 	return !(aPte&KPdePteWrite);
   151 	}
   152 
   153 
   154 FORCE_INLINE TBool Mmu::IsPteInaccessible(TPte aPte)
   155 	{
   156 	return !(aPte&KPdePtePresent);
   157 	}
   158 
   159 
   160 FORCE_INLINE TBool Mmu::IsPteMoreAccessible(TPte aNewPte, TPte aOldPte)
   161 	{
   162 	if(aNewPte&aOldPte&KPdePtePresent)			// if ptes both present
   163 		return (aNewPte&~aOldPte)&KPdePteWrite;	//   check for more writable
   164 	else										// else
   165 		return aNewPte&KPdePtePresent;			//   check for new pte being present
   166 	}
   167 
   168 
   169 enum TPdeType
   170 	{
   171 	ENumPdeTypes			= 1
   172 	};
   173 
   174 
   175 enum TPteType
   176 	{
   177 	EPteTypeUserAccess		= EUser,
   178 	EPteTypeWritable		= EReadWrite,
   179 	EPteTypeGlobal			= 1<<2,
   180 	ENumPteTypes			= 8
   181 	};
   182 
   183 __ASSERT_COMPILE(EPteTypeUserAccess==(1<<0));
   184 __ASSERT_COMPILE(EPteTypeWritable==(1<<1));
   185 
   186 
   187 FORCE_INLINE TUint Mmu::PdeType(TMemoryAttributes /*aAttributes*/)
   188 	{
   189 	return 0;
   190 	}
   191 
   192 
   193 FORCE_INLINE TUint Mmu::PteType(TMappingPermissions aPermissions, TBool aGlobal)
   194 	{
   195 	__NK_ASSERT_DEBUG(aPermissions&EUser || aGlobal); // can't have supervisor local memory
   196 
   197 	TUint pteType =	(aPermissions&(EUser|EReadWrite));
   198 	if(aGlobal)
   199 		pteType |= EPteTypeGlobal;
   200 
   201 	__NK_ASSERT_DEBUG(pteType<ENumPteTypes);
   202 
   203 	return pteType;
   204 	}
   205 
   206 
   207 FORCE_INLINE TBool Mmu::CheckPteTypePermissions(TUint aPteType, TUint aAccessPermissions)
   208 	{
   209 	aAccessPermissions &= EUser|EReadWrite;
   210 	return (aPteType&aAccessPermissions)==aAccessPermissions;
   211 	}
   212 
   213 
   214 FORCE_INLINE TMappingPermissions Mmu::PermissionsFromPteType(TUint aPteType)
   215 	{
   216 	return (TMappingPermissions)(aPteType&(EPteTypeUserAccess|EPteTypeWritable));
   217 	}
   218 
   219 extern void __fastcall UserWriteFault(TLinAddr aAddr);
   220 extern void __fastcall UserReadFault(TLinAddr aAddr);
   221 
   222 
   223 /**
   224 Indicate whether a PDE entry maps a page table.
   225 
   226 @param aPde The PDE entry in question.
   227 */
   228 FORCE_INLINE TBool Mmu::PdeMapsPageTable(TPde aPde)
   229 	{
   230 	return (aPde & KPdeLargePage) == 0;
   231 	}
   232 
   233 
   234 /**
   235 Indicate whether a PDE entry maps a section.
   236 
   237 @param aPde The PDE entry in question.
   238 */
   239 FORCE_INLINE TBool Mmu::PdeMapsSection(TPde aPde)
   240 	{
   241 	return (aPde & KPdeLargePage) != 0;
   242 	}