ReactOS 0.4.17-dev-1196-gb6224c3
mdlsup.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for mdlsup.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

static PVOID NTAPI MiMapLockedPagesInUserSpace (_In_ PMDL Mdl, _In_ PVOID StartVa, _In_ MEMORY_CACHING_TYPE CacheType, _In_opt_ PVOID BaseAddress)
 
static VOID NTAPI MiUnmapLockedPagesInUserSpace (_In_ PVOID BaseAddress, _In_ PMDL Mdl)
 
PMDL NTAPI MmCreateMdl (IN PMDL Mdl, IN PVOID Base, IN SIZE_T Length)
 
SIZE_T NTAPI MmSizeOfMdl (IN PVOID Base, IN SIZE_T Length)
 
VOID NTAPI MmBuildMdlForNonPagedPool (IN PMDL Mdl)
 
PMDL NTAPI MmAllocatePagesForMdl (IN PHYSICAL_ADDRESS LowAddress, IN PHYSICAL_ADDRESS HighAddress, IN PHYSICAL_ADDRESS SkipBytes, IN SIZE_T TotalBytes)
 
PMDL NTAPI MmAllocatePagesForMdlEx (IN PHYSICAL_ADDRESS LowAddress, IN PHYSICAL_ADDRESS HighAddress, IN PHYSICAL_ADDRESS SkipBytes, IN SIZE_T TotalBytes, IN MEMORY_CACHING_TYPE CacheType, IN ULONG Flags)
 
VOID NTAPI MmFreePagesFromMdl (IN PMDL Mdl)
 
PVOID NTAPI MmMapLockedPagesSpecifyCache (IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress, IN ULONG BugCheckOnFailure, IN ULONG Priority)
 
PVOID NTAPI MmMapLockedPages (IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode)
 
VOID NTAPI MmUnmapLockedPages (IN PVOID BaseAddress, IN PMDL Mdl)
 
VOID NTAPI MmProbeAndLockPages (IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
 
VOID NTAPI MmUnlockPages (IN PMDL Mdl)
 
NTSTATUS NTAPI MmAdvanceMdl (IN PMDL Mdl, IN ULONG NumberOfBytes)
 
PVOID NTAPI MmMapLockedPagesWithReservedMapping (_In_ PVOID MappingAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl, _In_ MEMORY_CACHING_TYPE CacheType)
 
VOID NTAPI MmUnmapReservedMapping (_In_ PVOID BaseAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl)
 
NTSTATUS NTAPI MmPrefetchPages (IN ULONG NumberOfLists, IN PREAD_LIST *ReadLists)
 
NTSTATUS NTAPI MmProtectMdlSystemAddress (IN PMDL MemoryDescriptorList, IN ULONG NewProtect)
 
 _IRQL_requires_max_ (APC_LEVEL)
 Probes and locks virtual pages in memory for the specified process.
 
VOID NTAPI MmProbeAndLockSelectedPages (IN OUT PMDL MemoryDescriptorList, IN LARGE_INTEGER PageList[], IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
 
VOID NTAPI MmMapMemoryDumpMdl (IN PMDL Mdl)
 

Variables

BOOLEAN MmTrackPtes
 
BOOLEAN MmTrackLockedPages
 
SIZE_T MmSystemLockPagesCount
 
ULONG MiCacheOverride [MiNotMapped+1]
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file mdlsup.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file mdlsup.c.

Function Documentation

◆ _IRQL_requires_max_()

_IRQL_requires_max_ ( APC_LEVEL  )

Probes and locks virtual pages in memory for the specified process.

Parameters
[in,out]MemoryDescriptorListMemory Descriptor List (MDL) containing the buffer to be probed and locked.
[in]ProcessThe process for which the buffer should be probed and locked.
[in]AccessModeAccess mode for probing the pages. Can be KernelMode or UserMode.
[in]LockOperationThe type of the probing and locking operation. Can be IoReadAccess, IoWriteAccess or IoModifyAccess.
Returns
Nothing.
See also
MmProbeAndLockPages
Remarks
Must be called at IRQL <= APC_LEVEL

Definition at line 1887 of file mdlsup.c.

1895{
1897 BOOLEAN IsAttached = FALSE;
1898
1900 {
1902 IsAttached = TRUE;
1903 }
1904
1905 /* Protect in try/finally to ensure we detach even if MmProbeAndLockPages() throws an exception */
1906 _SEH2_TRY
1907 {
1909 }
1911 {
1912 if (IsAttached)
1914 }
1915 _SEH2_END;
1916}
unsigned char BOOLEAN
Definition: actypes.h:127
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
FP_OP Operation
Definition: fpcontrol.c:150
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:928
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1751
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define _SEH2_FINALLY
Definition: pseh2_64.h:153
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
KAPC_STATE
Definition: ketypes.h:1727
_Inout_ PMDL MemoryDescriptorList
Definition: mmfuncs.h:405
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
#define PsGetCurrentProcess
Definition: psfuncs.h:17

◆ MiMapLockedPagesInUserSpace()

static PVOID NTAPI MiMapLockedPagesInUserSpace ( _In_ PMDL  Mdl,
_In_ PVOID  StartVa,
_In_ MEMORY_CACHING_TYPE  CacheType,
_In_opt_ PVOID  BaseAddress 
)
static

Definition at line 30 of file mdlsup.c.

35{
40 MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
41 MI_PFN_CACHE_ATTRIBUTE EffectiveCacheAttribute;
42 BOOLEAN IsIoMapping;
44 ULONG_PTR StartingVa;
45 ULONG_PTR EndingVa;
47 PMMVAD_LONG Vad;
48 ULONG NumberOfPages;
49 PMMPTE PointerPte;
50 PMMPDE PointerPde;
52 PPFN_NUMBER MdlPages;
53 PMMPFN Pfn1;
54 PMMPFN Pfn2;
55 BOOLEAN AddressSpaceLocked = FALSE;
56
57 PAGED_CODE();
58
59 DPRINT("MiMapLockedPagesInUserSpace(%p, %p, 0x%x, %p)\n",
60 Mdl, StartVa, CacheType, BaseAddress);
61
62 NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartVa,
64 MdlPages = MmGetMdlPfnArray(Mdl);
65
67
68 IsIoMapping = (Mdl->MdlFlags & MDL_IO_SPACE) != 0;
69 CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
70
71 /* Large pages are always cached, make sure we're not asking for those */
72 if (CacheAttribute != MiCached)
73 {
74 DPRINT1("FIXME: Need to check for large pages\n");
75 }
76
78 if (!NT_SUCCESS(Status))
79 {
80 Vad = NULL;
81 goto Error;
82 }
83
84 /* Allocate a VAD for our mapped region */
85 Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
86 if (Vad == NULL)
87 {
90 goto Error;
91 }
92
93 /* Initialize PhysicalMemory VAD */
94 RtlZeroMemory(Vad, sizeof(*Vad));
95 Vad->u2.VadFlags2.LongVad = 1;
98 Vad->u.VadFlags.PrivateMemory = 1;
99
100 /* Did the caller specify an address? */
101 if (BaseAddress == NULL)
102 {
103 /* We get to pick the address */
105 AddressSpaceLocked = TRUE;
106 if (Process->VmDeleted)
107 {
109 goto Error;
110 }
111
114 &Process->VadRoot,
115 &Parent,
116 &StartingVa);
117 if (Result == TableFoundNode)
118 {
120 goto Error;
121 }
122 EndingVa = StartingVa + NumberOfPages * PAGE_SIZE - 1;
123 BaseAddress = (PVOID)StartingVa;
124 }
125 else
126 {
127 /* Caller specified a base address */
128 StartingVa = (ULONG_PTR)BaseAddress;
129 EndingVa = StartingVa + NumberOfPages * PAGE_SIZE - 1;
130
131 /* Make sure it's valid */
132 if (BYTE_OFFSET(StartingVa) != 0 ||
133 EndingVa <= StartingVa ||
135 {
137 goto Error;
138 }
139
141 AddressSpaceLocked = TRUE;
142 if (Process->VmDeleted)
143 {
145 goto Error;
146 }
147
148 /* Check if it's already in use */
150 EndingVa >> PAGE_SHIFT,
151 &Process->VadRoot,
152 &Parent);
153 if (Result == TableFoundNode)
154 {
156 goto Error;
157 }
158 }
159
160 Vad->StartingVpn = StartingVa >> PAGE_SHIFT;
161 Vad->EndingVpn = EndingVa >> PAGE_SHIFT;
162
164
165 ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
166 MiInsertVad((PMMVAD)Vad, &Process->VadRoot);
167
168 /* Check if this is uncached */
169 if (CacheAttribute != MiCached)
170 {
171 /* Flush all caches */
174 }
175
176 PointerPte = MiAddressToPte(BaseAddress);
177 while (NumberOfPages != 0 &&
178 *MdlPages != LIST_HEAD)
179 {
180 PointerPde = MiPteToPde(PointerPte);
182 ASSERT(PointerPte->u.Hard.Valid == 0);
183
184 /* Add a PDE reference for each page */
186
187 /* Set up our basic user PTE */
189 PointerPte,
191 *MdlPages);
192
193 EffectiveCacheAttribute = CacheAttribute;
194
195 /* We need to respect the PFN's caching information in some cases */
196 Pfn2 = MiGetPfnEntry(*MdlPages);
197 if (Pfn2 != NULL)
198 {
199 ASSERT(Pfn2->u3.e2.ReferenceCount != 0);
200
201 switch (Pfn2->u3.e1.CacheAttribute)
202 {
203 case MiNonCached:
204 if (CacheAttribute != MiNonCached)
205 {
206 MiCacheOverride[1]++;
207 EffectiveCacheAttribute = MiNonCached;
208 }
209 break;
210
211 case MiCached:
212 if (CacheAttribute != MiCached)
213 {
214 MiCacheOverride[0]++;
215 EffectiveCacheAttribute = MiCached;
216 }
217 break;
218
219 case MiWriteCombined:
220 if (CacheAttribute != MiWriteCombined)
221 {
222 MiCacheOverride[2]++;
223 EffectiveCacheAttribute = MiWriteCombined;
224 }
225 break;
226
227 default:
228 /* We don't support AWE magic (MiNotMapped) */
229 DPRINT1("FIXME: MiNotMapped is not supported\n");
230 ASSERT(FALSE);
231 break;
232 }
233 }
234
235 /* Configure caching */
236 switch (EffectiveCacheAttribute)
237 {
238 case MiNonCached:
240 break;
241 case MiCached:
243 break;
244 case MiWriteCombined:
246 break;
247 default:
248 ASSERT(FALSE);
249 break;
250 }
251
252 /* Make the page valid */
253 MI_WRITE_VALID_PTE(PointerPte, TempPte);
254
255 /* Acquire a share count */
256 Pfn1 = MI_PFN_ELEMENT(PointerPde->u.Hard.PageFrameNumber);
257 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
258 OldIrql = MiAcquirePfnLock();
259 Pfn1->u2.ShareCount++;
260 MiReleasePfnLock(OldIrql);
261
262 /* Next page */
263 MdlPages++;
264 PointerPte++;
265 NumberOfPages--;
267 }
268
270 ASSERT(AddressSpaceLocked);
272
273 ASSERT(StartingVa != 0);
274 return (PVOID)((ULONG_PTR)StartingVa + MmGetMdlByteOffset(Mdl));
275
276Error:
277 if (AddressSpaceLocked)
278 {
280 }
281 if (Vad != NULL)
282 {
283 ExFreePoolWithTag(Vad, 'ldaV');
285 }
287}
#define PAGED_CODE()
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
BOOL Error
Definition: chkdsk.c:66
#define MM_READWRITE
Definition: bootanim.c:19
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
_In_ ULONG _In_ MEMORY_CACHING_TYPE CacheType
Definition: dispmprt.h:713
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define NonPagedPool
Definition: env_spec_w32.h:307
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:24
#define _ReturnAddress()
Definition: intrin_arm.h:35
MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType]
Definition: iosup.c:27
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:834
enum _MI_PFN_CACHE_ATTRIBUTE MI_PFN_CACHE_ATTRIBUTE
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1246
@ MiWriteCombined
Definition: miarm.h:416
@ MiCached
Definition: miarm.h:415
@ MiNonCached
Definition: miarm.h:414
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2446
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree(IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
Definition: vadnode.c:496
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:967
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:157
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2479
VOID NTAPI MiInsertVad(_Inout_ PMMVAD Vad, _Inout_ PMM_AVL_TABLE VadRoot)
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1581
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1176
ULONG MiCacheOverride[MiNotMapped+1]
Definition: mdlsup.c:24
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID * BaseAddress
Definition: mmfuncs.h:408
@ VadDevicePhysicalMemory
Definition: mmtypes.h:205
#define MiAddressToPte(x)
Definition: mm.h:144
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:48
#define MiPteToPde(_Pte)
Definition: mm.h:136
#define MI_MAKE_PTE_WRITE_COMBINE(Pte)
Definition: mm.h:94
#define MI_MAKE_PTE_CACHED(Pte)
Definition: mm.h:82
#define MI_MAKE_PTE_NON_CACHED(Pte)
Definition: mm.h:88
BOOLEAN NTAPI KeInvalidateAllCaches(VOID)
Definition: cpu.c:523
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1042
#define MM_NOIRQL
Definition: mm.h:67
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1677
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:99
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1690
#define ExRaiseStatus
Definition: ntoskrnl.h:114
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:487
#define STATUS_INVALID_ADDRESS
Definition: ntstatus.h:651
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:596
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:354
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the non paged pool quota of a given process.
Definition: quota.c:811
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define DPRINT
Definition: sndvol32.h:73
USHORT CacheAttribute
Definition: mm.h:373
Definition: mm.h:386
union _MMPFN::@2100 u2
MMPFNENTRY e1
Definition: mm.h:409
ULONG_PTR ShareCount
Definition: mm.h:402
struct _MMPFN::@2101::@2107 e2
union _MMPFN::@2101 u3
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
union _MMPTE::@2788 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG LongVad
Definition: mmtypes.h:711
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR VadType
Definition: mmtypes.h:694
ULONG_PTR PrivateMemory
Definition: mmtypes.h:698
union _MMVAD_LONG::@3117 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:763
ULONG_PTR EndingVpn
Definition: mmtypes.h:759
union _MMVAD_LONG::@3118 u2
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:771
ULONG_PTR StartingVpn
Definition: mmtypes.h:758
#define LIST_HEAD(name, type)
Definition: queue.h:167
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define MmGetMdlByteOffset(_Mdl)
#define MmGetMdlByteCount(_Mdl)
#define BYTE_OFFSET(Va)
#define MmGetMdlPfnArray(_Mdl)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
@ MmWriteCombined
Definition: mmtypes.h:131
#define MDL_IO_SPACE
Definition: mmtypes.h:29
TABLE_SEARCH_RESULT
Definition: rtltypes.h:386

Referenced by MmMapLockedPagesSpecifyCache().

◆ MiUnmapLockedPagesInUserSpace()

static VOID NTAPI MiUnmapLockedPagesInUserSpace ( _In_ PVOID  BaseAddress,
_In_ PMDL  Mdl 
)
static

Definition at line 292 of file mdlsup.c.

295{
298 PMMVAD Vad;
299 PMMPTE PointerPte;
300 PMMPDE PointerPde;
302 ULONG NumberOfPages;
303 PPFN_NUMBER MdlPages;
304 PFN_NUMBER PageTablePage;
305
306 DPRINT("MiUnmapLockedPagesInUserSpace(%p, %p)\n", BaseAddress, Mdl);
307
310 ASSERT(NumberOfPages != 0);
311 MdlPages = MmGetMdlPfnArray(Mdl);
312
313 /* Find the VAD */
316 if (!Vad ||
318 {
319 DPRINT1("MiUnmapLockedPagesInUserSpace invalid for %p\n", BaseAddress);
321 return;
322 }
323
325
326 /* Remove it from the process VAD tree */
327 ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
328 MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
330
331 /* MiRemoveNode should have removed us if we were the hint */
332 ASSERT(Process->VadRoot.NodeHint != Vad);
333
334 PointerPte = MiAddressToPte(BaseAddress);
335 OldIrql = MiAcquirePfnLock();
336 while (NumberOfPages != 0 &&
337 *MdlPages != LIST_HEAD)
338 {
339 ASSERT(MiAddressToPte(PointerPte)->u.Hard.Valid == 1);
340 ASSERT(PointerPte->u.Hard.Valid == 1);
341
342 /* Invalidate it */
343 MI_ERASE_PTE(PointerPte);
344
345 /* We invalidated this PTE, so dereference the PDE */
346 PointerPde = MiAddressToPde(BaseAddress);
347 PageTablePage = PointerPde->u.Hard.PageFrameNumber;
348 MiDecrementShareCount(MiGetPfnEntry(PageTablePage), PageTablePage);
349
351 {
352 ASSERT(MiIsPteOnPdeBoundary(PointerPte + 1) || (NumberOfPages == 1));
353 MiDeletePde(PointerPde, Process);
354 }
355
356 /* Next page */
357 PointerPte++;
358 NumberOfPages--;
360 MdlPages++;
361 }
362
364 MiReleasePfnLock(OldIrql);
367 ExFreePoolWithTag(Vad, 'ldaV');
368}
ULONG_PTR PFN_NUMBER
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
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2539
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:403
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1013
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2505
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1141
FORCEINLINE VOID KeFlushProcessTb(VOID)
Definition: ke.h:282
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:305
#define MiAddressToPde(x)
Definition: mm.h:155
union _MMVAD::@3114 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
#define MmGetMdlVirtualAddress(_Mdl)

Referenced by MmUnmapLockedPages().

◆ MmAdvanceMdl()

NTSTATUS NTAPI MmAdvanceMdl ( IN PMDL  Mdl,
IN ULONG  NumberOfBytes 
)

Definition at line 1614 of file mdlsup.c.

1616{
1619}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42

◆ MmAllocatePagesForMdl()

PMDL NTAPI MmAllocatePagesForMdl ( IN PHYSICAL_ADDRESS  LowAddress,
IN PHYSICAL_ADDRESS  HighAddress,
IN PHYSICAL_ADDRESS  SkipBytes,
IN SIZE_T  TotalBytes 
)

Definition at line 488 of file mdlsup.c.

492{
493 //
494 // Call the internal routine
495 //
496 return MiAllocatePagesForMdl(LowAddress,
498 SkipBytes,
501 0);
502}
PMDL NTAPI MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress, IN PHYSICAL_ADDRESS HighAddress, IN PHYSICAL_ADDRESS SkipBytes, IN SIZE_T TotalBytes, IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute, IN ULONG Flags)
Definition: freelist.c:182
@ MiNotMapped
Definition: miarm.h:417
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS HighAddress
Definition: mmfuncs.h:226
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:227
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS _In_ SIZE_T TotalBytes
Definition: mmfuncs.h:228

Referenced by HDA_AllocateDmaBufferWithNotification(), and TestMmAllocatePagesForMdl().

◆ MmAllocatePagesForMdlEx()

PMDL NTAPI MmAllocatePagesForMdlEx ( IN PHYSICAL_ADDRESS  LowAddress,
IN PHYSICAL_ADDRESS  HighAddress,
IN PHYSICAL_ADDRESS  SkipBytes,
IN SIZE_T  TotalBytes,
IN MEMORY_CACHING_TYPE  CacheType,
IN ULONG  Flags 
)

Definition at line 509 of file mdlsup.c.

515{
516 MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
517
518 //
519 // Check for invalid cache type
520 //
522 {
523 //
524 // Normalize to default
525 //
526 CacheAttribute = MiNotMapped;
527 }
528 else
529 {
530 //
531 // Convert to internal caching attribute
532 //
533 CacheAttribute = MiPlatformCacheAttributes[FALSE][CacheType];
534 }
535
536 //
537 // Only these flags are allowed
538 //
540 {
541 //
542 // Silently fail
543 //
544 return NULL;
545 }
546
547 //
548 // Call the internal routine
549 //
550 return MiAllocatePagesForMdl(LowAddress,
552 SkipBytes,
554 CacheAttribute,
555 Flags);
556}
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define MM_DONT_ZERO_ALLOCATION
Definition: mmtypes.h:11
#define MM_ALLOCATE_FROM_LOCAL_NODE_ONLY
Definition: mmtypes.h:12

◆ MmBuildMdlForNonPagedPool()

VOID NTAPI MmBuildMdlForNonPagedPool ( IN PMDL  Mdl)

Definition at line 423 of file mdlsup.c.

424{
425 PPFN_NUMBER MdlPages, EndPage;
426 PFN_NUMBER Pfn, PageCount;
427 PVOID Base;
428 PMMPTE PointerPte;
429
430 //
431 // Sanity checks
432 //
433 ASSERT(Mdl->ByteCount != 0);
434 ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED |
437 MDL_PARTIAL)) == 0);
438
439 //
440 // We know the MDL isn't associated to a process now
441 //
442 Mdl->Process = NULL;
443
444 //
445 // Get page and VA information
446 //
447 MdlPages = (PPFN_NUMBER)(Mdl + 1);
448 Base = Mdl->StartVa;
449
450 //
451 // Set the system address and now get the page count
452 //
453 Mdl->MappedSystemVa = (PVOID)((ULONG_PTR)Base + Mdl->ByteOffset);
454 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Mdl->MappedSystemVa,
455 Mdl->ByteCount);
456 ASSERT(PageCount != 0);
457 EndPage = MdlPages + PageCount;
458
459 //
460 // Loop the PTEs
461 //
462 PointerPte = MiAddressToPte(Base);
463 do
464 {
465 //
466 // Write the PFN
467 //
468 Pfn = PFN_FROM_PTE(PointerPte++);
469 *MdlPages++ = Pfn;
470 } while (MdlPages < EndPage);
471
472 //
473 // Set the nonpaged pool flag
474 //
475 Mdl->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
476
477 //
478 // Check if this is an I/O mapping
479 //
480 if (!MiGetPfnEntry(Pfn)) Mdl->MdlFlags |= MDL_IO_SPACE;
481}
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2486
#define PFN_FROM_PTE(v)
Definition: mm.h:94
int WINAPI EndPage(_In_ HDC)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_PARTIAL
Definition: mmtypes.h:22
#define MDL_SOURCE_IS_NONPAGED_POOL
Definition: mmtypes.h:20
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18

Referenced by __attribute__(), _Success_(), AtaReqAllocateMdl(), ClasspInitializeGesn(), CreateDMA(), DiskInfoExceptionCheck(), Ext2CreateMdl(), FatBuildZeroMdl(), KbdHid_StartDevice(), MouHid_StartDevice(), Mx::MxBuildMdlForNonPagedPool(), NdisAllocateBuffer(), read_data(), TestMmBuildMdlForNonPagedPool(), TestProviderInfo(), USBPORT_SendSetupPacket(), USBPORT_ValidateTransferParametersURB(), USBSTOR_AllocateIrp(), USBSTOR_SendInternalCdb(), USBSTOR_SendRequest(), and write_superblock().

◆ MmCreateMdl()

PMDL NTAPI MmCreateMdl ( IN PMDL  Mdl,
IN PVOID  Base,
IN SIZE_T  Length 
)

Definition at line 377 of file mdlsup.c.

380{
381 SIZE_T Size;
382
383 //
384 // Check if we don't have an MDL built
385 //
386 if (!Mdl)
387 {
388 //
389 // Calculate the size we'll need and allocate the MDL
390 //
393 if (!Mdl) return NULL;
394 }
395
396 //
397 // Initialize it
398 //
400 return Mdl;
401}
SIZE_T NTAPI MmSizeOfMdl(IN PVOID Base, IN SIZE_T Length)
Definition: mdlsup.c:408
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define TAG_MDL
Definition: tag.h:88
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)

Referenced by MiAllocatePagesForMdl().

◆ MmFreePagesFromMdl()

VOID NTAPI MmFreePagesFromMdl ( IN PMDL  Mdl)

Definition at line 563 of file mdlsup.c.

564{
565 PVOID Base;
566 PPFN_NUMBER Pages;
567 LONG NumberOfPages;
568 PMMPFN Pfn1;
570 DPRINT("Freeing MDL: %p\n", Mdl);
571
572 //
573 // Sanity checks
574 //
576 ASSERT((Mdl->MdlFlags & MDL_IO_SPACE) == 0);
577 ASSERT(((ULONG_PTR)Mdl->StartVa & (PAGE_SIZE - 1)) == 0);
578
579 //
580 // Get address and page information
581 //
582 Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
583 NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
584
585 //
586 // Acquire PFN lock
587 //
588 OldIrql = MiAcquirePfnLock();
589
590 //
591 // Loop all the MDL pages
592 //
593 Pages = (PPFN_NUMBER)(Mdl + 1);
594 do
595 {
596 //
597 // Reached the last page
598 //
599 if (*Pages == LIST_HEAD) break;
600
601 //
602 // Get the page entry
603 //
604 Pfn1 = MiGetPfnEntry(*Pages);
605 ASSERT(Pfn1);
606 ASSERT(Pfn1->u2.ShareCount == 1);
607 ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
608 if (Pfn1->u4.PteFrame != 0x1FFEDCB)
609 {
610 /* Corrupted PFN entry or invalid free */
611 KeBugCheckEx(MEMORY_MANAGEMENT, 0x1236, (ULONG_PTR)Mdl, (ULONG_PTR)Pages, *Pages);
612 }
613
614 //
615 // Clear it
616 //
617 Pfn1->u3.e1.StartOfAllocation = 0;
618 Pfn1->u3.e1.EndOfAllocation = 0;
620 Pfn1->u2.ShareCount = 0;
621
622 //
623 // Dereference it
624 //
625 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
626 if (Pfn1->u3.e2.ReferenceCount != 1)
627 {
628 /* Just take off one reference */
629 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
630 }
631 else
632 {
633 /* We'll be nuking the whole page */
634 MiDecrementReferenceCount(Pfn1, *Pages);
635 }
636
637 //
638 // Clear this page and move on
639 //
640 *Pages++ = LIST_HEAD;
641 } while (--NumberOfPages != 0);
642
643 //
644 // Release the lock
645 //
646 MiReleasePfnLock(OldIrql);
647
648 //
649 // Remove the pages locked flag
650 //
651 Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
652}
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define InterlockedDecrement16
Definition: interlocked.h:154
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1236
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:209
@ StandbyPageList
Definition: mmtypes.h:155
long LONG
Definition: pedump.c:60
USHORT PageLocation
Definition: mm.h:371
union _MMPFN::@2104 u4
ULONG_PTR PteFrame
Definition: mm.h:433
int16_t * PSHORT
Definition: typedefs.h:55

Referenced by HDA_FreeDmaBufferWithNotification(), MmAllocateNonCachedMemory(), MmFreeNonCachedMemory(), TestMap(), and TestMmAllocatePagesForMdl().

◆ MmMapLockedPages()

PVOID NTAPI MmMapLockedPages ( IN PMDL  Mdl,
IN KPROCESSOR_MODE  AccessMode 
)

Definition at line 815 of file mdlsup.c.

817{
818 //
819 // Call the extended version
820 //
823 MmCached,
824 NULL,
825 TRUE,
827}
PVOID NTAPI MmMapLockedPagesSpecifyCache(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress, IN ULONG BugCheckOnFailure, IN ULONG Priority)
Definition: mdlsup.c:659
@ HighPagePriority
Definition: imports.h:55
@ MmCached
Definition: mmtypes.h:130

Referenced by KsProbeStreamIrp(), MmGetSystemAddressForMdlSafer(), NtStartProfile(), SatisfyPacketRecvRequest(), SendComplete(), and TryToSatisfyRecvRequestFromBuffer().

◆ MmMapLockedPagesSpecifyCache()

PVOID NTAPI MmMapLockedPagesSpecifyCache ( IN PMDL  Mdl,
IN KPROCESSOR_MODE  AccessMode,
IN MEMORY_CACHING_TYPE  CacheType,
IN PVOID  BaseAddress,
IN ULONG  BugCheckOnFailure,
IN ULONG  Priority 
)

Definition at line 659 of file mdlsup.c.

665{
666 PVOID Base;
667 PPFN_NUMBER MdlPages, LastPage;
668 PFN_COUNT PageCount;
669 BOOLEAN IsIoMapping;
670 MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
671 PMMPTE PointerPte;
673
674 //
675 // Sanity check
676 //
677 ASSERT(Mdl->ByteCount != 0);
678
679 //
680 // Get the base
681 //
682 Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
683
684 //
685 // Handle kernel case first
686 //
687 if (AccessMode == KernelMode)
688 {
689 //
690 // Get the list of pages and count
691 //
692 MdlPages = (PPFN_NUMBER)(Mdl + 1);
693 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
694 LastPage = MdlPages + PageCount;
695
696 //
697 // Sanity checks
698 //
699 ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
702 ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0);
703
704 //
705 // Get the correct cache type
706 //
707 IsIoMapping = (Mdl->MdlFlags & MDL_IO_SPACE) != 0;
708 CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
709
710 //
711 // Reserve the PTEs
712 //
713 PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
714 if (!PointerPte)
715 {
716 //
717 // If it can fail, return NULL
718 //
719 if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
720
721 //
722 // Should we bugcheck?
723 //
724 if (!BugCheckOnFailure) return NULL;
725
726 //
727 // Yes, crash the system
728 //
729 KeBugCheckEx(NO_MORE_SYSTEM_PTES, 0, PageCount, 0, 0);
730 }
731
732 //
733 // Get the mapped address
734 //
735 Base = (PVOID)((ULONG_PTR)MiPteToAddress(PointerPte) + Mdl->ByteOffset);
736
737 //
738 // Get the template
739 //
741 switch (CacheAttribute)
742 {
743 case MiNonCached:
744
745 //
746 // Disable caching
747 //
749 break;
750
751 case MiWriteCombined:
752
753 //
754 // Enable write combining
755 //
757 break;
758
759 default:
760 //
761 // Nothing to do
762 //
763 break;
764 }
765
766 //
767 // Loop all PTEs
768 //
769 do
770 {
771 //
772 // We're done here
773 //
774 if (*MdlPages == LIST_HEAD) break;
775
776 //
777 // Write the PTE
778 //
779 TempPte.u.Hard.PageFrameNumber = *MdlPages;
780 MI_WRITE_VALID_PTE(PointerPte++, TempPte);
781 } while (++MdlPages < LastPage);
782
783 //
784 // Mark it as mapped
785 //
786 ASSERT((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0);
787 Mdl->MappedSystemVa = Base;
788 Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
789
790 //
791 // Check if it was partial
792 //
793 if (Mdl->MdlFlags & MDL_PARTIAL)
794 {
795 //
796 // Write the appropriate flag here too
797 //
798 Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
799 }
800
801 //
802 // Return the mapped address
803 //
804 return Base;
805 }
806
808}
@ SystemPteSpace
Definition: miarm.h:407
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
static PVOID NTAPI MiMapLockedPagesInUserSpace(_In_ PMDL Mdl, _In_ PVOID StartVa, _In_ MEMORY_CACHING_TYPE CacheType, _In_opt_ PVOID BaseAddress)
Definition: mdlsup.c:30
#define KernelMode
Definition: asm.h:38
#define MiPteToAddress(_Pte)
Definition: mm.h:131
MMPTE ValidKernelPte
Definition: init.c:29
ULONG PageFrameNumber
Definition: mmtypes.h:109
#define MDL_PARTIAL_HAS_BEEN_MAPPED
Definition: mmtypes.h:23
#define MDL_MAPPING_CAN_FAIL
Definition: mmtypes.h:31
ULONG PFN_COUNT
Definition: mmtypes.h:102

Referenced by get_block_bh_mdl(), KsepWriteImportEntry(), marshal_nfs41_dirquery(), marshal_nfs41_open(), marshal_nfs41_rw(), MiDoMappedCopy(), MmMapLockedPages(), RamdiskReadWriteReal(), TestMessageHandler(), and TestMmAllocatePagesForMdl().

◆ MmMapLockedPagesWithReservedMapping()

PVOID NTAPI MmMapLockedPagesWithReservedMapping ( _In_ PVOID  MappingAddress,
_In_ ULONG  PoolTag,
_In_ PMDL  Mdl,
_In_ MEMORY_CACHING_TYPE  CacheType 
)

Definition at line 1626 of file mdlsup.c.

1631{
1632 PPFN_NUMBER MdlPages, LastPage;
1633 PFN_COUNT PageCount;
1634 BOOLEAN IsIoMapping;
1635 MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
1636 PMMPTE PointerPte;
1637 MMPTE TempPte;
1638
1639 ASSERT(Mdl->ByteCount != 0);
1640
1641 // Get the list of pages and count
1642 MdlPages = MmGetMdlPfnArray(Mdl);
1644 Mdl->ByteCount);
1645 LastPage = MdlPages + PageCount;
1646
1647 // Sanity checks
1648 ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
1651 ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0);
1652
1653 // Get the correct cache type
1654 IsIoMapping = (Mdl->MdlFlags & MDL_IO_SPACE) != 0;
1655 CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
1656
1657 // Get the first PTE we reserved
1658 ASSERT(MappingAddress);
1659 PointerPte = MiAddressToPte(MappingAddress) - 2;
1660 ASSERT(!PointerPte[0].u.Hard.Valid &&
1661 !PointerPte[1].u.Hard.Valid);
1662
1663 // Verify that the pool tag matches
1664 TempPte.u.Long = PoolTag;
1665 TempPte.u.Hard.Valid = 0;
1666 if (PointerPte[1].u.Long != TempPte.u.Long)
1667 {
1668 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1669 PTE_MAPPING_ADDRESS_NOT_OWNED, /* Trying to map an address it does not own */
1670 (ULONG_PTR)MappingAddress,
1671 PoolTag,
1672 PointerPte[1].u.Long);
1673 }
1674
1675 // We must have a size, and our helper PTEs must be invalid
1676 if (PointerPte[0].u.List.NextEntry < 3)
1677 {
1678 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1679 PTE_MAPPING_ADDRESS_INVALID, /* Trying to map an invalid address */
1680 (ULONG_PTR)MappingAddress,
1681 PoolTag,
1683 }
1684
1685 // If the mapping isn't big enough, fail
1686 if (PointerPte[0].u.List.NextEntry - 2 < PageCount)
1687 {
1688 DPRINT1("Reserved mapping too small. Need %Iu pages, have %Iu\n",
1689 PageCount,
1690 PointerPte[0].u.List.NextEntry - 2);
1691 return NULL;
1692 }
1693 // Skip our two helper PTEs
1694 PointerPte += 2;
1695
1696 // Get the template
1698 switch (CacheAttribute)
1699 {
1700 case MiNonCached:
1701 // Disable caching
1703 break;
1704
1705 case MiWriteCombined:
1706 // Enable write combining
1708 break;
1709
1710 default:
1711 // Nothing to do
1712 break;
1713 }
1714
1715 // Loop all PTEs
1716 for (; (MdlPages < LastPage) && (*MdlPages != LIST_HEAD); ++MdlPages)
1717 {
1718 // Write the PTE
1719 TempPte.u.Hard.PageFrameNumber = *MdlPages;
1720 MI_WRITE_VALID_PTE(PointerPte++, TempPte);
1721 }
1722
1723 // Mark it as mapped
1724 ASSERT((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0);
1725 Mdl->MappedSystemVa = MappingAddress;
1726 Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
1727
1728 // Check if it was partial
1729 if (Mdl->MdlFlags & MDL_PARTIAL)
1730 {
1731 // Write the appropriate flag here too
1732 Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
1733 }
1734
1735 // Return the mapped address
1736 return (PVOID)((ULONG_PTR)MappingAddress + Mdl->ByteOffset);
1737}
#define PTE_MAPPING_ADDRESS_INVALID
Definition: miarm.h:167
#define PTE_MAPPING_ADDRESS_NOT_OWNED
Definition: miarm.h:166
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG PoolTag
Definition: wdfmemory.h:164

Referenced by AtaReqMapBuffer(), and TestMap().

◆ MmMapMemoryDumpMdl()

VOID NTAPI MmMapMemoryDumpMdl ( IN PMDL  Mdl)

Definition at line 1936 of file mdlsup.c.

1937{
1939}

◆ MmPrefetchPages()

NTSTATUS NTAPI MmPrefetchPages ( IN ULONG  NumberOfLists,
IN PREAD_LIST *  ReadLists 
)

Definition at line 1845 of file mdlsup.c.

1847{
1850}

Referenced by FatPrefetchPages().

◆ MmProbeAndLockPages()

VOID NTAPI MmProbeAndLockPages ( IN PMDL  Mdl,
IN KPROCESSOR_MODE  AccessMode,
IN LOCK_OPERATION  Operation 
)

Definition at line 928 of file mdlsup.c.

931{
932 PPFN_NUMBER MdlPages;
933 PVOID Base, Address, LastAddress, StartAddress;
934 ULONG LockPages, TotalPages;
936 PEPROCESS CurrentProcess;
937 NTSTATUS ProbeStatus;
938 PMMPTE PointerPte, LastPte;
939 PMMPDE PointerPde;
940#if (_MI_PAGING_LEVELS >= 3)
941 PMMPDE PointerPpe;
942#endif
943#if (_MI_PAGING_LEVELS == 4)
944 PMMPDE PointerPxe;
945#endif
946 PFN_NUMBER PageFrameIndex;
947 BOOLEAN UsePfnLock;
949 PMMPFN Pfn1;
950 DPRINT("Probing MDL: %p\n", Mdl);
951
952 //
953 // Sanity checks
954 //
955 ASSERT(Mdl->ByteCount != 0);
956 ASSERT(((ULONG)Mdl->ByteOffset & ~(PAGE_SIZE - 1)) == 0);
957 ASSERT(((ULONG_PTR)Mdl->StartVa & (PAGE_SIZE - 1)) == 0);
958 ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED |
962 MDL_IO_SPACE)) == 0);
963
964 //
965 // Get page and base information
966 //
967 MdlPages = (PPFN_NUMBER)(Mdl + 1);
968 Base = Mdl->StartVa;
969
970 //
971 // Get the addresses and how many pages we span (and need to lock)
972 //
973 Address = (PVOID)((ULONG_PTR)Base + Mdl->ByteOffset);
974 LastAddress = (PVOID)((ULONG_PTR)Address + Mdl->ByteCount);
975 LockPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Address, Mdl->ByteCount);
976 ASSERT(LockPages != 0);
977
978 /* Block invalid access */
979 if ((AccessMode != KernelMode) &&
980 ((LastAddress > (PVOID)MM_USER_PROBE_ADDRESS) || (Address >= LastAddress)))
981 {
982 /* Caller should be in SEH, raise the error */
983 *MdlPages = LIST_HEAD;
985 }
986
987 //
988 // Get the process
989 //
991 {
992 //
993 // Get the process
994 //
995 CurrentProcess = PsGetCurrentProcess();
996 }
997 else
998 {
999 //
1000 // No process
1001 //
1002 CurrentProcess = NULL;
1003 }
1004
1005 //
1006 // Save the number of pages we'll have to lock, and the start address
1007 //
1008 TotalPages = LockPages;
1009 StartAddress = Address;
1010
1011 /* Large pages not supported */
1013
1014 //
1015 // Now probe them
1016 //
1017 ProbeStatus = STATUS_SUCCESS;
1018 _SEH2_TRY
1019 {
1020 //
1021 // Enter probe loop
1022 //
1023 do
1024 {
1025 //
1026 // Assume failure
1027 //
1028 *MdlPages = LIST_HEAD;
1029
1030 //
1031 // Read
1032 //
1033 *(volatile CHAR*)Address;
1034
1035 //
1036 // Check if this is write access (only probe for user-mode)
1037 //
1038 if ((Operation != IoReadAccess) &&
1040 {
1041 //
1042 // Probe for write too
1043 //
1045 }
1046
1047 //
1048 // Next address...
1049 //
1051
1052 //
1053 // Next page...
1054 //
1055 LockPages--;
1056 MdlPages++;
1057 } while (Address < LastAddress);
1058
1059 //
1060 // Reset back to the original page
1061 //
1062 ASSERT(LockPages == 0);
1063 MdlPages = (PPFN_NUMBER)(Mdl + 1);
1064 }
1066 {
1067 //
1068 // Oops :(
1069 //
1070 ProbeStatus = _SEH2_GetExceptionCode();
1071 }
1072 _SEH2_END;
1073
1074 //
1075 // So how did that go?
1076 //
1077 if (ProbeStatus != STATUS_SUCCESS)
1078 {
1079 //
1080 // Fail
1081 //
1082 DPRINT1("MDL PROBE FAILED!\n");
1083 Mdl->Process = NULL;
1084 ExRaiseStatus(ProbeStatus);
1085 }
1086
1087 //
1088 // Get the PTE and PDE
1089 //
1090 PointerPte = MiAddressToPte(StartAddress);
1091 PointerPde = MiAddressToPde(StartAddress);
1092#if (_MI_PAGING_LEVELS >= 3)
1093 PointerPpe = MiAddressToPpe(StartAddress);
1094#endif
1095#if (_MI_PAGING_LEVELS == 4)
1096 PointerPxe = MiAddressToPxe(StartAddress);
1097#endif
1098
1099 //
1100 // Sanity check
1101 //
1102 ASSERT(MdlPages == (PPFN_NUMBER)(Mdl + 1));
1103
1104 //
1105 // Check what kind of operation this is
1106 //
1107 if (Operation != IoReadAccess)
1108 {
1109 //
1110 // Set the write flag
1111 //
1112 Mdl->MdlFlags |= MDL_WRITE_OPERATION;
1113 }
1114 else
1115 {
1116 //
1117 // Remove the write flag
1118 //
1119 Mdl->MdlFlags &= ~(MDL_WRITE_OPERATION);
1120 }
1121
1122 //
1123 // Mark the MDL as locked *now*
1124 //
1125 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
1126
1127 //
1128 // Check if this came from kernel mode
1129 //
1131 {
1132 //
1133 // We should not have a process
1134 //
1135 ASSERT(CurrentProcess == NULL);
1136 Mdl->Process = NULL;
1137
1138 //
1139 // In kernel mode, we don't need to check for write access
1140 //
1142
1143 //
1144 // Use the PFN lock
1145 //
1146 UsePfnLock = TRUE;
1147 OldIrql = MiAcquirePfnLock();
1148 }
1149 else
1150 {
1151 //
1152 // Sanity checks
1153 //
1154 ASSERT(TotalPages != 0);
1155 ASSERT(CurrentProcess == PsGetCurrentProcess());
1156
1157 //
1158 // Track locked pages
1159 //
1161 TotalPages);
1162
1163 //
1164 // Save the process
1165 //
1166 Mdl->Process = CurrentProcess;
1167
1168 /* Lock the process working set */
1170 UsePfnLock = FALSE;
1172 }
1173
1174 //
1175 // Get the last PTE
1176 //
1177 LastPte = MiAddressToPte((PVOID)((ULONG_PTR)LastAddress - 1));
1178
1179 //
1180 // Loop the pages
1181 //
1182 do
1183 {
1184 //
1185 // Assume failure and check for non-mapped pages
1186 //
1187 *MdlPages = LIST_HEAD;
1188 while (
1189#if (_MI_PAGING_LEVELS == 4)
1190 (PointerPxe->u.Hard.Valid == 0) ||
1191#endif
1192#if (_MI_PAGING_LEVELS >= 3)
1193 (PointerPpe->u.Hard.Valid == 0) ||
1194#endif
1195 (PointerPde->u.Hard.Valid == 0) ||
1196 (PointerPte->u.Hard.Valid == 0))
1197 {
1198 //
1199 // What kind of lock were we using?
1200 //
1201 if (UsePfnLock)
1202 {
1203 //
1204 // Release PFN lock
1205 //
1206 MiReleasePfnLock(OldIrql);
1207 }
1208 else
1209 {
1210 /* Release process working set */
1212 }
1213
1214 //
1215 // Access the page
1216 //
1217 Address = MiPteToAddress(PointerPte);
1218
1219 //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
1220 Status = MmAccessFault(FALSE, Address, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
1221 if (!NT_SUCCESS(Status))
1222 {
1223 //
1224 // Fail
1225 //
1226 DPRINT1("Access fault failed\n");
1227 goto Cleanup;
1228 }
1229
1230 //
1231 // What lock should we use?
1232 //
1233 if (UsePfnLock)
1234 {
1235 //
1236 // Grab the PFN lock
1237 //
1238 OldIrql = MiAcquirePfnLock();
1239 }
1240 else
1241 {
1242 /* Lock the process working set */
1244 }
1245 }
1246
1247 //
1248 // Check if this was a write or modify
1249 //
1250 if (Operation != IoReadAccess)
1251 {
1252 //
1253 // Check if the PTE is not writable
1254 //
1255 if (MI_IS_PAGE_WRITEABLE(PointerPte) == FALSE)
1256 {
1257 //
1258 // Check if it's copy on write
1259 //
1260 if (MI_IS_PAGE_COPY_ON_WRITE(PointerPte))
1261 {
1262 //
1263 // Get the base address and allow a change for user-mode
1264 //
1265 Address = MiPteToAddress(PointerPte);
1267 {
1268 //
1269 // What kind of lock were we using?
1270 //
1271 if (UsePfnLock)
1272 {
1273 //
1274 // Release PFN lock
1275 //
1276 MiReleasePfnLock(OldIrql);
1277 }
1278 else
1279 {
1280 /* Release process working set */
1282 }
1283
1284 //
1285 // Access the page
1286 //
1287
1288 //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
1289 Status = MmAccessFault(TRUE, Address, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
1290 if (!NT_SUCCESS(Status))
1291 {
1292 //
1293 // Fail
1294 //
1295 DPRINT1("Access fault failed\n");
1296 goto Cleanup;
1297 }
1298
1299 //
1300 // Re-acquire the lock
1301 //
1302 if (UsePfnLock)
1303 {
1304 //
1305 // Grab the PFN lock
1306 //
1307 OldIrql = MiAcquirePfnLock();
1308 }
1309 else
1310 {
1311 /* Lock the process working set */
1313 }
1314
1315 //
1316 // Start over
1317 //
1318 continue;
1319 }
1320 }
1321
1322 //
1323 // Fail, since we won't allow this
1324 //
1326 goto CleanupWithLock;
1327 }
1328 }
1329
1330 //
1331 // Grab the PFN
1332 //
1333 PageFrameIndex = PFN_FROM_PTE(PointerPte);
1334 Pfn1 = MiGetPfnEntry(PageFrameIndex);
1335 if (Pfn1)
1336 {
1337 /* Either this is for kernel-mode, or the working set is held */
1338 ASSERT((CurrentProcess == NULL) || (UsePfnLock == FALSE));
1339
1340 /* No Physical VADs supported yet */
1341 if (CurrentProcess) ASSERT(CurrentProcess->PhysicalVadRoot == NULL);
1342
1343 /* This address should already exist and be fully valid */
1345 }
1346 else
1347 {
1348 //
1349 // For I/O addresses, just remember this
1350 //
1351 Mdl->MdlFlags |= MDL_IO_SPACE;
1352 }
1353
1354 //
1355 // Write the page and move on
1356 //
1357 *MdlPages++ = PageFrameIndex;
1358 PointerPte++;
1359
1360 /* Check if we're on a PDE boundary */
1361 if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
1362#if (_MI_PAGING_LEVELS >= 3)
1363 if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
1364#endif
1365#if (_MI_PAGING_LEVELS == 4)
1366 if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
1367#endif
1368
1369 } while (PointerPte <= LastPte);
1370
1371 //
1372 // What kind of lock were we using?
1373 //
1374 if (UsePfnLock)
1375 {
1376 //
1377 // Release PFN lock
1378 //
1379 MiReleasePfnLock(OldIrql);
1380 }
1381 else
1382 {
1383 /* Release process working set */
1385 }
1386
1387 //
1388 // Sanity check
1389 //
1390 ASSERT((Mdl->MdlFlags & MDL_DESCRIBES_AWE) == 0);
1391 return;
1392
1393CleanupWithLock:
1394 //
1395 // This is the failure path
1396 //
1398
1399 //
1400 // What kind of lock were we using?
1401 //
1402 if (UsePfnLock)
1403 {
1404 //
1405 // Release PFN lock
1406 //
1407 MiReleasePfnLock(OldIrql);
1408 }
1409 else
1410 {
1411 /* Release process working set */
1413 }
1414Cleanup:
1415 //
1416 // Pages must be locked so MmUnlock can work
1417 //
1418 ASSERT(Mdl->MdlFlags & MDL_PAGES_LOCKED);
1420
1421 //
1422 // Raise the error
1423 //
1425}
#define MM_USER_PROBE_ADDRESS
Definition: armddk.h:19
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
static const WCHAR Cleanup[]
Definition: register.c:80
#define STATUS_ACCESS_VIOLATION
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:211
if(dx< 0)
Definition: linetemp.h:194
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:953
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1201
FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1694
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1131
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1432
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:109
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:105
#define MiIsPteOnPpeBoundary(PointerPte)
Definition: mm.h:307
#define _MI_PAGING_LEVELS
Definition: mm.h:8
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:160
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:170
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:309
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:220
char CHAR
Definition: pedump.c:57
static WCHAR Address[46]
Definition: ping.c:68
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define ProbeForWriteChar(Ptr)
Definition: probe.h:33
#define STATUS_SUCCESS
Definition: shellext.h:65
PMM_AVL_TABLE PhysicalVadRoot
Definition: pstypes.h:1503
PFN_NUMBER NumberOfLockedPages
Definition: pstypes.h:1506
@ IoReadAccess
Definition: ketypes.h:931
#define PAGE_ALIGN(Va)
#define MDL_WRITE_OPERATION
Definition: mmtypes.h:25
#define MDL_DESCRIBES_AWE
Definition: mmtypes.h:28

Referenced by __attribute__(), __drv_allocatesMem(), _IRQL_requires_max_(), add_thread_job(), AfdGetSockName(), AfdSuperAccept(), BuildAndSubmitIrp(), CdCreateUserMdl(), ClasspBuildDeviceMdl(), ClassSendDeviceIoControlSynchronous(), ClassSendSrbSynchronous(), DispTdiQueryInformationEx(), DriverIoControl(), ExLockUserBuffer(), Ext2CreateMdl(), Ext2LockUserBuffer(), FatLockUserBuffer(), FatSingleNonAlignedSync(), FxProbeAndLockForRead(), FxProbeAndLockForWrite(), FxProbeAndLockWithAccess(), HackSecureVirtualMemory(), IoBuildAsynchronousFsdRequest(), IoBuildDeviceIoControlRequest(), IopDeviceFsIoControl(), KsepWriteImportEntry(), KsProbeStreamIrp(), LockBuffers(), LockRequest(), MapAndLockUserBuffer(), MiDoMappedCopy(), MupBuildIoControlRequest(), nfs41_QueryDirectory(), NtfsIssueIoRuns(), NtfsLockUserBuffer(), NtQueryDirectoryFile(), NtReadFile(), NtStartProfile(), NtWriteFile(), PortPdoIssueRequest(), read_data(), RxLockUserBuffer(), SatisfySuperAccept(), scrub_chunk_raid56_stripe_run(), scrub_extent(), sync_read_phys(), TdiQueryMaxDatagramLength(), TdiReceive(), TdiReceiveDatagram(), TdiSend(), TdiSendDatagram(), TestMessageHandler(), UDFGetCallersBuffer(), UDFLockCallersBuffer(), VfatLockUserBuffer(), VideoPortLockBuffer(), and write_data_phys().

◆ MmProbeAndLockSelectedPages()

VOID NTAPI MmProbeAndLockSelectedPages ( IN OUT PMDL  MemoryDescriptorList,
IN LARGE_INTEGER  PageList[],
IN KPROCESSOR_MODE  AccessMode,
IN LOCK_OPERATION  Operation 
)

Definition at line 1923 of file mdlsup.c.

1927{
1929}

◆ MmProtectMdlSystemAddress()

NTSTATUS NTAPI MmProtectMdlSystemAddress ( IN PMDL  MemoryDescriptorList,
IN ULONG  NewProtect 
)

Definition at line 1857 of file mdlsup.c.

1859{
1862}

◆ MmSizeOfMdl()

SIZE_T NTAPI MmSizeOfMdl ( IN PVOID  Base,
IN SIZE_T  Length 
)

Definition at line 408 of file mdlsup.c.

410{
411 //
412 // Return the MDL size
413 //
414 return sizeof(MDL) +
416}
MDL
Definition: mmtypes.h:117

Referenced by FxRequestBuffer::GetOrAllocateMdlWorker(), and MmCreateMdl().

◆ MmUnlockPages()

VOID NTAPI MmUnlockPages ( IN PMDL  Mdl)

Definition at line 1432 of file mdlsup.c.

1433{
1434 PPFN_NUMBER MdlPages, LastPage;
1436 PVOID Base;
1437 ULONG Flags, PageCount;
1438 KIRQL OldIrql;
1439 PMMPFN Pfn1;
1440 DPRINT("Unlocking MDL: %p\n", Mdl);
1441
1442 //
1443 // Sanity checks
1444 //
1445 ASSERT((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0);
1446 ASSERT((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0);
1447 ASSERT((Mdl->MdlFlags & MDL_PARTIAL) == 0);
1448 ASSERT(Mdl->ByteCount != 0);
1449
1450 //
1451 // Get the process associated and capture the flags which are volatile
1452 //
1453 Process = Mdl->Process;
1454 Flags = Mdl->MdlFlags;
1455
1456 //
1457 // Automagically undo any calls to MmGetSystemAddressForMdl's for this MDL
1458 //
1459 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1460 {
1461 //
1462 // Unmap the pages from system space
1463 //
1464 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1465 }
1466
1467 //
1468 // Get the page count
1469 //
1470 MdlPages = (PPFN_NUMBER)(Mdl + 1);
1471 Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
1472 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
1473 ASSERT(PageCount != 0);
1474
1475 //
1476 // We don't support AWE
1477 //
1479
1480 //
1481 // Check if the buffer is mapped I/O space
1482 //
1483 if (Flags & MDL_IO_SPACE)
1484 {
1485 //
1486 // Acquire PFN lock
1487 //
1488 OldIrql = MiAcquirePfnLock();
1489
1490 //
1491 // Loop every page
1492 //
1493 LastPage = MdlPages + PageCount;
1494 do
1495 {
1496 //
1497 // Last page, break out
1498 //
1499 if (*MdlPages == LIST_HEAD) break;
1500
1501 //
1502 // Check if this page is in the PFN database
1503 //
1504 Pfn1 = MiGetPfnEntry(*MdlPages);
1505 if (Pfn1) MiDereferencePfnAndDropLockCount(Pfn1);
1506 } while (++MdlPages < LastPage);
1507
1508 //
1509 // Release the lock
1510 //
1511 MiReleasePfnLock(OldIrql);
1512
1513 //
1514 // Check if we have a process
1515 //
1516 if (Process)
1517 {
1518 //
1519 // Handle the accounting of locked pages
1520 //
1521 ASSERT(Process->NumberOfLockedPages > 0);
1522 InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
1523 -(LONG_PTR)PageCount);
1524 }
1525
1526 //
1527 // We're done
1528 //
1529 Mdl->MdlFlags &= ~MDL_IO_SPACE;
1530 Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
1531 return;
1532 }
1533
1534 //
1535 // Check if we have a process
1536 //
1537 if (Process)
1538 {
1539 //
1540 // Handle the accounting of locked pages
1541 //
1542 ASSERT(Process->NumberOfLockedPages > 0);
1543 InterlockedExchangeAddSizeT(&Process->NumberOfLockedPages,
1544 -(LONG_PTR)PageCount);
1545 }
1546
1547 //
1548 // Loop every page
1549 //
1550 LastPage = MdlPages + PageCount;
1551 do
1552 {
1553 //
1554 // Last page reached
1555 //
1556 if (*MdlPages == LIST_HEAD)
1557 {
1558 //
1559 // Were there no pages at all?
1560 //
1561 if (MdlPages == (PPFN_NUMBER)(Mdl + 1))
1562 {
1563 //
1564 // We're already done
1565 //
1566 Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
1567 return;
1568 }
1569
1570 //
1571 // Otherwise, stop here
1572 //
1573 LastPage = MdlPages;
1574 break;
1575 }
1576
1577 /* Save the PFN entry instead for the secondary loop */
1578 *MdlPages = (PFN_NUMBER)MiGetPfnEntry(*MdlPages);
1579 ASSERT(*MdlPages != 0);
1580 } while (++MdlPages < LastPage);
1581
1582 //
1583 // Reset pointer
1584 //
1585 MdlPages = (PPFN_NUMBER)(Mdl + 1);
1586
1587 //
1588 // Now grab the PFN lock for the actual unlock and dereference
1589 //
1590 OldIrql = MiAcquirePfnLock();
1591 do
1592 {
1593 /* Get the current entry and reference count */
1594 Pfn1 = (PMMPFN)*MdlPages;
1596 } while (++MdlPages < LastPage);
1597
1598 //
1599 // Release the lock
1600 //
1601 MiReleasePfnLock(OldIrql);
1602
1603 //
1604 // We're done
1605 //
1606 Mdl->MdlFlags &= ~MDL_PAGES_LOCKED;
1607}
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1622
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:834
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
struct _MMPFN * PMMPFN

Referenced by __attribute__(), _At_(), _Function_class_(), AcceptExReceiveComplete(), AfdCancelHandler(), CcMdlReadComplete2(), ClassAsynchronousCompletion(), ClasspFreeDeviceMdl(), ClasspSendSynchronousCompletion(), ClassSendDeviceIoControlSynchronous(), CommonForwardedIoCompletionRoutine(), DispTdiQueryInformationEx(), DispTdiQueryInformationExComplete(), DriverCleanup(), DriverIoControl(), ExpDeleteProfile(), Ext2DestroyMdl(), ExUnlockUserBuffer(), FatSingleNonAlignedSync(), FxRequestBase::FreeMdls(), HackSecureVirtualMemory(), HackUnsecureVirtualMemory(), IoCompletion(), IofCompleteRequest(), KsepWriteImportEntry(), LockRequest(), MiDoMappedCopy(), MmProbeAndLockPages(), Mx::MxUnlockPages(), nfs41_QueryDirectory(), NtfsIssueIoRuns(), NtStopProfile(), PortCompleteRequest(), read_data(), FxIoContext::ReleaseAndRestore(), FxUsbPipeTransferContext::ReleaseAndRestore(), SatisfySuperAccept(), scrub_chunk_raid56_stripe_run(), scrub_extent(), SpiSenseCompletionRoutine(), sync_read_phys(), TestCleanEverything(), UDFAsyncCompletionRoutine(), UnlockBuffers(), UnlockRequest(), VideoPortUnlockBuffer(), write_data_phys(), write_superblocks(), and FxIoContext::~FxIoContext().

◆ MmUnmapLockedPages()

VOID NTAPI MmUnmapLockedPages ( IN PVOID  BaseAddress,
IN PMDL  Mdl 
)

Definition at line 834 of file mdlsup.c.

836{
837 PVOID Base;
838 PFN_COUNT PageCount, ExtraPageCount;
839 PPFN_NUMBER MdlPages;
840 PMMPTE PointerPte;
841
842 //
843 // Sanity check
844 //
845 ASSERT(Mdl->ByteCount != 0);
846
847 //
848 // Check if this is a kernel request
849 //
851 {
852 //
853 // Get base and count information
854 //
855 Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
856 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
857
858 //
859 // Sanity checks
860 //
861 ASSERT((Mdl->MdlFlags & MDL_PARENT_MAPPED_SYSTEM_VA) == 0);
862 ASSERT(PageCount != 0);
864
865 //
866 // Get the PTE
867 //
868 PointerPte = MiAddressToPte(BaseAddress);
869
870 //
871 // This should be a resident system PTE
872 //
874 ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
875 ASSERT(PointerPte->u.Hard.Valid == 1);
876
877 //
878 // Check if the caller wants us to free advanced pages
879 //
880 if (Mdl->MdlFlags & MDL_FREE_EXTRA_PTES)
881 {
882 //
883 // Get the MDL page array
884 //
885 MdlPages = MmGetMdlPfnArray(Mdl);
886
887 /* Number of extra pages stored after the PFN array */
888 ExtraPageCount = (PFN_COUNT)*(MdlPages + PageCount);
889
890 //
891 // Do the math
892 //
893 PageCount += ExtraPageCount;
894 PointerPte -= ExtraPageCount;
896 ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
897
898 //
899 // Get the new base address
900 //
902 (ExtraPageCount << PAGE_SHIFT));
903 }
904
905 //
906 // Remove flags
907 //
908 Mdl->MdlFlags &= ~(MDL_MAPPED_TO_SYSTEM_VA |
911
912 //
913 // Release the system PTEs
914 //
915 MiReleaseSystemPtes(PointerPte, PageCount, SystemPteSpace);
916 }
917 else
918 {
920 }
921}
PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
Definition: syspte.c:22
PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
Definition: syspte.c:23
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
static VOID NTAPI MiUnmapLockedPagesInUserSpace(_In_ PVOID BaseAddress, _In_ PMDL Mdl)
Definition: mdlsup.c:292
#define MDL_FREE_EXTRA_PTES
Definition: mmtypes.h:27
#define MDL_PARENT_MAPPED_SYSTEM_VA
Definition: mmtypes.h:26

Referenced by CcZeroData(), ExpDeleteProfile(), free_buffer_head(), KsepWriteImportEntry(), MiDoMappedCopy(), MiReadFilePage(), MiReadPageFile(), MiWritePage(), MmMakeSegmentResident(), MmUnlockPages(), MmWriteToSwapPage(), nfs41_downcall(), NtStopProfile(), SatisfyPacketRecvRequest(), SendComplete(), TestCleanEverything(), TestMmAllocatePagesForMdl(), TryToSatisfyRecvRequestFromBuffer(), unmarshal_nfs41_dirquery(), unmarshal_nfs41_open(), and unmarshal_nfs41_rw().

◆ MmUnmapReservedMapping()

VOID NTAPI MmUnmapReservedMapping ( _In_ PVOID  BaseAddress,
_In_ ULONG  PoolTag,
_In_ PMDL  Mdl 
)

Definition at line 1744 of file mdlsup.c.

1748{
1749 PVOID Base;
1750 PFN_COUNT PageCount, ExtraPageCount;
1751 PPFN_NUMBER MdlPages;
1752 PMMPTE PointerPte;
1753 MMPTE TempPte;
1754
1755 // Sanity check
1756 ASSERT(Mdl->ByteCount != 0);
1758
1759 // Get base and count information
1760 Base = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
1761 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base, Mdl->ByteCount);
1762
1763 // Sanity checks
1764 ASSERT((Mdl->MdlFlags & MDL_PARENT_MAPPED_SYSTEM_VA) == 0);
1765 ASSERT(PageCount != 0);
1766 ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
1767
1768 // Get the first PTE we reserved
1769 PointerPte = MiAddressToPte(BaseAddress) - 2;
1770 ASSERT(!PointerPte[0].u.Hard.Valid &&
1771 !PointerPte[1].u.Hard.Valid);
1772
1773 // Verify that the pool tag matches
1774 TempPte.u.Long = PoolTag;
1775 TempPte.u.Hard.Valid = 0;
1776 if (PointerPte[1].u.Long != TempPte.u.Long)
1777 {
1778 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1779 PTE_UNMAPPING_ADDRESS_NOT_OWNED, /* Trying to unmap an address it does not own */
1781 PoolTag,
1782 PointerPte[1].u.Long);
1783 }
1784
1785 // We must have a size
1786 if (PointerPte[0].u.List.NextEntry < 3)
1787 {
1788 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1789 PTE_MAPPING_ADDRESS_EMPTY, /* Mapping apparently empty */
1791 PoolTag,
1793 }
1794
1795 // Skip our two helper PTEs
1796 PointerPte += 2;
1797
1798 // This should be a resident system PTE
1799 ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
1800 ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
1801 ASSERT(PointerPte->u.Hard.Valid == 1);
1802
1803 // TODO: check the MDL range makes sense with regard to the mapping range
1804 // TODO: check if any of them are already zero
1805 // TODO: check if any outside the MDL range are nonzero
1806 // TODO: find out what to do with extra PTEs
1807
1808 // Check if the caller wants us to free advanced pages
1809 if (Mdl->MdlFlags & MDL_FREE_EXTRA_PTES)
1810 {
1811 // Get the MDL page array
1812 MdlPages = MmGetMdlPfnArray(Mdl);
1813
1814 /* Number of extra pages stored after the PFN array */
1815 ExtraPageCount = MdlPages[PageCount];
1816
1817 // Do the math
1818 PageCount += ExtraPageCount;
1819 PointerPte -= ExtraPageCount;
1820 ASSERT(PointerPte >= MmSystemPtesStart[SystemPteSpace]);
1821 ASSERT(PointerPte <= MmSystemPtesEnd[SystemPteSpace]);
1822
1823 // Get the new base address
1825 (ExtraPageCount << PAGE_SHIFT));
1826 }
1827
1828 // Zero the PTEs
1829 RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
1830
1831 // Flush the TLB
1833
1834 // Remove flags
1835 Mdl->MdlFlags &= ~(MDL_MAPPED_TO_SYSTEM_VA |
1838}
#define PTE_UNMAPPING_ADDRESS_NOT_OWNED
Definition: miarm.h:168
#define PTE_MAPPING_ADDRESS_EMPTY
Definition: miarm.h:169

Referenced by AtaReqReleaseResources(), and TestMap().

Variable Documentation

◆ MiCacheOverride

ULONG MiCacheOverride[MiNotMapped+1]

Definition at line 24 of file mdlsup.c.

Referenced by MiMapLockedPagesInUserSpace().

◆ MmSystemLockPagesCount

◆ MmTrackLockedPages

BOOLEAN MmTrackLockedPages

Definition at line 21 of file mdlsup.c.

◆ MmTrackPtes

BOOLEAN MmTrackPtes

Definition at line 20 of file mdlsup.c.