ReactOS 0.4.15-dev-7928-g68a8619
special.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for special.c:

Go to the source code of this file.

Classes

struct  _MI_FREED_SPECIAL_POOL
 

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define SPECIAL_POOL_PAGED_PTE   0x2000
 
#define SPECIAL_POOL_NONPAGED_PTE   0x4000
 
#define SPECIAL_POOL_PAGED   0x8000
 

Typedefs

typedef struct _MI_FREED_SPECIAL_POOL MI_FREED_SPECIAL_POOL
 
typedef struct _MI_FREED_SPECIAL_POOLPMI_FREED_SPECIAL_POOL
 

Functions

PMMPTE NTAPI MiReserveAlignedSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
 
VOID NTAPI MiTestSpecialPool (VOID)
 
BOOLEAN NTAPI MmUseSpecialPool (SIZE_T NumberOfBytes, ULONG Tag)
 
BOOLEAN NTAPI MmIsSpecialPoolAddress (PVOID P)
 
BOOLEAN NTAPI MmIsSpecialPoolAddressFree (PVOID P)
 
VOID NTAPI MiInitializeSpecialPool (VOID)
 
NTSTATUS NTAPI MmExpandSpecialPool (VOID)
 
PVOID NTAPI MmAllocateSpecialPool (SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG SpecialType)
 
VOID NTAPI MiSpecialPoolCheckPattern (PUCHAR P, PPOOL_HEADER Header)
 
VOID NTAPI MmFreeSpecialPool (PVOID P)
 

Variables

ULONG ExpPoolFlags
 
PMMPTE MmSystemPteBase
 
PVOID MmSpecialPoolStart
 
PVOID MmSpecialPoolEnd
 
PVOID MiSpecialPoolExtra
 
ULONG MiSpecialPoolExtraCount
 
PMMPTE MiSpecialPoolFirstPte
 
PMMPTE MiSpecialPoolLastPte
 
PFN_COUNT MmSpecialPagesInUse
 
PFN_COUNT MmSpecialPagesInUsePeak
 
PFN_COUNT MiSpecialPagesPagable
 
PFN_COUNT MiSpecialPagesPagablePeak
 
PFN_COUNT MiSpecialPagesNonPaged
 
PFN_COUNT MiSpecialPagesNonPagedPeak
 
PFN_COUNT MiSpecialPagesNonPagedMaximum
 
BOOLEAN MmSpecialPoolCatchOverruns = TRUE
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 20 of file special.c.

◆ NDEBUG

#define NDEBUG

Definition at line 17 of file special.c.

◆ SPECIAL_POOL_NONPAGED_PTE

#define SPECIAL_POOL_NONPAGED_PTE   0x4000

Definition at line 35 of file special.c.

◆ SPECIAL_POOL_PAGED

#define SPECIAL_POOL_PAGED   0x8000

Definition at line 36 of file special.c.

◆ SPECIAL_POOL_PAGED_PTE

#define SPECIAL_POOL_PAGED_PTE   0x2000

Definition at line 34 of file special.c.

Typedef Documentation

◆ MI_FREED_SPECIAL_POOL

◆ PMI_FREED_SPECIAL_POOL

Function Documentation

◆ MiInitializeSpecialPool()

VOID NTAPI MiInitializeSpecialPool ( VOID  )

Definition at line 123 of file special.c.

124{
125 ULONG SpecialPoolPtes, i;
126 PMMPTE PointerPte;
127
128 /* Check if there is a special pool tag */
129 if ((MmSpecialPoolTag == 0) ||
130 (MmSpecialPoolTag == -1)) return;
131
132 /* Calculate number of system PTEs for the special pool */
133 if (MmNumberOfSystemPtes >= 0x3000)
134 SpecialPoolPtes = MmNumberOfSystemPtes / 3;
135 else
136 SpecialPoolPtes = MmNumberOfSystemPtes / 6;
137
138 /* Don't let the number go too high */
139 if (SpecialPoolPtes > 0x6000) SpecialPoolPtes = 0x6000;
140
141 /* Round up to the page size */
142 SpecialPoolPtes = PAGE_ROUND_UP(SpecialPoolPtes);
143
144 ASSERT((SpecialPoolPtes & (PTE_PER_PAGE - 1)) == 0);
145
146 /* Reserve those PTEs */
147 do
148 {
149 PointerPte = MiReserveAlignedSystemPtes(SpecialPoolPtes,
151 /*0x400000*/0); // FIXME:
152 if (PointerPte) break;
153
154 /* Reserving didn't work, so try to reduce the requested size */
155 ASSERT(SpecialPoolPtes >= PTE_PER_PAGE);
156 SpecialPoolPtes -= PTE_PER_PAGE;
157 } while (SpecialPoolPtes);
158
159 /* Fail if we couldn't reserve them at all */
160 if (!SpecialPoolPtes) return;
161
162 /* Make sure we got enough */
163 ASSERT(SpecialPoolPtes >= PTE_PER_PAGE);
164
165 /* Save first PTE and its address */
166 MiSpecialPoolFirstPte = PointerPte;
168
169 for (i = 0; i < PTE_PER_PAGE / 2; i++)
170 {
171 /* Point it to the next entry */
172 PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
173
174 /* Move to the next pair */
175 PointerPte += 2;
176 }
177
178 /* Save extra values */
179 MiSpecialPoolExtra = PointerPte;
180 MiSpecialPoolExtraCount = SpecialPoolPtes - PTE_PER_PAGE;
181
182 /* Mark the previous PTE as the last one */
183 MiSpecialPoolLastPte = PointerPte - 2;
185
186 /* Save end address of the special pool */
188
189 /* Calculate maximum non-paged part of the special pool */
191
192 /* And limit it if it turned out to be too big */
193 if (MmNumberOfPhysicalPages > 0x3FFF)
195
196 DPRINT1("Special pool start %p - end %p\n", MmSpecialPoolStart, MmSpecialPoolEnd);
198
199 //MiTestSpecialPool();
200}
#define DPRINT1
Definition: precomp.h:8
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ SystemPteSpace
Definition: miarm.h:403
ULONG MmSpecialPoolTag
Definition: pool.c:29
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:283
#define ASSERT(a)
Definition: mode.c:44
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define MM_EMPTY_PTE_LIST
Definition: mm.h:87
#define PTE_PER_PAGE
Definition: mm.h:20
#define MiPteToAddress(_Pte)
Definition: mm.h:116
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
ULONG MmNumberOfSystemPtes
Definition: init.c:42
PVOID MmSpecialPoolEnd
Definition: special.c:39
ULONG MiSpecialPoolExtraCount
Definition: special.c:41
PMMPTE MmSystemPteBase
Definition: syspte.c:21
PVOID MmSpecialPoolStart
Definition: special.c:38
PMMPTE MiSpecialPoolLastPte
Definition: special.c:44
PFN_COUNT MiSpecialPagesNonPagedMaximum
Definition: special.c:52
PMMPTE NTAPI MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
Definition: syspte.c:88
PVOID MiSpecialPoolExtra
Definition: special.c:40
ULONG ExpPoolFlags
Definition: expool.c:56
PMMPTE MiSpecialPoolFirstPte
Definition: special.c:43
ULONG64 NextEntry
Definition: mmtypes.h:145
union _MMPTE::@2330 u
MMPTE_LIST List
Definition: mmtypes.h:222
uint32_t ULONG
Definition: typedefs.h:59

Referenced by MiBuildPagedPool().

◆ 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{
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;
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}
DWORD ClusterSize
Definition: format.c:67
#define NULL
Definition: types.h:112
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PAGE_SIZE
Definition: env_spec_w32.h:49
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE VOID KeFlushProcessTb(VOID)
Definition: ke.h:272
ULONG64 OneEntry
Definition: mmtypes.h:139
ULONG_PTR Long
Definition: mmtypes.h:215
PMMPTE MmSystemPteBase
Definition: syspte.c:21
FORCEINLINE ULONG MI_GET_CLUSTER_SIZE(IN PMMPTE Pte)
Definition: syspte.c:71
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ LockQueueSystemSpaceLock
Definition: ketypes.h:661

Referenced by MiInitializeSpecialPool(), and MiReserveSystemPtes().

◆ MiSpecialPoolCheckPattern()

VOID NTAPI MiSpecialPoolCheckPattern ( PUCHAR  P,
PPOOL_HEADER  Header 
)

Definition at line 418 of file special.c.

419{
420 ULONG BytesToCheck, BytesRequested, Index;
421 PUCHAR Ptr;
422
423 /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
424 BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
425 ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
426
427 /* Get a pointer to the end of user's area */
428 Ptr = P + BytesRequested;
429
430 /* Calculate how many bytes to check */
431 BytesToCheck = (ULONG)((PUCHAR)PAGE_ALIGN(P) + PAGE_SIZE - Ptr);
432
433 /* Remove pool header size if we're catching underruns */
434 if (((ULONG_PTR)P & (PAGE_SIZE - 1)) == 0)
435 {
436 /* User buffer is located in the beginning of the page */
437 BytesToCheck -= sizeof(POOL_HEADER);
438 }
439
440 /* Check the pattern after user buffer */
441 for (Index = 0; Index < BytesToCheck; Index++)
442 {
443 /* Bugcheck if bytes don't match */
444 if (Ptr[Index] != Header->BlockSize)
445 {
446 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
447 (ULONG_PTR)P,
449 Header->BlockSize,
450 0x24);
451 }
452 }
453}
Definition: Header.h:9
#define P(row, col)
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
struct _POOL_HEADER POOL_HEADER
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
_In_ WDFCOLLECTION _In_ ULONG Index
#define PAGE_ALIGN(Va)

Referenced by MmFreeSpecialPool().

◆ MiTestSpecialPool()

VOID NTAPI MiTestSpecialPool ( VOID  )

Definition at line 652 of file special.c.

653{
654 ULONG i;
655 PVOID p1, p2[100];
656 //PUCHAR p3;
659
660 // First allocate/free
661 for (i=0; i<100; i++)
662 {
663 ByteSize = (100 * (i+1)) % (PAGE_SIZE - sizeof(POOL_HEADER));
664 p1 = MmAllocateSpecialPool(ByteSize, 'TEST', PoolType, 0);
665 DPRINT1("p1 %p size %lu\n", p1, ByteSize);
667 }
668
669 // Now allocate all at once, then free at once
670 for (i=0; i<100; i++)
671 {
672 ByteSize = (100 * (i+1)) % (PAGE_SIZE - sizeof(POOL_HEADER));
673 p2[i] = MmAllocateSpecialPool(ByteSize, 'TEST', PoolType, 0);
674 DPRINT1("p2[%lu] %p size %lu\n", i, p1, ByteSize);
675 }
676 for (i=0; i<100; i++)
677 {
678 DPRINT1("Freeing %p\n", p2[i]);
679 MmFreeSpecialPool(p2[i]);
680 }
681
682 // Overrun the buffer to test
683 //ByteSize = 16;
684 //p3 = MmAllocateSpecialPool(ByteSize, 'TEST', NonPagedPool, 0);
685 //p3[ByteSize] = 0xF1; // This should cause an exception
686
687 // Underrun the buffer to test
688 //p3 = MmAllocateSpecialPool(ByteSize, 'TEST', NonPagedPool, 1);
689 //p3--;
690 //*p3 = 0xF1; // This should cause an exception
691
692}
#define PagedPool
Definition: env_spec_w32.h:308
PVOID NTAPI MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG SpecialType)
Definition: special.c:245
VOID NTAPI MmFreeSpecialPool(PVOID P)
Definition: special.c:457
INT POOL_TYPE
Definition: typedefs.h:78
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:399

◆ MmAllocateSpecialPool()

PVOID NTAPI MmAllocateSpecialPool ( SIZE_T  NumberOfBytes,
ULONG  Tag,
POOL_TYPE  PoolType,
ULONG  SpecialType 
)

Definition at line 245 of file special.c.

246{
247 KIRQL Irql;
249 PMMPTE PointerPte;
250 PFN_NUMBER PageFrameNumber;
251 LARGE_INTEGER TickCount;
252 PVOID Entry;
254 PFN_COUNT PagesInUse;
255
256 DPRINT("MmAllocateSpecialPool(%x %x %x %x)\n", NumberOfBytes, Tag, PoolType, SpecialType);
257
258 /* Check if the pool is initialized and quit if it's not */
259 if (!MiSpecialPoolFirstPte) return NULL;
260
261 /* Get the pool type */
263
264 /* Check whether current IRQL matches the pool type */
266
267 if (((PoolType == PagedPool) && (Irql > APC_LEVEL)) ||
269 {
270 /* Bad caller */
271 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
272 Irql,
273 PoolType,
275 0x30);
276 }
277
278 /* Some allocations from Mm must never use special pool */
279 if (Tag == 'tSmM')
280 {
281 /* Reject and let normal pool handle it */
282 return NULL;
283 }
284
285 /* TODO: Take into account various limitations */
286
287 /* Heed the maximum limit of nonpaged pages */
288 if ((PoolType == NonPagedPool) &&
290 {
291 return NULL;
292 }
293
294 /* Lock PFN database */
295 Irql = MiAcquirePfnLock();
296
297 /* Reject allocation in case amount of available pages is too small */
298 if (MmAvailablePages < 0x100)
299 {
300 /* Release the PFN database lock */
301 MiReleasePfnLock(Irql);
302 DPRINT1("Special pool: MmAvailablePages 0x%x is too small\n", MmAvailablePages);
303 return NULL;
304 }
305
306 /* Check if special pool PTE list is exhausted */
308 {
309 /* Try to expand it */
311 {
312 /* No reserves left, reject this allocation */
313 static int once;
314 MiReleasePfnLock(Irql);
315 if (!once++) DPRINT1("Special pool: No PTEs left!\n");
316 return NULL;
317 }
319 }
320
321 /* Save allocation time */
322 KeQueryTickCount(&TickCount);
323
324 /* Get a pointer to the first PTE */
325 PointerPte = MiSpecialPoolFirstPte;
326
327 /* Set the first PTE pointer to the next one in the list */
329
330 /* Allocate a physical page */
331 if (PoolType == PagedPool)
332 {
334 }
335 else
336 {
338 }
339 MI_SET_PROCESS2("Kernel-Special");
340 PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
341
342 /* Initialize PFN and make it valid */
343 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
344 MiInitializePfnAndMakePteValid(PageFrameNumber, PointerPte, TempPte);
345
346 /* Release the PFN database lock */
347 MiReleasePfnLock(Irql);
348
349 /* Increase page counter */
351 if (PagesInUse > MmSpecialPagesInUsePeak)
352 MmSpecialPagesInUsePeak = PagesInUse;
353
354 /* Put some content into the page. Low value of tick count would do */
355 Entry = MiPteToAddress(PointerPte);
357
358 /* Calculate header and entry addresses */
359 if ((SpecialType != 0) &&
360 ((SpecialType == 1) || (!MmSpecialPoolCatchOverruns)))
361 {
362 /* We catch underruns. Data is at the beginning of the page */
364 }
365 else
366 {
367 /* We catch overruns. Data is at the end of the page */
370 }
371
372 /* Initialize the header */
374
375 /* Save allocation size there */
376 Header->Ulong1 = (ULONG)NumberOfBytes;
377
378 /* Make sure it's all good */
379 ASSERT((NumberOfBytes <= PAGE_SIZE - sizeof(POOL_HEADER)) &&
380 (PAGE_SIZE <= 32 * 1024));
381
382 /* Mark it as paged or nonpaged */
383 if (PoolType == PagedPool)
384 {
385 /* Add pagedpool flag into the pool header too */
386 Header->Ulong1 |= SPECIAL_POOL_PAGED;
387
388 /* Also mark the next PTE as special-pool-paged */
389 PointerPte[1].u.Soft.PageFileHigh |= SPECIAL_POOL_PAGED_PTE;
390
391 /* Increase pagable counter */
393 if (PagesInUse > MiSpecialPagesPagablePeak)
394 MiSpecialPagesPagablePeak = PagesInUse;
395 }
396 else
397 {
398 /* Mark the next PTE as special-pool-nonpaged */
400
401 /* Increase nonpaged counter */
403 if (PagesInUse > MiSpecialPagesNonPagedPeak)
404 MiSpecialPagesNonPagedPeak = PagesInUse;
405 }
406
407 /* Finally save tag and put allocation time into the header's blocksize.
408 That time will be used to check memory consistency within the allocated
409 page. */
410 Header->PoolTag = Tag;
411 Header->BlockSize = (UCHAR)TickCount.LowPart;
412 DPRINT("%p\n", Entry);
413 return Entry;
414}
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1527
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
struct _POOL_HEADER * PPOOL_HEADER
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:232
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
VOID NTAPI MiInitializePfnAndMakePteValid(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: pfnlist.c:1041
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
@ MI_USAGE_PAGED_POOL
Definition: mm.h:325
@ MI_USAGE_NONPAGED_POOL
Definition: mm.h:326
#define MI_SET_USAGE(x)
Definition: mm.h:317
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
MMPTE ValidKernelPte
Definition: init.c:29
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
ULONG PFN_NUMBER
Definition: ke.h:9
#define DPRINT
Definition: sndvol32.h:71
PFN_COUNT MmSpecialPagesInUse
Definition: special.c:46
PFN_COUNT MiSpecialPagesNonPagedPeak
Definition: special.c:51
#define SPECIAL_POOL_NONPAGED_PTE
Definition: special.c:35
#define SPECIAL_POOL_PAGED_PTE
Definition: special.c:34
PFN_COUNT MiSpecialPagesPagable
Definition: special.c:48
NTSTATUS NTAPI MmExpandSpecialPool(VOID)
Definition: special.c:204
PFN_COUNT MiSpecialPagesNonPaged
Definition: special.c:50
PFN_COUNT MmSpecialPagesInUsePeak
Definition: special.c:47
BOOLEAN MmSpecialPoolCatchOverruns
Definition: special.c:54
#define SPECIAL_POOL_PAGED
Definition: special.c:36
PFN_COUNT MiSpecialPagesPagablePeak
Definition: special.c:49
base of all file and directory entries
Definition: entries.h:83
ULONG PageFrameNumber
Definition: mmtypes.h:109
ULONG64 PageFileHigh
Definition: mmtypes.h:93
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define LONG_PTR
Definition: treelist.c:79
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ULONG LowPart
Definition: typedefs.h:106
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036
ULONG PFN_COUNT
Definition: mmtypes.h:102
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by MiTestSpecialPool().

◆ MmExpandSpecialPool()

NTSTATUS NTAPI MmExpandSpecialPool ( VOID  )

Definition at line 204 of file special.c.

205{
206 ULONG i;
207 PMMPTE PointerPte;
208
210
213
214 PointerPte = MiSpecialPoolExtra;
218
220 for (i = 0; i < PTE_PER_PAGE / 2; i++)
221 {
222 /* Point it to the next entry */
223 PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
224
225 /* Move to the next pair */
226 PointerPte += 2;
227 }
228
229 /* Save remaining extra values */
230 MiSpecialPoolExtra = PointerPte;
232
233 /* Mark the previous PTE as the last one */
234 MiSpecialPoolLastPte = PointerPte - 2;
236
237 /* Save new end address of the special pool */
239
240 return STATUS_SUCCESS;
241}
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by MmAllocateSpecialPool().

◆ MmFreeSpecialPool()

VOID NTAPI MmFreeSpecialPool ( PVOID  P)

Definition at line 457 of file special.c.

458{
459 PMMPTE PointerPte;
461 BOOLEAN Overruns = FALSE;
464 ULONG BytesRequested, BytesReal = 0;
466 PUCHAR b;
467 PMI_FREED_SPECIAL_POOL FreedHeader;
468 LARGE_INTEGER TickCount;
469 PMMPFN Pfn;
470
471 DPRINT("MmFreeSpecialPool(%p)\n", P);
472
473 /* Get the PTE */
474 PointerPte = MiAddressToPte(P);
475
476 /* Check if it's valid */
477 if (PointerPte->u.Hard.Valid == 0)
478 {
479 /* Bugcheck if it has NOACCESS or 0 set as protection */
480 if (PointerPte->u.Soft.Protection == MM_NOACCESS ||
481 !PointerPte->u.Soft.Protection)
482 {
483 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
484 (ULONG_PTR)P,
485 (ULONG_PTR)PointerPte,
486 0,
487 0x20);
488 }
489 }
490
491 /* Determine if it's a underruns or overruns pool pointer */
492 PtrOffset = (ULONG)((ULONG_PTR)P & (PAGE_SIZE - 1));
493 if (PtrOffset)
494 {
495 /* Pool catches overruns */
497 Overruns = TRUE;
498 }
499 else
500 {
501 /* Pool catches underruns */
503 }
504
505 /* Check if it's non paged pool */
506 if ((Header->Ulong1 & SPECIAL_POOL_PAGED) == 0)
507 {
508 /* Non-paged allocation, ensure that IRQ is not higher that DISPATCH */
510 ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_NONPAGED_PTE);
511 if (Irql > DISPATCH_LEVEL)
512 {
513 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
514 Irql,
515 PoolType,
516 (ULONG_PTR)P,
517 0x31);
518 }
519 }
520 else
521 {
522 /* Paged allocation, ensure */
524 ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE);
525 if (Irql > APC_LEVEL)
526 {
527 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
528 Irql,
529 PoolType,
530 (ULONG_PTR)P,
531 0x31);
532 }
533 }
534
535 /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
536 BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
537 ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
538
539 /* Check memory before the allocated user buffer in case of overruns detection */
540 if (Overruns)
541 {
542 /* Calculate the real placement of the buffer */
543 BytesReal = PAGE_SIZE - PtrOffset;
544
545 /* If they mismatch, it's unrecoverable */
546 if (BytesRequested > BytesReal)
547 {
548 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
549 (ULONG_PTR)P,
550 BytesRequested,
551 BytesReal,
552 0x21);
553 }
554
555 if (BytesRequested + sizeof(POOL_HEADER) < BytesReal)
556 {
557 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
558 (ULONG_PTR)P,
559 BytesRequested,
560 BytesReal,
561 0x22);
562 }
563
564 /* Actually check the memory pattern */
565 for (b = (PUCHAR)(Header + 1); b < (PUCHAR)P; b++)
566 {
567 if (*b != Header->BlockSize)
568 {
569 /* Bytes mismatch */
570 KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
571 (ULONG_PTR)P,
572 (ULONG_PTR)b,
573 Header->BlockSize,
574 0x23);
575 }
576 }
577 }
578
579 /* Check the memory pattern after the user buffer */
581
582 /* Fill the freed header */
583 KeQueryTickCount(&TickCount);
584 FreedHeader = (PMI_FREED_SPECIAL_POOL)PAGE_ALIGN(P);
585 FreedHeader->Signature = 0x98764321;
586 FreedHeader->TickCount = TickCount.LowPart;
587 FreedHeader->NumberOfBytesRequested = BytesRequested;
588 FreedHeader->Pagable = PoolType;
589 FreedHeader->VirtualAddress = P;
590 FreedHeader->Thread = PsGetCurrentThread();
591 /* TODO: Fill StackPointer and StackBytes */
592 FreedHeader->StackPointer = NULL;
593 FreedHeader->StackBytes = 0;
594
595 if (PoolType == NonPagedPool)
596 {
597 /* Non pagable. Get PFN element corresponding to the PTE */
598 Pfn = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
599
600 /* Count the page as free */
602
603 /* Lock PFN database */
604 Irql = MiAcquirePfnLock();
605
606 /* Delete this PFN */
608
609 /* Decrement share count of this PFN */
611
612 MI_ERASE_PTE(PointerPte);
613
614 /* Flush the TLB */
615 //FIXME: Use KeFlushSingleTb() instead
617 }
618 else
619 {
620 /* Pagable. Delete that virtual address */
621 MiDeleteSystemPageableVm(PointerPte, 1, 0, NULL);
622
623 /* Count the page as free */
625
626 /* Lock PFN database */
627 Irql = MiAcquirePfnLock();
628 }
629
630 /* Mark next PTE as invalid */
631 MI_ERASE_PTE(PointerPte + 1);
632
633 /* Make sure that the last entry is really the last one */
635
636 /* Update the current last PTE next pointer */
638
639 /* PointerPte becomes the new last PTE */
640 PointerPte->u.List.NextEntry = MM_EMPTY_PTE_LIST;
641 MiSpecialPoolLastPte = PointerPte;
642
643 /* Release the PFN database lock */
644 MiReleasePfnLock(Irql);
645
646 /* Update page counter */
648}
unsigned char BOOLEAN
#define PtrOffset(BASE, OFFSET)
Definition: cdprocs.h:1547
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1524
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define b
Definition: ke_i.h:79
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1006
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1141
#define MM_NOACCESS
Definition: miarm.h:65
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:275
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1574
#define MiAddressToPte(x)
Definition: mmx86.c:19
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:617
VOID NTAPI MiSpecialPoolCheckPattern(PUCHAR P, PPOOL_HEADER Header)
Definition: special.c:418
struct _MI_FREED_SPECIAL_POOL * PMI_FREED_SPECIAL_POOL
ULONG NumberOfBytesRequested
Definition: special.c:62
Definition: mm.h:374
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG64 Protection
Definition: mmtypes.h:88
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217

Referenced by MiTestSpecialPool().

◆ MmIsSpecialPoolAddress()

BOOLEAN NTAPI MmIsSpecialPoolAddress ( PVOID  P)

Definition at line 95 of file special.c.

96{
97 return ((P >= MmSpecialPoolStart) &&
98 (P <= MmSpecialPoolEnd));
99}

Referenced by MmIsSpecialPoolAddressFree().

◆ MmIsSpecialPoolAddressFree()

BOOLEAN NTAPI MmIsSpecialPoolAddressFree ( PVOID  P)

Definition at line 103 of file special.c.

104{
105 PMMPTE PointerPte;
106
108 PointerPte = MiAddressToPte(P);
109
110 if (PointerPte->u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE ||
112 {
113 /* Guard page PTE */
114 return FALSE;
115 }
116
117 /* Free PTE */
118 return TRUE;
119}
BOOLEAN NTAPI MmIsSpecialPoolAddress(PVOID P)
Definition: special.c:95

◆ MmUseSpecialPool()

BOOLEAN NTAPI MmUseSpecialPool ( SIZE_T  NumberOfBytes,
ULONG  Tag 
)

Definition at line 77 of file special.c.

78{
79 /* Special pool is not suitable for allocations bigger than 1 page */
80 if (NumberOfBytes > (PAGE_SIZE - sizeof(POOL_HEADER)))
81 {
82 return FALSE;
83 }
84
85 if (MmSpecialPoolTag == '*')
86 {
87 return TRUE;
88 }
89
90 return Tag == MmSpecialPoolTag;
91}

Variable Documentation

◆ ExpPoolFlags

◆ MiSpecialPagesNonPaged

PFN_COUNT MiSpecialPagesNonPaged

Definition at line 50 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

◆ MiSpecialPagesNonPagedMaximum

PFN_COUNT MiSpecialPagesNonPagedMaximum

Definition at line 52 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmAllocateSpecialPool().

◆ MiSpecialPagesNonPagedPeak

PFN_COUNT MiSpecialPagesNonPagedPeak

Definition at line 51 of file special.c.

Referenced by MmAllocateSpecialPool().

◆ MiSpecialPagesPagable

PFN_COUNT MiSpecialPagesPagable

Definition at line 48 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

◆ MiSpecialPagesPagablePeak

PFN_COUNT MiSpecialPagesPagablePeak

Definition at line 49 of file special.c.

Referenced by MmAllocateSpecialPool().

◆ MiSpecialPoolExtra

PVOID MiSpecialPoolExtra

Definition at line 40 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmExpandSpecialPool().

◆ MiSpecialPoolExtraCount

ULONG MiSpecialPoolExtraCount

Definition at line 41 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmExpandSpecialPool().

◆ MiSpecialPoolFirstPte

PMMPTE MiSpecialPoolFirstPte

Definition at line 43 of file special.c.

Referenced by MiInitializeSpecialPool(), MmAllocateSpecialPool(), and MmExpandSpecialPool().

◆ MiSpecialPoolLastPte

PMMPTE MiSpecialPoolLastPte

Definition at line 44 of file special.c.

Referenced by MiInitializeSpecialPool(), MmExpandSpecialPool(), and MmFreeSpecialPool().

◆ MmSpecialPagesInUse

PFN_COUNT MmSpecialPagesInUse

Definition at line 46 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

◆ MmSpecialPagesInUsePeak

PFN_COUNT MmSpecialPagesInUsePeak

Definition at line 47 of file special.c.

Referenced by MmAllocateSpecialPool().

◆ MmSpecialPoolCatchOverruns

BOOLEAN MmSpecialPoolCatchOverruns = TRUE

Definition at line 54 of file special.c.

Referenced by MmAllocateSpecialPool().

◆ MmSpecialPoolEnd

PVOID MmSpecialPoolEnd

Definition at line 39 of file special.c.

Referenced by MiInitializeSpecialPool(), MmExpandSpecialPool(), and MmIsSpecialPoolAddress().

◆ MmSpecialPoolStart

PVOID MmSpecialPoolStart

Definition at line 38 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmIsSpecialPoolAddress().

◆ MmSystemPteBase