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