ReactOS  0.4.14-dev-317-g96040ec
syspte.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for syspte.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

FORCEINLINE ULONG MI_GET_CLUSTER_SIZE (IN PMMPTE Pte)
 
PMMPTE NTAPI MiReserveAlignedSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
 
PMMPTE NTAPI MiReserveSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
 
VOID NTAPI MiReleaseSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
 
INIT_FUNCTION VOID NTAPI MiInitializeSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
 

Variables

PMMPTE MmSystemPteBase
 
PMMPTE MmSystemPtesStart [MaximumPtePoolTypes]
 
PMMPTE MmSystemPtesEnd [MaximumPtePoolTypes]
 
MMPTE MmFirstFreeSystemPte [MaximumPtePoolTypes]
 
ULONG MmTotalFreeSystemPtes [MaximumPtePoolTypes]
 
ULONG MmTotalSystemPtes
 
ULONG MiNumberOfExtraSystemPdes
 
const ULONG MmSysPteIndex [5] = { 1, 2, 4, 8, 16 }
 
const UCHAR MmSysPteTables []
 
LONG MmSysPteListBySizeCount [5]
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 16 of file syspte.c.

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file syspte.c.

Function Documentation

◆ MI_GET_CLUSTER_SIZE()

FORCEINLINE ULONG MI_GET_CLUSTER_SIZE ( IN PMMPTE  Pte)

Definition at line 71 of file syspte.c.

72 {
73  //
74  // First check for a single PTE
75  //
76  if (Pte->u.List.OneEntry)
77  return 1;
78 
79  //
80  // Then read the size from the trailing PTE
81  //
82  Pte++;
83  return (ULONG)Pte->u.List.NextEntry;
84 }
unsigned int ULONG
Definition: retypes.h:1

Referenced by MiReleaseSystemPtes(), and MiReserveAlignedSystemPtes().

◆ MiInitializeSystemPtes()

INIT_FUNCTION VOID NTAPI MiInitializeSystemPtes ( IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  PoolType 
)

Definition at line 399 of file syspte.c.

402 {
403  //
404  // Sanity checks
405  //
406  ASSERT(NumberOfPtes >= 1);
407 
408  //
409  // Set the starting and ending PTE addresses for this space
410  //
412  MmSystemPtesStart[PoolType] = StartingPte;
413  MmSystemPtesEnd[PoolType] = StartingPte + NumberOfPtes - 1;
414  DPRINT("System PTE space for %d starting at: %p and ending at: %p\n",
416 
417  //
418  // Clear all the PTEs to start with
419  //
420  RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
421 
422  //
423  // Make the first entry free and link it
424  //
425  StartingPte->u.List.NextEntry = MM_EMPTY_PTE_LIST;
427  MmFirstFreeSystemPte[PoolType].u.List.NextEntry = StartingPte -
429 
430  //
431  // The second entry stores the size of this PTE space
432  //
433  StartingPte++;
434  StartingPte->u.Long = 0;
435  StartingPte->u.List.NextEntry = NumberOfPtes;
436 
437  //
438  // We also keep a global for it
439  //
440  MmTotalFreeSystemPtes[PoolType] = NumberOfPtes;
441 
442  //
443  // Check if this is the system PTE space
444  //
445  if (PoolType == SystemPteSpace)
446  {
447  //
448  // Remember how many PTEs we have
449  //
450  MmTotalSystemPtes = NumberOfPtes;
451  }
452 }
ULONG64 NextEntry
Definition: mmtypes.h:145
#define MM_EMPTY_PTE_LIST
Definition: mm.h:84
PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
Definition: syspte.c:22
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
void DPRINT(...)
Definition: polytest.cpp:61
ULONG MmTotalSystemPtes
Definition: syspte.c:26
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
MMPTE_LIST List
Definition: mmtypes.h:222
PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
Definition: syspte.c:23
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define MI_SYSTEM_PTE_BASE
Definition: mm.h:42
PMMPTE MmSystemPteBase
Definition: syspte.c:21
ULONG_PTR Long
Definition: mmtypes.h:215
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T _In_ POOL_TYPE PoolType
Definition: fltkernel.h:1444
union _MMPTE::@2256 u

Referenced by MiBuildSystemPteSpace(), MiInitializeNonPagedPool(), and MiInitMachineDependent().

◆ MiReleaseSystemPtes()

VOID NTAPI MiReleaseSystemPtes ( IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType 
)

Definition at line 275 of file syspte.c.

278 {
279  KIRQL OldIrql;
281  PMMPTE PreviousPte, NextPte, InsertPte;
282 
283  //
284  // Check to make sure the PTE address is within bounds
285  //
286  ASSERT(NumberOfPtes != 0);
287  ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]);
288  ASSERT(StartingPte + NumberOfPtes - 1 <= MmSystemPtesEnd[SystemPtePoolType]);
289 
290  //
291  // Zero PTEs
292  //
293  RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
294 
295  //
296  // Acquire the System PTE lock
297  //
299 
300  //
301  // Increase availability
302  //
303  MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes;
304 
305  //
306  // Step through the cluster list to find where to insert the PTEs
307  //
308  PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
309  InsertPte = NULL;
310 
311  while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
312  {
313  //
314  // Get the next cluster and its size
315  //
316  NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
317  ClusterSize = MI_GET_CLUSTER_SIZE(NextPte);
318 
319  //
320  // Check if this cluster is adjacent to the PTEs being released
321  //
322  if ((NextPte + ClusterSize == StartingPte) ||
323  (StartingPte + NumberOfPtes == NextPte))
324  {
325  //
326  // Add the PTEs in the cluster to the PTEs being released
327  //
328  NumberOfPtes += ClusterSize;
329 
330  if (NextPte < StartingPte)
331  StartingPte = NextPte;
332 
333  //
334  // Unlink this cluster and zero it
335  //
336  PreviousPte->u.List.NextEntry = NextPte->u.List.NextEntry;
337 
338  if (NextPte->u.List.OneEntry == 0)
339  {
340  NextPte->u.Long = 0;
341  NextPte++;
342  }
343  NextPte->u.Long = 0;
344 
345  //
346  // Invalidate the previously found insertion location, if any
347  //
348  InsertPte = NULL;
349  }
350  else
351  {
352  //
353  // Check if the insertion location is right before this cluster
354  //
355  if ((InsertPte == NULL) && (NumberOfPtes <= ClusterSize))
356  InsertPte = PreviousPte;
357 
358  //
359  // On to the next cluster
360  //
361  PreviousPte = NextPte;
362  }
363  }
364 
365  //
366  // If no insertion location was found, use the tail of the list
367  //
368  if (InsertPte == NULL)
369  InsertPte = PreviousPte;
370 
371  //
372  // Create a new cluster using the PTEs being released
373  //
374  if (NumberOfPtes != 1)
375  {
376  StartingPte->u.List.OneEntry = 0;
377 
378  NextPte = StartingPte + 1;
379  NextPte->u.List.NextEntry = NumberOfPtes;
380  }
381  else
382  StartingPte->u.List.OneEntry = 1;
383 
384  //
385  // Link the new cluster into the cluster list at the insertion location
386  //
387  StartingPte->u.List.NextEntry = InsertPte->u.List.NextEntry;
388  InsertPte->u.List.NextEntry = StartingPte - MmSystemPteBase;
389 
390  //
391  // Release the System PTE lock
392  //
394 }
ULONG64 NextEntry
Definition: mmtypes.h:145
#define MM_EMPTY_PTE_LIST
Definition: mm.h:84
ULONG64 OneEntry
Definition: mmtypes.h:139
PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
Definition: syspte.c:22
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
smooth NULL
Definition: ftsmooth.c:416
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
MMPTE_LIST List
Definition: mmtypes.h:222
DWORD ClusterSize
Definition: format.c:67
FORCEINLINE ULONG MI_GET_CLUSTER_SIZE(IN PMMPTE Pte)
Definition: syspte.c:71
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
Definition: syspte.c:23
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PMMPTE MmSystemPteBase
Definition: syspte.c:21
ULONG_PTR Long
Definition: mmtypes.h:215
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
union _MMPTE::@2256 u

Referenced by MiCopyPfn(), MiReleaseProcessReferenceToSessionDataPage(), MiZeroPfn(), MmCreateProcessAddressSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace2(), MmFreeNonCachedMemory(), MmUnmapIoSpace(), and MmUnmapLockedPages().

◆ MiReserveAlignedSystemPtes()

PMMPTE NTAPI MiReserveAlignedSystemPtes ( IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType,
IN ULONG  Alignment 
)

Definition at line 88 of file syspte.c.

91 {
92  KIRQL OldIrql;
93  PMMPTE PreviousPte, NextPte, ReturnPte;
95 
96  //
97  // Sanity check
98  //
100 
101  //
102  // Acquire the System PTE lock
103  //
105 
106  //
107  // Find the last cluster in the list that doesn't contain enough PTEs
108  //
109  PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
110 
111  while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
112  {
113  //
114  // Get the next cluster and its size
115  //
116  NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
117  ClusterSize = MI_GET_CLUSTER_SIZE(NextPte);
118 
119  //
120  // Check if this cluster contains enough PTEs
121  //
122  if (NumberOfPtes <= ClusterSize)
123  break;
124 
125  //
126  // On to the next cluster
127  //
128  PreviousPte = NextPte;
129  }
130 
131  //
132  // Make sure we didn't reach the end of the cluster list
133  //
134  if (PreviousPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)
135  {
136  //
137  // Release the System PTE lock and return failure
138  //
140  return NULL;
141  }
142 
143  //
144  // Unlink the cluster
145  //
146  PreviousPte->u.List.NextEntry = NextPte->u.List.NextEntry;
147 
148  //
149  // Check if the reservation spans the whole cluster
150  //
151  if (ClusterSize == NumberOfPtes)
152  {
153  //
154  // Return the first PTE of this cluster
155  //
156  ReturnPte = NextPte;
157 
158  //
159  // Zero the cluster
160  //
161  if (NextPte->u.List.OneEntry == 0)
162  {
163  NextPte->u.Long = 0;
164  NextPte++;
165  }
166  NextPte->u.Long = 0;
167  }
168  else
169  {
170  //
171  // Divide the cluster into two parts
172  //
173  ClusterSize -= NumberOfPtes;
174  ReturnPte = NextPte + ClusterSize;
175 
176  //
177  // Set the size of the first cluster, zero the second if needed
178  //
179  if (ClusterSize == 1)
180  {
181  NextPte->u.List.OneEntry = 1;
182  ReturnPte->u.Long = 0;
183  }
184  else
185  {
186  NextPte++;
187  NextPte->u.List.NextEntry = ClusterSize;
188  }
189 
190  //
191  // Step through the cluster list to find out where to insert the first
192  //
193  PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
194 
195  while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
196  {
197  //
198  // Get the next cluster
199  //
200  NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
201 
202  //
203  // Check if the cluster to insert is smaller or of equal size
204  //
205  if (ClusterSize <= MI_GET_CLUSTER_SIZE(NextPte))
206  break;
207 
208  //
209  // On to the next cluster
210  //
211  PreviousPte = NextPte;
212  }
213 
214  //
215  // Retrieve the first cluster and link it back into the cluster list
216  //
217  NextPte = ReturnPte - ClusterSize;
218 
219  NextPte->u.List.NextEntry = PreviousPte->u.List.NextEntry;
220  PreviousPte->u.List.NextEntry = NextPte - MmSystemPteBase;
221  }
222 
223  //
224  // Decrease availability
225  //
226  MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;
227 
228  //
229  // Release the System PTE lock
230  //
232 
233  //
234  // Flush the TLB
235  //
237 
238  //
239  // Return the reserved PTEs
240  //
241  return ReturnPte;
242 }
ULONG64 NextEntry
Definition: mmtypes.h:145
#define MM_EMPTY_PTE_LIST
Definition: mm.h:84
ULONG64 OneEntry
Definition: mmtypes.h:139
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
smooth NULL
Definition: ftsmooth.c:416
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
MMPTE_LIST List
Definition: mmtypes.h:222
DWORD ClusterSize
Definition: format.c:67
FORCEINLINE ULONG MI_GET_CLUSTER_SIZE(IN PMMPTE Pte)
Definition: syspte.c:71
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PMMPTE MmSystemPteBase
Definition: syspte.c:21
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID KeFlushProcessTb(VOID)
Definition: ke.h:209
unsigned int ULONG
Definition: retypes.h:1
union _MMPTE::@2256 u

Referenced by MiInitializeSpecialPool(), and MiReserveSystemPtes().

◆ MiReserveSystemPtes()

PMMPTE NTAPI MiReserveSystemPtes ( IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType 
)

Definition at line 246 of file syspte.c.

248 {
249  PMMPTE PointerPte;
250 
251  //
252  // Use the extended function
253  //
254  PointerPte = MiReserveAlignedSystemPtes(NumberOfPtes, SystemPtePoolType, 0);
255 
256  //
257  // Check if allocation failed
258  //
259  if (!PointerPte)
260  {
261  //
262  // Warn that we are out of memory
263  //
264  DPRINT1("MiReserveSystemPtes: Failed to reserve %lu PTE(s)!\n", NumberOfPtes);
265  }
266 
267  //
268  // Return the PTE Pointer
269  //
270  return PointerPte;
271 }
#define DPRINT1
Definition: precomp.h:8
PMMPTE NTAPI MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
Definition: syspte.c:88

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiBuildSystemPteSpace(), MiCopyPfn(), MiInitializeLargePageSupport(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiLoadImageSection(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MiZeroPfn(), MmAllocateNonCachedMemory(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmMapIoSpace(), and MmMapLockedPagesSpecifyCache().

Variable Documentation

◆ MiNumberOfExtraSystemPdes

ULONG MiNumberOfExtraSystemPdes

Definition at line 27 of file syspte.c.

◆ MmFirstFreeSystemPte

MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]

◆ MmSysPteIndex

const ULONG MmSysPteIndex[5] = { 1, 2, 4, 8, 16 }

Definition at line 28 of file syspte.c.

◆ MmSysPteListBySizeCount

LONG MmSysPteListBySizeCount[5]

Definition at line 36 of file syspte.c.

◆ MmSysPteTables

const UCHAR MmSysPteTables[]
Initial value:
= { 0,
0,
1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4
}

Definition at line 29 of file syspte.c.

◆ MmSystemPteBase

◆ MmSystemPtesEnd

PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]

Definition at line 23 of file syspte.c.

Referenced by MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MmUnmapLockedPages().

◆ MmSystemPtesStart

PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]

Definition at line 22 of file syspte.c.

Referenced by MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MmUnmapLockedPages().

◆ MmTotalFreeSystemPtes

◆ MmTotalSystemPtes

ULONG MmTotalSystemPtes

Definition at line 26 of file syspte.c.

Referenced by MiInitializeSystemPtes().