00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "mi.h"
00023
00024
#undef MmIsRecursiveIoFault
00025
00026 PFN_NUMBER
MmSystemLockPagesCount;
00027
00028 extern ULONG
MmTotalSystemDriverPages;
00029
00030 BOOLEAN
00031
MmIsRecursiveIoFault(
00032 VOID
00033 );
00034
00035 PVOID
00036
MiAllocateContiguousMemory (
00037 IN SIZE_T NumberOfBytes,
00038 IN PFN_NUMBER LowestAcceptablePfn,
00039 IN PFN_NUMBER HighestAcceptablePfn,
00040 IN PFN_NUMBER BoundaryPfn,
00041 PVOID CallingAddress
00042 );
00043
00044 PVOID
00045
MiMapLockedPagesInUserSpace (
00046 IN
PMDL MemoryDescriptorList,
00047 IN PVOID StartingVa,
00048 IN MEMORY_CACHING_TYPE CacheType,
00049 IN PVOID BaseVa
00050 );
00051
00052
VOID
00053
MiUnmapLockedPagesInUserSpace (
00054 IN PVOID BaseAddress,
00055 IN
PMDL MemoryDescriptorList
00056 );
00057
00058 LOGICAL
00059
MiGetSystemPteAvailability (
00060 IN ULONG NumberOfPtes,
00061 IN
MM_PAGE_PRIORITY Priority
00062 );
00063
00064
VOID
00065
MiAddMdlTracker (
00066 IN
PMDL MemoryDescriptorList,
00067 IN PVOID CallingAddress,
00068 IN PVOID CallersCaller,
00069 IN PFN_NUMBER NumberOfPagesToLock,
00070 IN ULONG Who
00071 );
00072
00073 typedef struct _PTE_TRACKER {
00074 LIST_ENTRY
ListEntry;
00075 PMDL Mdl;
00076 PFN_NUMBER
Count;
00077 PVOID
SystemVa;
00078 PVOID
StartVa;
00079 ULONG
Offset;
00080 ULONG
Length;
00081 ULONG_PTR
Page;
00082 PVOID
CallingAddress;
00083 PVOID
CallersCaller;
00084 PVOID
PteAddress;
00085 }
PTE_TRACKER, *
PPTE_TRACKER;
00086
00087 typedef struct _SYSPTES_HEADER {
00088 LIST_ENTRY
ListHead;
00089 PFN_NUMBER
Count;
00090 }
SYSPTES_HEADER, *
PSYSPTES_HEADER;
00091
00092 LOGICAL
MmTrackPtes =
FALSE;
00093 BOOLEAN
MiTrackPtesAborted =
FALSE;
00094 SYSPTES_HEADER MiPteHeader;
00095 LIST_ENTRY
MiDeadPteTrackerListHead;
00096 KSPIN_LOCK
MiPteTrackerLock;
00097
00098 LOCK_HEADER MmLockedPagesHead;
00099 BOOLEAN
MiTrackingAborted =
FALSE;
00100
00101
VOID
00102
MiInsertPteTracker (
00103 IN PVOID PoolBlock,
00104 IN
PMDL MemoryDescriptorList,
00105 IN PFN_NUMBER NumberOfPtes,
00106 IN PVOID MyCaller,
00107 IN PVOID MyCallersCaller
00108 );
00109
00110 PVOID
00111
MiRemovePteTracker (
00112 IN
PMDL MemoryDescriptorList,
00113 IN PVOID PteAddress,
00114 IN PFN_NUMBER NumberOfPtes
00115 );
00116
00117
VOID
00118
MiReleaseDeadPteTrackers (
00119 VOID
00120 );
00121
00122
VOID
00123
MiInsertDeadPteTrackingBlock (
00124 IN PVOID PoolBlock
00125 );
00126
00127
00128
00129
VOID
00130
MiProtectFreeNonPagedPool (
00131 IN PVOID VirtualAddress,
00132 IN ULONG SizeInPages
00133 );
00134
00135 LOGICAL
00136
MiUnProtectFreeNonPagedPool (
00137 IN PVOID VirtualAddress,
00138 IN ULONG SizeInPages
00139 );
00140
00141 extern LOGICAL
MiNoLowMemory;
00142
00143 PVOID
00144
MiAllocateLowMemory (
00145 IN SIZE_T NumberOfBytes,
00146 IN PFN_NUMBER LowestAcceptablePfn,
00147 IN PFN_NUMBER HighestAcceptablePfn,
00148 IN PFN_NUMBER BoundaryPfn,
00149 IN PVOID CallingAddress,
00150 IN ULONG Tag
00151 );
00152
00153 LOGICAL
00154
MiFreeLowMemory (
00155 IN PVOID BaseAddress,
00156 IN ULONG Tag
00157 );
00158
00159
#if DBG
00160
ULONG MiPrintLockedPages;
00161
00162
VOID
00163 MiVerifyLockedPageCharges (
00164 VOID
00165 );
00166
#endif
00167
00168
#ifdef ALLOC_PRAGMA
00169
#pragma alloc_text(INIT, MmAllocateIndependentPages)
00170
#pragma alloc_text(INIT, MmSetPageProtection)
00171
#pragma alloc_text(INIT, MiInitializeIoTrackers)
00172
00173
#pragma alloc_text(PAGE, MmLockPagableDataSection)
00174
#pragma alloc_text(PAGE, MiLookupDataTableEntry)
00175
#pragma alloc_text(PAGE, MiMapLockedPagesInUserSpace)
00176
#pragma alloc_text(PAGE, MmSetBankedSection)
00177
#pragma alloc_text(PAGE, MmProbeAndLockProcessPages)
00178
#pragma alloc_text(PAGE, MmProbeAndLockSelectedPages)
00179
#pragma alloc_text(PAGE, MmMapVideoDisplay)
00180
#pragma alloc_text(PAGE, MmUnmapVideoDisplay)
00181
#pragma alloc_text(PAGE, MmGetSectionRange)
00182
#pragma alloc_text(PAGE, MiMapSinglePage)
00183
#pragma alloc_text(PAGE, MiUnmapSinglePage)
00184
00185
#pragma alloc_text(PAGELK, MiUnmapLockedPagesInUserSpace)
00186
#pragma alloc_text(PAGELK, MmAllocateNonCachedMemory)
00187
#pragma alloc_text(PAGELK, MmFreeNonCachedMemory)
00188
#pragma alloc_text(PAGELK, MmAllocatePagesForMdl)
00189
#pragma alloc_text(PAGELK, MmFreePagesFromMdl)
00190
#pragma alloc_text(PAGELK, MmLockPagedPool)
00191
#pragma alloc_text(PAGELK, MmUnlockPagedPool)
00192
#pragma alloc_text(PAGELK, MmGatherMemoryForHibernate)
00193
#pragma alloc_text(PAGELK, MmReturnMemoryForHibernate)
00194
#pragma alloc_text(PAGELK, MmReleaseDumpAddresses)
00195
#pragma alloc_text(PAGELK, MmEnablePAT)
00196
00197
#pragma alloc_text(PAGEVRFY, MmIsSystemAddressLocked)
00198
00199
#pragma alloc_text(PAGEHYDRA, MmDispatchWin32Callout)
00200
#endif
00201
00202 extern POOL_DESCRIPTOR NonPagedPoolDescriptor;
00203
00204 PFN_NUMBER
MmMdlPagesAllocated;
00205
00206 KEVENT MmCollidedLockEvent;
00207 ULONG
MmCollidedLockWait;
00208
00209 SIZE_T
MmLockedCode;
00210
00211 BOOLEAN
MiWriteCombiningPtes =
FALSE;
00212
00213
#ifdef LARGE_PAGES
00214
ULONG MmLargeVideoMapped;
00215
#endif
00216
00217
#if DBG
00218
ULONG MiPrintAwe;
00219
#endif
00220
00221 #define MI_PROBE_RAISE_SIZE 10
00222
00223 ULONG
MiProbeRaises[
MI_PROBE_RAISE_SIZE];
00224
00225 #define MI_INSTRUMENT_PROBE_RAISES(i) \
00226
ASSERT (i < MI_PROBE_RAISE_SIZE); \
00227
MiProbeRaises[i] += 1;
00228
00229
00230
00231
00232
00233
00234 ULONG
MmReferenceCountCheck = 2500;
00235
00236
00237
VOID
00238 MmProbeAndLockPages (
00239 IN OUT
PMDL MemoryDescriptorList,
00240 IN KPROCESSOR_MODE AccessMode,
00241 IN LOCK_OPERATION Operation
00242 )
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 {
00278 PPFN_NUMBER Page;
00279
MMPTE PteContents;
00280
PMMPTE PointerPte;
00281
PMMPTE PointerPde;
00282
PMMPTE PointerPpe;
00283 PVOID Va;
00284 PVOID EndVa;
00285 PVOID AlignedVa;
00286
PMMPFN Pfn1;
00287 PFN_NUMBER PageFrameIndex;
00288
PEPROCESS CurrentProcess;
00289 KIRQL OldIrql;
00290 PFN_NUMBER NumberOfPagesToLock;
00291 PFN_NUMBER NumberOfPagesSpanned;
00292
NTSTATUS status;
00293
NTSTATUS ProbeStatus;
00294
PETHREAD Thread;
00295 ULONG SavedState;
00296 LOGICAL AddressIsPhysical;
00297 PLIST_ENTRY NextEntry;
00298
PMI_PHYSICAL_VIEW PhysicalView;
00299 PCHAR StartVa;
00300 PVOID CallingAddress;
00301 PVOID CallersCaller;
00302
00303
#if !defined (_X86_)
00304
CallingAddress = (PVOID)_ReturnAddress();
00305 CallersCaller = (PVOID)0;
00306
#endif
00307
00308
#if DBG
00309
if (MiPrintLockedPages != 0) {
00310 MiVerifyLockedPageCharges ();
00311 }
00312
#endif
00313
00314
ASSERT (MemoryDescriptorList->ByteCount != 0);
00315
ASSERT (((ULONG)MemoryDescriptorList->ByteOffset & ~(
PAGE_SIZE - 1)) == 0);
00316
00317 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
00318
00319
ASSERT (((ULONG_PTR)MemoryDescriptorList->StartVa & (
PAGE_SIZE - 1)) == 0);
00320 AlignedVa = (PVOID)MemoryDescriptorList->StartVa;
00321
00322
ASSERT ((MemoryDescriptorList->MdlFlags & (
00323
MDL_PAGES_LOCKED |
00324
MDL_MAPPED_TO_SYSTEM_VA |
00325
MDL_SOURCE_IS_NONPAGED_POOL |
00326
MDL_PARTIAL |
00327
MDL_IO_SPACE)) == 0);
00328
00329 Va = (PCHAR)AlignedVa + MemoryDescriptorList->ByteOffset;
00330 StartVa = Va;
00331
00332 PointerPte =
MiGetPteAddress (Va);
00333
00334
00335
00336
00337
00338
00339
00340 EndVa = (PVOID)((PCHAR)Va + MemoryDescriptorList->ByteCount);
00341
00342
if ((AccessMode !=
KernelMode) &&
00343 ((EndVa > (PVOID)MM_USER_PROBE_ADDRESS) || (Va >= EndVa))) {
00344 *Page =
MM_EMPTY_LIST;
00345
MI_INSTRUMENT_PROBE_RAISES(0);
00346
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
00347
return;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 MemoryDescriptorList->Process = (
PEPROCESS)
NULL;
00360
00361 Thread =
PsGetCurrentThread ();
00362
00363
if (!
MI_IS_PHYSICAL_ADDRESS(Va)) {
00364
00365 AddressIsPhysical =
FALSE;
00366 ProbeStatus = STATUS_SUCCESS;
00367
00368 NumberOfPagesToLock =
COMPUTE_PAGES_SPANNED (Va,
00369 MemoryDescriptorList->ByteCount);
00370
00371
ASSERT (NumberOfPagesToLock != 0);
00372
00373 NumberOfPagesSpanned = NumberOfPagesToLock;
00374
00375 PointerPpe =
MiGetPpeAddress (Va);
00376 PointerPde =
MiGetPdeAddress (Va);
00377
00378
MmSavePageFaultReadAhead (Thread, &SavedState);
00379
MmSetPageFaultReadAhead (Thread, (ULONG)(NumberOfPagesToLock - 1));
00380
00381
try {
00382
00383
do {
00384
00385 *Page =
MM_EMPTY_LIST;
00386
00387
00388
00389
00390
00391 *(
volatile CHAR *)Va;
00392
00393
if ((Operation !=
IoReadAccess) &&
00394 (Va <= MM_HIGHEST_USER_ADDRESS)) {
00395
00396
00397
00398
00399
00400
ProbeForWriteChar ((PCHAR)Va);
00401 }
00402
00403 NumberOfPagesToLock -= 1;
00404
00405
MmSetPageFaultReadAhead (Thread, (ULONG)(NumberOfPagesToLock - 1));
00406 Va = (PVOID)(((ULONG_PTR)(PCHAR)Va +
PAGE_SIZE) & ~(
PAGE_SIZE - 1));
00407 Page += 1;
00408 }
while (Va < EndVa);
00409
00410
ASSERT (NumberOfPagesToLock == 0);
00411
00412 } except (
EXCEPTION_EXECUTE_HANDLER) {
00413 ProbeStatus = GetExceptionCode();
00414 }
00415
00416
00417
00418
00419
00420
00421
MmResetPageFaultReadAhead (Thread, SavedState);
00422
00423
if (ProbeStatus != STATUS_SUCCESS) {
00424
MI_INSTRUMENT_PROBE_RAISES(1);
00425
ExRaiseStatus (ProbeStatus);
00426
return;
00427 }
00428 }
00429
else {
00430 AddressIsPhysical =
TRUE;
00431 *Page =
MM_EMPTY_LIST;
00432 }
00433
00434 Va = AlignedVa;
00435 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
00436
00437
00438
00439
00440
00441
if (Operation !=
IoReadAccess) {
00442 MemoryDescriptorList->MdlFlags |=
MDL_WRITE_OPERATION;
00443 }
else {
00444 MemoryDescriptorList->MdlFlags &= ~(
MDL_WRITE_OPERATION);
00445 }
00446
00447
00448
00449
00450
00451
LOCK_PFN2 (OldIrql);
00452
00453
if (Va <= MM_HIGHEST_USER_ADDRESS) {
00454
00455
00456
00457
00458
00459
00460
ASSERT (NumberOfPagesSpanned != 0);
00461
00462 CurrentProcess =
PsGetCurrentProcess ();
00463
00464
00465
00466
00467
00468
00469 NextEntry = CurrentProcess->
PhysicalVadList.Flink;
00470
while (NextEntry != &CurrentProcess->
PhysicalVadList) {
00471
00472 PhysicalView = CONTAINING_RECORD(NextEntry,
00473
MI_PHYSICAL_VIEW,
00474 ListEntry);
00475
00476
if ((PhysicalView->
Vad->
u.VadFlags.UserPhysicalPages == 0) &&
00477 (PhysicalView->
Vad->
u.VadFlags.PhysicalMapping == 0)) {
00478 NextEntry = NextEntry->Flink;
00479
continue;
00480 }
00481
00482
if (StartVa < PhysicalView->
StartVa) {
00483
00484
if ((PCHAR)EndVa - 1 >= PhysicalView->
StartVa) {
00485
00486
00487
00488
00489
00490
00491
UNLOCK_PFN2 (OldIrql);
00492
MI_INSTRUMENT_PROBE_RAISES(2);
00493
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
00494
return;
00495 }
00496
00497 NextEntry = NextEntry->Flink;
00498
continue;
00499 }
00500
00501
if (StartVa <= PhysicalView->
EndVa) {
00502
00503
00504
00505
00506
00507
if ((PCHAR)EndVa - 1 > PhysicalView->
EndVa) {
00508
00509
00510
00511
00512
00513
UNLOCK_PFN2 (OldIrql);
00514
MI_INSTRUMENT_PROBE_RAISES(3);
00515
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
00516
return;
00517 }
00518
00519
if (PhysicalView->
Vad->
u.VadFlags.UserPhysicalPages == 1) {
00520
00521
00522
00523
00524
00525
00526
00527 NextEntry = NextEntry->Flink;
00528
continue;
00529 }
00530
00531
00532
00533
00534
00535
if (Operation !=
IoReadAccess) {
00536
00537
00538
00539
00540
00541
00542
if ((PhysicalView->
Vad->
u.VadFlags.Protection &
MM_READWRITE) == 0) {
00543
UNLOCK_PFN2 (OldIrql);
00544
MI_INSTRUMENT_PROBE_RAISES(4);
00545
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
00546
return;
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557 MemoryDescriptorList->MdlFlags |= (
MDL_PHYSICAL_VIEW |
MDL_PAGES_LOCKED);
00558 MemoryDescriptorList->Process = CurrentProcess;
00559
00560
do {
00561 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
00562 *Page = PageFrameIndex;
00563 Page += 1;
00564 PointerPte += 1;
00565 Va = (PVOID)((PCHAR)Va +
PAGE_SIZE);
00566 }
while (Va < EndVa);
00567
00568
UNLOCK_PFN2 (OldIrql);
00569
return;
00570 }
00571 NextEntry = NextEntry->Flink;
00572 }
00573
00574 CurrentProcess->
NumberOfLockedPages += NumberOfPagesSpanned;
00575
00576 MemoryDescriptorList->Process = CurrentProcess;
00577 }
00578
00579 MemoryDescriptorList->MdlFlags |=
MDL_PAGES_LOCKED;
00580
00581
do {
00582
00583
if (AddressIsPhysical ==
TRUE) {
00584
00585
00586
00587
00588
00589
00590 PageFrameIndex =
MI_CONVERT_PHYSICAL_TO_PFN (Va);
00591
00592 }
else {
00593
00594
#if defined (_WIN64)
00595
while ((PointerPpe->
u.Hard.Valid == 0) ||
00596 (PointerPde->
u.Hard.Valid == 0) ||
00597 (PointerPte->
u.Hard.Valid == 0))
00598
#else
00599
while ((PointerPde->
u.Hard.Valid == 0) ||
00600 (PointerPte->
u.Hard.Valid == 0))
00601
#endif
00602
{
00603
00604
00605
00606
00607
00608
00609
UNLOCK_PFN2 (OldIrql);
00610
00611
MmSetPageFaultReadAhead (Thread, 0);
00612
00613 status =
MmAccessFault (
FALSE, Va,
KernelMode, (PVOID)0);
00614
00615
MmResetPageFaultReadAhead (Thread, SavedState);
00616
00617
if (!
NT_SUCCESS(status)) {
00618
00619
00620
00621
00622
00623
00624
failure:
00625
if (
MmTrackLockedPages ==
TRUE) {
00626
00627
00628
00629
00630
00631
00632 ULONG PagesLocked;
00633
00634 PagesLocked =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartVa,
00635 MemoryDescriptorList->ByteCount);
00636
00637
#if defined (_X86_)
00638
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
00639
#endif
00640
MiAddMdlTracker (MemoryDescriptorList,
00641 CallingAddress,
00642 CallersCaller,
00643 PagesLocked,
00644 0);
00645 }
00646
00647
MmUnlockPages (MemoryDescriptorList);
00648
00649
00650
00651
00652
00653
MI_INSTRUMENT_PROBE_RAISES(7);
00654
ExRaiseStatus (status);
00655
return;
00656 }
00657
00658
LOCK_PFN2 (OldIrql);
00659 }
00660
00661 PteContents = *PointerPte;
00662
ASSERT (PteContents.
u.Hard.Valid == 1);
00663
00664
if (Va <= MM_HIGHEST_USER_ADDRESS) {
00665
if (Operation !=
IoReadAccess) {
00666
00667
if ((PteContents.
u.Long &
MM_PTE_WRITE_MASK) == 0) {
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
#if DBG
00679
DbgPrint (
"MmProbeAndLockPages: PTE %p %p changed\n",
00680 PointerPte,
00681 PteContents.
u.Long);
00682
ASSERT (
FALSE);
00683
#endif
00684
00685
UNLOCK_PFN2 (OldIrql);
00686 status = STATUS_ACCESS_VIOLATION;
00687
goto failure;
00688 }
00689 }
00690 }
00691
00692 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
00693 }
00694
00695
if (PageFrameIndex >
MmHighestPhysicalPage) {
00696
00697
00698
00699
00700
00701
00702 MemoryDescriptorList->MdlFlags |=
MDL_IO_SPACE;
00703
00704 }
else {
00705
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_IO_SPACE) == 0);
00706
00707 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
00708
00709
#if PFN_CONSISTENCY
00710
ASSERT(Pfn1->
u3.e1.PageTablePage == 0);
00711
#endif
00712
00713
00714
00715
00716
00717
00718
if (Pfn1->
u3.e2.ReferenceCount >=
MmReferenceCountCheck) {
00719
UNLOCK_PFN2 (OldIrql);
00720
ASSERT (
FALSE);
00721 status = STATUS_WORKING_SET_QUOTA;
00722
goto failure;
00723 }
00724
00725
00726
00727
00728
00729
if (
MI_NONPAGABLE_MEMORY_AVAILABLE() <= 0) {
00730
00731
00732
00733
00734
00735
00736
if ((Va > MM_HIGHEST_USER_ADDRESS) &&
00737 (!
MI_IS_SYSTEM_CACHE_ADDRESS(Va))) {
00738
MI_INSTRUMENT_PROBE_RAISES(8);
00739
goto ok;
00740 }
00741
00742
MI_INSTRUMENT_PROBE_RAISES(5);
00743
UNLOCK_PFN2 (OldIrql);
00744 status = STATUS_WORKING_SET_QUOTA;
00745
goto failure;
00746 }
00747
00748
00749
00750
00751
00752
if (
MmSystemLockPagesCount + 1 >=
MmLockPagesLimit) {
00753
00754
00755
00756
00757
00758
00759
if ((Va > MM_HIGHEST_USER_ADDRESS) &&
00760 (!
MI_IS_SYSTEM_CACHE_ADDRESS(Va))) {
00761
MI_INSTRUMENT_PROBE_RAISES(9);
00762
goto ok;
00763 }
00764
00765
MI_INSTRUMENT_PROBE_RAISES(6);
00766
UNLOCK_PFN2 (OldIrql);
00767 status = STATUS_WORKING_SET_QUOTA;
00768
goto failure;
00769 }
00770
00771 ok:
00772
MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 0);
00773
00774 Pfn1->
u3.e2.ReferenceCount += 1;
00775 }
00776
00777 *Page = PageFrameIndex;
00778
00779 Page += 1;
00780 PointerPte += 1;
00781
if (
MiIsPteOnPdeBoundary(PointerPte)) {
00782 PointerPde += 1;
00783
if (
MiIsPteOnPpeBoundary(PointerPte)) {
00784 PointerPpe += 1;
00785 }
00786 }
00787
00788 Va = (PVOID)((PCHAR)Va +
PAGE_SIZE);
00789 }
while (Va < EndVa);
00790
00791
UNLOCK_PFN2 (OldIrql);
00792
00793
if ((
MmTrackLockedPages ==
TRUE) && (AlignedVa <= MM_HIGHEST_USER_ADDRESS)) {
00794
00795
ASSERT (NumberOfPagesSpanned != 0);
00796
00797
#if defined (_X86_)
00798
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
00799
#endif
00800
00801
MiAddMdlTracker (MemoryDescriptorList,
00802 CallingAddress,
00803 CallersCaller,
00804 NumberOfPagesSpanned,
00805 1);
00806 }
00807
00808
return;
00809 }
00810
00811
NTKERNELAPI
00812
VOID
00813 MmProbeAndLockProcessPages (
00814 IN OUT
PMDL MemoryDescriptorList,
00815 IN
PEPROCESS Process,
00816 IN KPROCESSOR_MODE AccessMode,
00817 IN LOCK_OPERATION Operation
00818 )
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 {
00847 LOGICAL Attached;
00848
NTSTATUS Status;
00849
00850 Attached =
FALSE;
00851
Status = STATUS_SUCCESS;
00852
00853
if (Process !=
PsGetCurrentProcess ()) {
00854
KeAttachProcess (&Process->Pcb);
00855 Attached =
TRUE;
00856 }
00857
00858
try {
00859
00860
MmProbeAndLockPages (MemoryDescriptorList,
00861 AccessMode,
00862 Operation);
00863
00864 } except (
EXCEPTION_EXECUTE_HANDLER) {
00865
Status = GetExceptionCode();
00866 }
00867
00868
if (Attached) {
00869
KeDetachProcess();
00870 }
00871
00872
if (
Status != STATUS_SUCCESS) {
00873
ExRaiseStatus (
Status);
00874 }
00875
return;
00876 }
00877
00878
VOID
00879 MiAddMdlTracker (
00880 IN
PMDL MemoryDescriptorList,
00881 IN PVOID CallingAddress,
00882 IN PVOID CallersCaller,
00883 IN PFN_NUMBER NumberOfPagesToLock,
00884 IN ULONG Who
00885 )
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 {
00919 KIRQL OldIrql;
00920
PEPROCESS Process;
00921
PLOCK_HEADER LockedPagesHeader;
00922
PLOCK_TRACKER Tracker;
00923
PLOCK_TRACKER P;
00924 PLIST_ENTRY NextEntry;
00925
00926
ASSERT (
MmTrackLockedPages ==
TRUE);
00927
00928 Process = MemoryDescriptorList->Process;
00929
00930
if (Process ==
NULL) {
00931
return;
00932 }
00933
00934 LockedPagesHeader = Process->
LockedPagesList;
00935
00936
if (LockedPagesHeader ==
NULL) {
00937
return;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
if (
MiTrackingAborted ==
TRUE) {
00948
return;
00949 }
00950
00951 Tracker =
ExAllocatePoolWithTag (
NonPagedPool,
00952
sizeof (
LOCK_TRACKER),
00953 'kLmM');
00954
00955
if (Tracker ==
NULL) {
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
MiTrackingAborted =
TRUE;
00966
00967
return;
00968 }
00969
00970 Tracker->
Mdl = MemoryDescriptorList;
00971 Tracker->
Count = NumberOfPagesToLock;
00972 Tracker->
StartVa = MemoryDescriptorList->StartVa;
00973 Tracker->
Offset = MemoryDescriptorList->ByteOffset;
00974 Tracker->
Length = MemoryDescriptorList->ByteCount;
00975 Tracker->
Page = *(PPFN_NUMBER)(MemoryDescriptorList + 1);
00976
00977 Tracker->
CallingAddress = CallingAddress;
00978 Tracker->
CallersCaller = CallersCaller;
00979
00980 Tracker->
Who = Who;
00981 Tracker->
Process = Process;
00982
00983
LOCK_PFN2 (OldIrql);
00984
00985
00986
00987
00988
00989
00990 NextEntry = LockedPagesHeader->
ListHead.Flink;
00991
while (NextEntry != &LockedPagesHeader->
ListHead) {
00992
00993 P = CONTAINING_RECORD (NextEntry,
00994
LOCK_TRACKER,
00995 ListEntry);
00996
00997
if (P->
Mdl == MemoryDescriptorList) {
00998
KeBugCheckEx (LOCKED_PAGES_TRACKER_CORRUPTION,
00999 0x1,
01000 (ULONG_PTR)P,
01001 (ULONG_PTR)MemoryDescriptorList,
01002 (ULONG_PTR)
MmLockedPagesHead.
Count);
01003 }
01004 NextEntry = NextEntry->Flink;
01005 }
01006
01007 InsertHeadList (&LockedPagesHeader->
ListHead, &Tracker->
ListEntry);
01008 LockedPagesHeader->
Count += NumberOfPagesToLock;
01009
01010
01011
01012
01013
01014
01015 NextEntry =
MmLockedPagesHead.
ListHead.Flink;
01016
while (NextEntry != &
MmLockedPagesHead.
ListHead) {
01017
01018 P = CONTAINING_RECORD(NextEntry,
01019
LOCK_TRACKER,
01020 GlobalListEntry);
01021
01022
if (P->
Mdl == MemoryDescriptorList) {
01023
KeBugCheckEx (LOCKED_PAGES_TRACKER_CORRUPTION,
01024 0x2,
01025 (ULONG_PTR)P,
01026 (ULONG_PTR)MemoryDescriptorList,
01027 (ULONG_PTR)
MmLockedPagesHead.
Count);
01028 }
01029
01030 NextEntry = NextEntry->Flink;
01031 }
01032
01033 InsertHeadList (&
MmLockedPagesHead.
ListHead,
01034 &Tracker->
GlobalListEntry);
01035
MmLockedPagesHead.
Count += NumberOfPagesToLock;
01036
01037
UNLOCK_PFN2 (OldIrql);
01038 }
01039
01040 LOGICAL
01041 MiFreeMdlTracker (
01042 IN OUT
PMDL MemoryDescriptorList,
01043 IN PFN_NUMBER NumberOfPages
01044 )
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 {
01072 KIRQL OldIrql;
01073
PLOCK_TRACKER Tracker;
01074 PLIST_ENTRY NextEntry;
01075
PLOCK_HEADER LockedPagesHeader;
01076 PPFN_NUMBER Page;
01077
PLOCK_TRACKER Found;
01078 PVOID PoolToFree;
01079
01080
ASSERT (MemoryDescriptorList->Process !=
NULL);
01081
01082 LockedPagesHeader = (
PLOCK_HEADER)MemoryDescriptorList->Process->LockedPagesList;
01083
01084
if (LockedPagesHeader ==
NULL) {
01085
return TRUE;
01086 }
01087
01088 Found =
NULL;
01089 Page = (PPFN_NUMBER) (MemoryDescriptorList + 1);
01090
01091
LOCK_PFN2 (OldIrql);
01092
01093 NextEntry = LockedPagesHeader->
ListHead.Flink;
01094
while (NextEntry != &LockedPagesHeader->
ListHead) {
01095
01096 Tracker = CONTAINING_RECORD (NextEntry,
01097
LOCK_TRACKER,
01098 ListEntry);
01099
01100
if (MemoryDescriptorList == Tracker->
Mdl) {
01101
01102
if (Found !=
NULL) {
01103
KeBugCheckEx (LOCKED_PAGES_TRACKER_CORRUPTION,
01104 0x3,
01105 (ULONG_PTR)Found,
01106 (ULONG_PTR)Tracker,
01107 (ULONG_PTR)MemoryDescriptorList);
01108 }
01109
01110
ASSERT (Tracker->
Page == *Page);
01111
ASSERT (NumberOfPages == Tracker->
Count);
01112 Tracker->
Count = (PFN_NUMBER)-1;
01113 RemoveEntryList (NextEntry);
01114 LockedPagesHeader->
Count -= NumberOfPages;
01115
01116 RemoveEntryList (&Tracker->
GlobalListEntry);
01117
MmLockedPagesHead.
Count -= NumberOfPages;
01118
01119 Found = Tracker;
01120 PoolToFree = (PVOID)NextEntry;
01121 }
01122 NextEntry = Tracker->
ListEntry.Flink;
01123 }
01124
01125
UNLOCK_PFN2 (OldIrql);
01126
01127
if (Found ==
NULL) {
01128
01129
01130
01131
01132
01133
if (
MiTrackingAborted ==
TRUE) {
01134
return TRUE;
01135 }
01136
01137
KeBugCheckEx (PROCESS_HAS_LOCKED_PAGES,
01138 1,
01139 (ULONG_PTR)MemoryDescriptorList,
01140 MemoryDescriptorList->Process->NumberOfLockedPages,
01141 (ULONG_PTR)MemoryDescriptorList->Process->LockedPagesList);
01142 }
01143
01144
ExFreePool (PoolToFree);
01145
01146
return TRUE;
01147 }
01148
01149
01150
NTKERNELAPI
01151
VOID
01152 MmProbeAndLockSelectedPages (
01153 IN OUT
PMDL MemoryDescriptorList,
01154 IN PFILE_SEGMENT_ELEMENT SegmentArray,
01155 IN KPROCESSOR_MODE AccessMode,
01156 IN LOCK_OPERATION Operation
01157 )
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 {
01194
PMDL TempMdl;
01195 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + 1];
01196 PPFN_NUMBER Page;
01197 PFILE_SEGMENT_ELEMENT LastSegment;
01198 PVOID CallingAddress;
01199 PVOID CallersCaller;
01200 ULONG NumberOfPagesToLock;
01201
01202
PAGED_CODE();
01203
01204
#if !defined (_X86_)
01205
CallingAddress = (PVOID)_ReturnAddress();
01206 CallersCaller = (PVOID)0;
01207
#endif
01208
01209 NumberOfPagesToLock = 0;
01210
01211
ASSERT (MemoryDescriptorList->ByteCount != 0);
01212
ASSERT (((ULONG_PTR)MemoryDescriptorList->ByteOffset & ~(
PAGE_SIZE - 1)) == 0);
01213
01214
ASSERT ((MemoryDescriptorList->MdlFlags & (
01215
MDL_PAGES_LOCKED |
01216
MDL_MAPPED_TO_SYSTEM_VA |
01217
MDL_SOURCE_IS_NONPAGED_POOL |
01218
MDL_PARTIAL |
01219
MDL_IO_SPACE)) == 0);
01220
01221
01222
01223
01224
01225 TempMdl = (
PMDL) &MdlHack;
01226
01227
MmInitializeMdl( TempMdl, SegmentArray->Buffer,
PAGE_SIZE );
01228
01229 Page = (PPFN_NUMBER) (MemoryDescriptorList + 1);
01230
01231
01232
01233
01234
01235 LastSegment = SegmentArray +
01236
BYTES_TO_PAGES(MemoryDescriptorList->ByteCount);
01237
01238
ASSERT(SegmentArray < LastSegment);
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 SegmentArray += 1;
01254
MmProbeAndLockPages( TempMdl, AccessMode, Operation );
01255
01256
if (
MmTrackLockedPages ==
TRUE) {
01257
01258
01259
01260
01261
01262
01263
if (
MiFreeMdlTracker (TempMdl, 1) ==
TRUE) {
01264 NumberOfPagesToLock += 1;
01265 }
01266 }
01267
01268 *Page++ = *((PPFN_NUMBER) (TempMdl + 1));
01269
01270
01271
01272
01273
01274 MemoryDescriptorList->MdlFlags |= TempMdl->
MdlFlags;
01275 MemoryDescriptorList->Process = TempMdl->
Process;
01276
01277
try {
01278
01279
while (SegmentArray < LastSegment) {
01280
01281
01282
01283
01284
01285
01286
01287 TempMdl->
StartVa = (PVOID)(ULONG_PTR)SegmentArray->Buffer;
01288 TempMdl->
MdlFlags = 0;
01289
01290 SegmentArray += 1;
01291
MmProbeAndLockPages( TempMdl, AccessMode, Operation );
01292
01293
01294
if (
MmTrackLockedPages ==
TRUE) {
01295
01296
01297
01298
01299
01300
01301
if (
MiFreeMdlTracker (TempMdl, 1) ==
TRUE) {
01302 NumberOfPagesToLock += 1;
01303 }
01304 }
01305
01306 *Page++ = *((PPFN_NUMBER) (TempMdl + 1));
01307 }
01308 } finally {
01309
01310
if (abnormal_termination()) {
01311
01312
01313
01314
01315
01316
01317 MemoryDescriptorList->ByteCount =
01318 (ULONG) (Page - (PPFN_NUMBER) (MemoryDescriptorList + 1)) <<
PAGE_SHIFT;
01319
01320
if (
MmTrackLockedPages ==
TRUE) {
01321
#if defined (_X86_)
01322
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
01323
#endif
01324
MiAddMdlTracker (MemoryDescriptorList,
01325 CallingAddress,
01326 CallersCaller,
01327 NumberOfPagesToLock,
01328 2);
01329 }
01330
01331
MmUnlockPages( MemoryDescriptorList );
01332 }
01333
else if (
MmTrackLockedPages ==
TRUE) {
01334
#if defined (_X86_)
01335
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
01336
#endif
01337
MiAddMdlTracker (MemoryDescriptorList,
01338 CallingAddress,
01339 CallersCaller,
01340 NumberOfPagesToLock,
01341 3);
01342 }
01343 }
01344 }
01345
01346
VOID
01347 MmUnlockPages (
01348 IN OUT
PMDL MemoryDescriptorList
01349 )
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375 {
01376 PFN_NUMBER NumberOfPages;
01377 PPFN_NUMBER Page;
01378 PVOID StartingVa;
01379 KIRQL OldIrql;
01380
PMMPFN Pfn1;
01381 LOGICAL
Unlock;
01382
01383
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_PAGES_LOCKED) != 0);
01384
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_SOURCE_IS_NONPAGED_POOL) == 0);
01385
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_PARTIAL) == 0);
01386
ASSERT (MemoryDescriptorList->ByteCount != 0);
01387
01388
if (MemoryDescriptorList->MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
01389
01390
01391
01392
01393
01394
MmUnmapLockedPages (MemoryDescriptorList->MappedSystemVa,
01395 MemoryDescriptorList);
01396 }
01397
01398 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
01399
Unlock =
TRUE;
01400 StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
01401 MemoryDescriptorList->ByteOffset);
01402
01403 NumberOfPages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartingVa,
01404 MemoryDescriptorList->ByteCount);
01405
01406
if (
MmTrackLockedPages ==
TRUE) {
01407
if ((MemoryDescriptorList->Process !=
NULL) &&
01408 (
Unlock ==
TRUE) &&
01409 ((MemoryDescriptorList->MdlFlags &
MDL_PHYSICAL_VIEW) == 0)) {
01410
MiFreeMdlTracker (MemoryDescriptorList, NumberOfPages);
01411 }
01412 }
01413
01414
ASSERT (NumberOfPages != 0);
01415
01416
LOCK_PFN2 (OldIrql);
01417
01418
if (
MmLockedPagesHead.
ListHead.Flink != 0) {
01419
01420
PLOCK_TRACKER P;
01421 PLIST_ENTRY NextEntry;
01422
01423 NextEntry =
MmLockedPagesHead.
ListHead.Flink;
01424
while (NextEntry != &
MmLockedPagesHead.
ListHead) {
01425
01426 P = CONTAINING_RECORD(NextEntry,
01427
LOCK_TRACKER,
01428 GlobalListEntry);
01429
01430
if (P->
Mdl == MemoryDescriptorList) {
01431
KeBugCheckEx (LOCKED_PAGES_TRACKER_CORRUPTION,
01432 0x4,
01433 (ULONG_PTR)P,
01434 (ULONG_PTR)MemoryDescriptorList,
01435 0);
01436 }
01437
01438 NextEntry = NextEntry->Flink;
01439 }
01440 }
01441
01442
if ((MemoryDescriptorList->Process !=
NULL) &&
01443 (
Unlock ==
TRUE) &&
01444 ((MemoryDescriptorList->MdlFlags &
MDL_PHYSICAL_VIEW) == 0)) {
01445
01446 MemoryDescriptorList->Process->NumberOfLockedPages -= NumberOfPages;
01447
ASSERT ((SPFN_NUMBER)MemoryDescriptorList->Process->NumberOfLockedPages >= 0);
01448 }
01449
01450
if ((MemoryDescriptorList->MdlFlags & (
MDL_IO_SPACE |
MDL_PHYSICAL_VIEW)) == 0) {
01451
01452
01453
01454
01455
01456
do {
01457
01458
if (*Page ==
MM_EMPTY_LIST) {
01459
01460
01461
01462
01463
01464
break;
01465 }
01466
ASSERT (*Page <=
MmHighestPhysicalPage);
01467
01468
01469
01470
01471
01472
01473 Pfn1 =
MI_PFN_ELEMENT (*Page);
01474
if (MemoryDescriptorList->MdlFlags &
MDL_WRITE_OPERATION) {
01475 Pfn1->
u3.e1.Modified = 1;
01476
if ((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
01477 (Pfn1->
u3.e1.WriteInProgress == 0)) {
01478
MiReleasePageFileSpace (Pfn1->
OriginalPte);
01479 Pfn1->
OriginalPte.
u.Soft.PageFileHigh = 0;
01480 }
01481 }
01482
01483
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 1);
01484
01485
MiDecrementReferenceCount (*Page);
01486
01487 *Page =
MM_EMPTY_LIST;
01488 Page += 1;
01489 NumberOfPages -= 1;
01490 }
while (NumberOfPages != 0);
01491 }
01492
01493 MemoryDescriptorList->MdlFlags &= ~
MDL_PAGES_LOCKED;
01494
UNLOCK_PFN2 (OldIrql);
01495
01496
return;
01497 }
01498
01499
VOID
01500 MmBuildMdlForNonPagedPool (
01501 IN OUT
PMDL MemoryDescriptorList
01502 )
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 {
01536 PPFN_NUMBER Page;
01537
PMMPTE PointerPte;
01538
PMMPTE LastPte;
01539 PVOID EndVa;
01540 PFN_NUMBER PageFrameIndex;
01541
01542 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
01543
01544
ASSERT (MemoryDescriptorList->ByteCount != 0);
01545
ASSERT ((MemoryDescriptorList->MdlFlags & (
01546
MDL_PAGES_LOCKED |
01547
MDL_MAPPED_TO_SYSTEM_VA |
01548
MDL_SOURCE_IS_NONPAGED_POOL |
01549
MDL_PARTIAL)) == 0);
01550
01551 MemoryDescriptorList->Process = (
PEPROCESS)
NULL;
01552
01553
01554
01555
01556
01557 MemoryDescriptorList->MdlFlags |=
MDL_SOURCE_IS_NONPAGED_POOL;
01558
01559 MemoryDescriptorList->MappedSystemVa =
01560 (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
01561 MemoryDescriptorList->ByteOffset);
01562
01563 EndVa = (PVOID)(((PCHAR)MemoryDescriptorList->MappedSystemVa +
01564 MemoryDescriptorList->ByteCount - 1));
01565
01566 LastPte =
MiGetPteAddress (EndVa);
01567
01568
ASSERT (
MmIsNonPagedSystemAddressValid (MemoryDescriptorList->StartVa));
01569
01570 PointerPte =
MiGetPteAddress (MemoryDescriptorList->StartVa);
01571
01572
if (
MI_IS_PHYSICAL_ADDRESS(EndVa)) {
01573 PageFrameIndex =
MI_CONVERT_PHYSICAL_TO_PFN (
01574 MemoryDescriptorList->StartVa);
01575
01576
do {
01577 *Page = PageFrameIndex;
01578 Page += 1;
01579 PageFrameIndex += 1;
01580 PointerPte += 1;
01581 }
while (PointerPte <= LastPte);
01582 }
else {
01583
do {
01584 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
01585 *Page = PageFrameIndex;
01586 Page += 1;
01587 PointerPte += 1;
01588 }
while (PointerPte <= LastPte);
01589 }
01590
01591
return;
01592 }
01593
01594
VOID
01595 MiInitializeIoTrackers (
01596 VOID
01597 )
01598 {
01599
if (
MmTrackPtes != 0) {
01600 InitializeListHead (&
MiDeadPteTrackerListHead);
01601
KeInitializeSpinLock (&
MiPteTrackerLock);
01602 InitializeListHead (&
MiPteHeader.
ListHead);
01603 }
01604
01605
if (
MmTrackLockedPages ==
TRUE) {
01606 InitializeListHead (&
MmLockedPagesHead.
ListHead);
01607 }
01608 }
01609
01610
VOID
01611 MiInsertPteTracker (
01612 IN PVOID PoolBlock,
01613 IN
PMDL MemoryDescriptorList,
01614 IN PFN_NUMBER NumberOfPtes,
01615 IN PVOID MyCaller,
01616 IN PVOID MyCallersCaller
01617 )
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651 {
01652
PPTE_TRACKER Tracker;
01653
01654 Tracker = (
PPTE_TRACKER)PoolBlock;
01655
01656 Tracker->
Mdl = MemoryDescriptorList;
01657 Tracker->
SystemVa = MemoryDescriptorList->MappedSystemVa;
01658 Tracker->
Count = NumberOfPtes;
01659
01660 Tracker->
StartVa = MemoryDescriptorList->StartVa;
01661 Tracker->
Offset = MemoryDescriptorList->ByteOffset;
01662 Tracker->
Length = MemoryDescriptorList->ByteCount;
01663 Tracker->
Page = *(PPFN_NUMBER)(MemoryDescriptorList + 1);
01664
01665 Tracker->
CallingAddress = MyCaller;
01666 Tracker->
CallersCaller = MyCallersCaller;
01667 Tracker->
PteAddress =
MiGetPteAddress (Tracker->
SystemVa);
01668
01669
MiPteHeader.
Count += NumberOfPtes;
01670
01671 InsertHeadList (&
MiPteHeader.
ListHead, &Tracker->
ListEntry);
01672 }
01673
01674 PVOID
01675 MiRemovePteTracker (
01676 IN
PMDL MemoryDescriptorList OPTIONAL,
01677 IN PVOID PteAddress,
01678 IN PFN_NUMBER NumberOfPtes
01679 )
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707 {
01708
PPTE_TRACKER Tracker;
01709 PFN_NUMBER Page;
01710 PVOID BaseAddress;
01711 PLIST_ENTRY LastFound;
01712 PLIST_ENTRY NextEntry;
01713
01714 BaseAddress =
MiGetVirtualAddressMappedByPte (PteAddress);
01715
01716
if (ARGUMENT_PRESENT (MemoryDescriptorList)) {
01717 Page = *(PPFN_NUMBER)(MemoryDescriptorList + 1);
01718 }
01719
01720 LastFound =
NULL;
01721 NextEntry =
MiPteHeader.
ListHead.Flink;
01722
while (NextEntry != &
MiPteHeader.
ListHead) {
01723
01724 Tracker = (
PPTE_TRACKER) CONTAINING_RECORD (NextEntry,
01725
PTE_TRACKER,
01726 ListEntry.Flink);
01727
01728
if (PteAddress == Tracker->
PteAddress) {
01729
01730
if (LastFound !=
NULL) {
01731
01732
01733
01734
01735
01736
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01737 0x1,
01738 (ULONG_PTR)Tracker,
01739 (ULONG_PTR)MemoryDescriptorList,
01740 (ULONG_PTR)LastFound);
01741 }
01742
01743
if (Tracker->
Count != NumberOfPtes) {
01744
01745
01746
01747
01748
01749
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01750 0x2,
01751 (ULONG_PTR)Tracker,
01752 Tracker->
Count,
01753 NumberOfPtes);
01754 }
01755
01756
if (ARGUMENT_PRESENT (MemoryDescriptorList)) {
01757
01758
if (Tracker->
SystemVa != MemoryDescriptorList->MappedSystemVa) {
01759
01760
01761
01762
01763
01764
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01765 0x3,
01766 (ULONG_PTR)Tracker,
01767 (ULONG_PTR)Tracker->
SystemVa,
01768 (ULONG_PTR)MemoryDescriptorList->MappedSystemVa);
01769 }
01770
01771
if (Tracker->
Page != Page) {
01772
01773
01774
01775
01776
01777
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01778 0x4,
01779 (ULONG_PTR)Tracker,
01780 (ULONG_PTR)Tracker->
Page,
01781 (ULONG_PTR)Page);
01782 }
01783
01784
if (Tracker->
StartVa != MemoryDescriptorList->StartVa) {
01785
01786
01787
01788
01789
01790
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01791 0x5,
01792 (ULONG_PTR)Tracker,
01793 (ULONG_PTR)Tracker->
StartVa,
01794 (ULONG_PTR)MemoryDescriptorList->StartVa);
01795 }
01796 }
01797
01798 RemoveEntryList (NextEntry);
01799 LastFound = NextEntry;
01800 }
01801 NextEntry = Tracker->
ListEntry.Flink;
01802 }
01803
01804
if ((LastFound ==
NULL) && (
MiTrackPtesAborted ==
FALSE)) {
01805
01806
01807
01808
01809
01810
KeBugCheckEx (SYSTEM_PTE_MISUSE,
01811 0x6,
01812 (ULONG_PTR)MemoryDescriptorList,
01813 (ULONG_PTR)BaseAddress,
01814 (ULONG_PTR)NumberOfPtes);
01815 }
01816
01817
MiPteHeader.
Count -= NumberOfPtes;
01818
01819
return (PVOID)LastFound;
01820 }
01821
01822
VOID
01823 MiInsertDeadPteTrackingBlock (
01824 IN PVOID PoolBlock
01825 )
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 {
01849 KIRQL OldIrql;
01850
01851 ExAcquireSpinLock (&
MiPteTrackerLock, &OldIrql);
01852
01853 InsertTailList (&
MiDeadPteTrackerListHead, (PLIST_ENTRY)PoolBlock);
01854
01855 ExReleaseSpinLock (&
MiPteTrackerLock, OldIrql);
01856 }
01857
01858
VOID
01859 MiReleaseDeadPteTrackers (
01860 VOID
01861 )
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882 {
01883 KIRQL OldIrql;
01884 PVOID PoolBlock;
01885
01886
ASSERT (KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01887
01888 ExAcquireSpinLock (&
MiPteTrackerLock, &OldIrql);
01889
01890
while (IsListEmpty(&
MiDeadPteTrackerListHead) == 0) {
01891 PoolBlock = (PVOID)RemoveHeadList(&
MiDeadPteTrackerListHead);
01892 ExReleaseSpinLock (&
MiPteTrackerLock, OldIrql);
01893
ExFreePool (PoolBlock);
01894 ExAcquireSpinLock (&
MiPteTrackerLock, &OldIrql);
01895 }
01896
01897 ExReleaseSpinLock (&
MiPteTrackerLock, OldIrql);
01898 }
01899
01900 PVOID
01901 MiGetHighestPteConsumer (
01902 OUT PULONG_PTR NumberOfPtes
01903 )
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926 {
01927
PPTE_TRACKER Tracker;
01928 PVOID BaseAddress;
01929 PFN_NUMBER NumberOfPages;
01930 PLIST_ENTRY NextEntry;
01931 PLIST_ENTRY NextEntry2;
01932 PLDR_DATA_TABLE_ENTRY DataTableEntry;
01933 ULONG_PTR Highest;
01934 ULONG_PTR PagesByThisModule;
01935 PLDR_DATA_TABLE_ENTRY HighDataTableEntry;
01936
01937 *NumberOfPtes = 0;
01938
01939
01940
01941
01942
01943
if (
MmTrackPtes ==
FALSE) {
01944
return NULL;
01945 }
01946
01947
if (
MiTrackPtesAborted ==
TRUE) {
01948
return NULL;
01949 }
01950
01951
if (IsListEmpty(&
MiPteHeader.
ListHead)) {
01952
return NULL;
01953 }
01954
01955
if (
PsLoadedModuleList.Flink ==
NULL) {
01956
return NULL;
01957 }
01958
01959 Highest = 0;
01960 HighDataTableEntry =
NULL;
01961
01962 NextEntry =
PsLoadedModuleList.Flink;
01963
while (NextEntry != &
PsLoadedModuleList) {
01964
01965 DataTableEntry = CONTAINING_RECORD(NextEntry,
01966 LDR_DATA_TABLE_ENTRY,
01967 InLoadOrderLinks);
01968
01969 PagesByThisModule = 0;
01970
01971
01972
01973
01974
01975 NextEntry2 =
MiPteHeader.
ListHead.Flink;
01976
while (NextEntry2 != &
MiPteHeader.
ListHead) {
01977
01978 Tracker = (
PPTE_TRACKER) CONTAINING_RECORD (NextEntry2,
01979
PTE_TRACKER,
01980 ListEntry.Flink);
01981
01982 BaseAddress = Tracker->
CallingAddress;
01983 NumberOfPages = Tracker->
Count;
01984
01985
if ((BaseAddress >= DataTableEntry->DllBase) &&
01986 (BaseAddress < (PVOID)((ULONG_PTR)(DataTableEntry->DllBase) + DataTableEntry->SizeOfImage))) {
01987
01988 PagesByThisModule += NumberOfPages;
01989 }
01990
01991 NextEntry2 = NextEntry2->Flink;
01992
01993 }
01994
01995
if (PagesByThisModule > Highest) {
01996 Highest = PagesByThisModule;
01997 HighDataTableEntry = DataTableEntry;
01998 }
01999
02000 NextEntry = NextEntry->Flink;
02001 }
02002
02003 *NumberOfPtes = Highest;
02004
02005
return (PVOID)HighDataTableEntry;
02006 }
02007
02008 PVOID
02009 MmMapLockedPages (
02010 IN
PMDL MemoryDescriptorList,
02011 IN KPROCESSOR_MODE AccessMode
02012 )
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048 {
02049
return MmMapLockedPagesSpecifyCache (MemoryDescriptorList,
02050 AccessMode,
02051
MmCached,
02052
NULL,
02053
TRUE,
02054
HighPagePriority);
02055 }
02056
02057 PVOID
02058 MmMapLockedPagesSpecifyCache (
02059 IN
PMDL MemoryDescriptorList,
02060 IN KPROCESSOR_MODE AccessMode,
02061 IN MEMORY_CACHING_TYPE CacheType,
02062 IN PVOID RequestedAddress,
02063 IN ULONG BugCheckOnFailure,
02064 IN MM_PAGE_PRIORITY Priority
02065 )
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 {
02123 PFN_NUMBER NumberOfPages;
02124 PFN_NUMBER SavedPageCount;
02125 PPFN_NUMBER Page;
02126
PMMPTE PointerPte;
02127 PVOID BaseVa;
02128
MMPTE TempPte;
02129 PVOID StartingVa;
02130
PMMPFN Pfn2;
02131 KIRQL OldIrql;
02132 PFN_NUMBER NumberOfPtes;
02133 PVOID CallingAddress;
02134 PVOID CallersCaller;
02135 PVOID Tracker;
02136
02137
#if !defined (_X86_)
02138
CallingAddress = (PVOID)_ReturnAddress();
02139 CallersCaller = (PVOID)0;
02140
#endif
02141
02142 StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
02143 MemoryDescriptorList->ByteOffset);
02144
02145
ASSERT (MemoryDescriptorList->ByteCount != 0);
02146
02147
if (AccessMode ==
KernelMode) {
02148
02149 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
02150 NumberOfPages =
COMPUTE_PAGES_SPANNED (StartingVa,
02151 MemoryDescriptorList->ByteCount);
02152 SavedPageCount = NumberOfPages;
02153
02154
02155
02156
02157
02158
02159
ASSERT ((MemoryDescriptorList->MdlFlags & (
02160
MDL_MAPPED_TO_SYSTEM_VA |
02161
MDL_SOURCE_IS_NONPAGED_POOL |
02162
MDL_PARTIAL_HAS_BEEN_MAPPED)) == 0);
02163
ASSERT ((MemoryDescriptorList->MdlFlags & (
02164
MDL_PAGES_LOCKED |
02165
MDL_PARTIAL)) != 0);
02166
02167
02168
02169
02170
02171
#if defined(_ALPHA_)
02172
#define KSEG0_MAXPAGE ((PFN_NUMBER)((KSEG2_BASE - KSEG0_BASE) >> PAGE_SHIFT))
02173
#endif
02174
02175
#if defined(_X86_) || defined(_IA64_)
02176
#define KSEG0_MAXPAGE MmKseg2Frame
02177
#endif
02178
02179
#if defined(_IA64_)
02180
#define MM_KSEG0_BASE KSEG0_BASE
02181
#endif
02182
02183
if ((NumberOfPages == 1) && (CacheType ==
MmCached) &&
02184 (*Page < KSEG0_MAXPAGE)) {
02185 BaseVa = (PVOID)(
MM_KSEG0_BASE + (*Page <<
PAGE_SHIFT) +
02186 MemoryDescriptorList->ByteOffset);
02187 MemoryDescriptorList->MappedSystemVa = BaseVa;
02188 MemoryDescriptorList->MdlFlags |=
MDL_MAPPED_TO_SYSTEM_VA;
02189
02190
goto Update;
02191 }
02192
02193
02194
02195
02196
02197
if ((Priority !=
HighPagePriority) &&
02198 (
MiGetSystemPteAvailability ((ULONG)NumberOfPages, Priority) ==
FALSE)) {
02199
return NULL;
02200 }
02201
02202 PointerPte =
MiReserveSystemPtes (
02203 (ULONG)NumberOfPages,
02204
SystemPteSpace,
02205
MM_COLOR_ALIGNMENT,
02206 (PtrToUlong(StartingVa) &
02207
MM_COLOR_MASK_VIRTUAL),
02208 MemoryDescriptorList->MdlFlags &
MDL_MAPPING_CAN_FAIL ? 0 : BugCheckOnFailure);
02209
02210
if (PointerPte ==
NULL) {
02211
02212
02213
02214
02215
02216
return NULL;
02217 }
02218 BaseVa = (PVOID)((PCHAR)
MiGetVirtualAddressMappedByPte (PointerPte) +
02219 MemoryDescriptorList->ByteOffset);
02220
02221 NumberOfPtes = NumberOfPages;
02222
02223 TempPte =
ValidKernelPte;
02224
02225
switch (CacheType) {
02226
02227
case MmNonCached:
02228
MI_DISABLE_CACHING (TempPte);
02229
break;
02230
02231
case MmCached:
02232
break;
02233
02234
case MmWriteCombined:
02235
MI_SET_PTE_WRITE_COMBINE (TempPte);
02236
break;
02237
02238
case MmHardwareCoherentCached:
02239
break;
02240
02241
#if 0
02242
case MmNonCachedUnordered:
02243
break;
02244
#endif
02245
02246
default:
02247
break;
02248 }
02249
02250
#if defined(_IA64_)
02251
if (CacheType !=
MmCached) {
02252
KeFlushEntireTb(
FALSE,
TRUE);
02253 }
02254
#endif
02255
02256
#if DBG
02257
LOCK_PFN2 (OldIrql);
02258
#endif //DBG
02259
02260
do {
02261
02262
if (*Page ==
MM_EMPTY_LIST) {
02263
break;
02264 }
02265 TempPte.
u.Hard.PageFrameNumber = *Page;
02266
ASSERT (PointerPte->
u.Hard.Valid == 0);
02267
02268
#if DBG
02269
if ((MemoryDescriptorList->MdlFlags & (
MDL_IO_SPACE |
MDL_PHYSICAL_VIEW)) == 0) {
02270 Pfn2 =
MI_PFN_ELEMENT (*Page);
02271
ASSERT (Pfn2->
u3.e2.ReferenceCount != 0);
02272
ASSERT ((((ULONG_PTR)PointerPte >>
PTE_SHIFT) &
MM_COLOR_MASK) ==
02273 (((ULONG)Pfn2->
u3.e1.PageColor)));
02274 }
02275
#endif //DBG
02276
02277
MI_WRITE_VALID_PTE (PointerPte, TempPte);
02278 Page += 1;
02279 PointerPte += 1;
02280 NumberOfPages -= 1;
02281 }
while (NumberOfPages != 0);
02282
02283
#if DBG
02284
UNLOCK_PFN2 (OldIrql);
02285
#endif //DBG
02286
02287
#if defined(i386)
02288
02289
02290
02291
02292
if (CacheType ==
MmWriteCombined &&
MiWriteCombiningPtes ==
TRUE) {
02293
KeFlushEntireTb (
FALSE,
TRUE);
02294
KeInvalidateAllCaches (
TRUE);
02295 }
02296
#endif
02297
02298
#if defined(_IA64_)
02299
if (CacheType !=
MmCached) {
02300
MiSweepCacheMachineDependent(BaseVa, SavedPageCount *
PAGE_SIZE, CacheType);
02301 }
02302
#endif
02303
if (
MmTrackPtes != 0) {
02304
02305
02306
02307
02308
02309
MiReleaseDeadPteTrackers ();
02310
02311 Tracker =
ExAllocatePoolWithTag (
NonPagedPool,
02312
sizeof (
PTE_TRACKER),
02313 'ySmM');
02314
if (Tracker ==
NULL) {
02315
MiTrackPtesAborted =
TRUE;
02316 }
02317 }
02318
02319
MiLockSystemSpace(OldIrql);
02320
if (MemoryDescriptorList->MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
02321
02322
02323
02324
02325
02326
02327
MiUnlockSystemSpace(OldIrql);
02328
02329
if (
MmTrackPtes != 0) {
02330
if (Tracker !=
NULL) {
02331
ExFreePool(Tracker);
02332 }
02333 }
02334
02335
#if DBG
02336
if ((MemoryDescriptorList->MdlFlags & (
MDL_IO_SPACE |
MDL_PHYSICAL_VIEW)) == 0) {
02337
PMMPFN Pfn3;
02338 PFN_NUMBER j;
02339 PPFN_NUMBER Page1;
02340
02341 Page1 = (PPFN_NUMBER)(MemoryDescriptorList + 1);
02342
for (j = 0; j < SavedPageCount ;j += 1) {
02343
if (*Page ==
MM_EMPTY_LIST) {
02344
break;
02345 }
02346 Pfn3 =
MI_PFN_ELEMENT (*Page1);
02347
ASSERT (Pfn3->
u3.e2.ReferenceCount != 0);
02348 Page1 += 1;
02349 }
02350 }
02351
#endif //DBG
02352
PointerPte =
MiGetPteAddress (BaseVa);
02353
02354
MiReleaseSystemPtes (PointerPte,
02355 (ULONG)SavedPageCount,
02356
SystemPteSpace);
02357
02358
return MemoryDescriptorList->MappedSystemVa;
02359 }
02360
02361 MemoryDescriptorList->MappedSystemVa = BaseVa;
02362 *(
volatile ULONG *)&
MmSystemLockPagesCount;
02363 MemoryDescriptorList->MdlFlags |=
MDL_MAPPED_TO_SYSTEM_VA;
02364
02365
if ((
MmTrackPtes != 0) && (Tracker !=
NULL)) {
02366
#if defined (_X86_)
02367
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
02368
#endif
02369
MiInsertPteTracker (Tracker,
02370 MemoryDescriptorList,
02371 NumberOfPtes,
02372 CallingAddress,
02373 CallersCaller);
02374 }
02375
02376
MiUnlockSystemSpace(OldIrql);
02377
02378 Update:
02379
if ((MemoryDescriptorList->MdlFlags &
MDL_PARTIAL) != 0) {
02380 MemoryDescriptorList->MdlFlags |=
MDL_PARTIAL_HAS_BEEN_MAPPED;
02381 }
02382
02383
return BaseVa;
02384
02385 }
else {
02386
02387
return MiMapLockedPagesInUserSpace (MemoryDescriptorList,
02388 StartingVa,
02389 CacheType,
02390 RequestedAddress);
02391 }
02392 }
02393
02394 PVOID
02395 MiMapSinglePage (
02396 IN PVOID VirtualAddress OPTIONAL,
02397 IN PFN_NUMBER PageFrameIndex,
02398 IN MEMORY_CACHING_TYPE CacheType,
02399 IN MM_PAGE_PRIORITY Priority
02400 )
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434 {
02435
PMMPTE PointerPte;
02436
MMPTE TempPte;
02437
02438
PAGED_CODE ();
02439
02440
if (VirtualAddress ==
NULL) {
02441
02442
02443
02444
02445
02446
if ((Priority !=
HighPagePriority) &&
02447 (
MiGetSystemPteAvailability (1, Priority) ==
FALSE)) {
02448
return NULL;
02449 }
02450
02451 PointerPte =
MiReserveSystemPtes (1,
02452
SystemPteSpace,
02453
MM_COLOR_ALIGNMENT,
02454 0,
02455 0);
02456
02457
if (PointerPte ==
NULL) {
02458
02459
02460
02461
02462
02463
return NULL;
02464 }
02465
02466
ASSERT (PointerPte->
u.Hard.Valid == 0);
02467 VirtualAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
02468 }
02469
else {
02470
ASSERT (
MI_IS_PHYSICAL_ADDRESS (VirtualAddress) == 0);
02471
ASSERT (VirtualAddress >= MM_SYSTEM_RANGE_START);
02472
02473 PointerPte =
MiGetPteAddress (VirtualAddress);
02474
ASSERT (PointerPte->
u.Hard.Valid == 1);
02475
02476
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
02477
02478
KeFlushSingleTb (VirtualAddress,
02479
TRUE,
02480
TRUE,
02481 (PHARDWARE_PTE)PointerPte,
02482
ZeroPte.
u.Flush);
02483 }
02484
02485 TempPte =
ValidKernelPte;
02486
02487
switch (CacheType) {
02488
02489
case MmNonCached:
02490
MI_DISABLE_CACHING (TempPte);
02491
break;
02492
02493
case MmCached:
02494
break;
02495
02496
case MmWriteCombined:
02497
MI_SET_PTE_WRITE_COMBINE (TempPte);
02498
break;
02499
02500
case MmHardwareCoherentCached:
02501
break;
02502
02503
#if 0
02504
case MmNonCachedUnordered:
02505
break;
02506
#endif
02507
02508
default:
02509
break;
02510 }
02511
02512
#if defined(_IA64_)
02513
if (CacheType !=
MmCached) {
02514
KeFlushEntireTb(
FALSE,
TRUE);
02515 }
02516
#endif
02517
02518 TempPte.
u.Hard.PageFrameNumber = PageFrameIndex;
02519
02520
MI_WRITE_VALID_PTE (PointerPte, TempPte);
02521
02522
#if defined(i386)
02523
02524
02525
02526
02527
if (CacheType ==
MmWriteCombined &&
MiWriteCombiningPtes ==
TRUE) {
02528
KeFlushEntireTb (
FALSE,
TRUE);
02529
KeInvalidateAllCaches (
TRUE);
02530 }
02531
#endif
02532
02533
#if defined(_IA64_)
02534
if (CacheType !=
MmCached) {
02535
MiSweepCacheMachineDependent(VirtualAddress,
PAGE_SIZE, CacheType);
02536 }
02537
#endif
02538
02539
return VirtualAddress;
02540 }
02541
02542
VOID
02543 MiUnmapSinglePage (
02544 IN PVOID VirtualAddress
02545 )
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568 {
02569
PMMPTE PointerPte;
02570
02571
PAGED_CODE ();
02572
02573
ASSERT (
MI_IS_PHYSICAL_ADDRESS (VirtualAddress) == 0);
02574
ASSERT (VirtualAddress >= MM_SYSTEM_RANGE_START);
02575
02576 PointerPte =
MiGetPteAddress (VirtualAddress);
02577
02578
MiReleaseSystemPtes (PointerPte, 1,
SystemPteSpace);
02579
return;
02580 }
02581
02582
VOID
02583 MiPhysicalViewInserter (
02584 IN
PEPROCESS Process,
02585 IN
PMI_PHYSICAL_VIEW PhysicalView
02586 )
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610 {
02611 KIRQL OldIrql;
02612 KIRQL OldIrql2;
02613
02614
LOCK_AWE (Process, OldIrql);
02615
02616
LOCK_PFN2 (OldIrql2);
02617
02618 InsertHeadList (&Process->PhysicalVadList, &PhysicalView->ListEntry);
02619
02620
if (PhysicalView->Vad->u.VadFlags.WriteWatch == 1) {
02621
MiActiveWriteWatch += 1;
02622 }
02623
02624
UNLOCK_PFN2 (OldIrql2);
02625
02626
UNLOCK_AWE (Process, OldIrql);
02627
02628
if (PhysicalView->Vad->u.VadFlags.WriteWatch == 1) {
02629
02630
02631
02632
02633
02634
if (Process->Vm.u.Flags.WriteWatch == 0) {
02635
MiMarkProcessAsWriteWatch (Process);
02636 }
02637 }
02638 }
02639
02640
VOID
02641 MiPhysicalViewRemover (
02642 IN
PEPROCESS Process,
02643 IN
PMMVAD Vad
02644 )
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668 {
02669 KIRQL OldIrql;
02670 KIRQL OldIrql2;
02671 PRTL_BITMAP
BitMap;
02672 PLIST_ENTRY NextEntry;
02673
PMI_PHYSICAL_VIEW PhysicalView;
02674 ULONG BitMapSize;
02675
02676
BitMap =
NULL;
02677
02678
LOCK_AWE (Process, OldIrql);
02679
02680
LOCK_PFN2 (OldIrql2);
02681
02682 NextEntry = Process->PhysicalVadList.Flink;
02683
while (NextEntry != &Process->PhysicalVadList) {
02684
02685 PhysicalView = CONTAINING_RECORD(NextEntry,
02686
MI_PHYSICAL_VIEW,
02687 ListEntry);
02688
02689
if (PhysicalView->
Vad == Vad) {
02690 RemoveEntryList (NextEntry);
02691
02692
if (Vad->u.VadFlags.WriteWatch == 1) {
02693
MiActiveWriteWatch -= 1;
02694
BitMap = PhysicalView->
BitMap;
02695
ASSERT (
BitMap !=
NULL);
02696 }
02697
02698
UNLOCK_PFN2 (OldIrql2);
02699
UNLOCK_AWE (Process, OldIrql);
02700
ExFreePool (PhysicalView);
02701
02702
if (
BitMap !=
NULL) {
02703 BitMapSize =
sizeof(RTL_BITMAP) + (ULONG)(((
BitMap->SizeOfBitMap + 31) / 32) * 4);
02704
PsReturnPoolQuota (Process,
NonPagedPool, BitMapSize);
02705
ExFreePool (
BitMap);
02706 }
02707
02708
return;
02709 }
02710
02711 NextEntry = NextEntry->Flink;
02712 }
02713
02714
ASSERT (
FALSE);
02715
02716
UNLOCK_PFN2 (OldIrql2);
02717
UNLOCK_AWE (Process, OldIrql);
02718 }
02719
02720
VOID
02721 MiPhysicalViewAdjuster (
02722 IN
PEPROCESS Process,
02723 IN
PMMVAD OldVad,
02724 IN
PMMVAD NewVad
02725 )
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751 {
02752 KIRQL OldIrql;
02753 KIRQL OldIrql2;
02754 PLIST_ENTRY NextEntry;
02755
PMI_PHYSICAL_VIEW PhysicalView;
02756
02757
LOCK_AWE (Process, OldIrql);
02758
02759
LOCK_PFN2 (OldIrql2);
02760
02761 NextEntry = Process->PhysicalVadList.Flink;
02762
while (NextEntry != &Process->PhysicalVadList) {
02763
02764 PhysicalView = CONTAINING_RECORD(NextEntry,
02765
MI_PHYSICAL_VIEW,
02766 ListEntry);
02767
02768
if (PhysicalView->
Vad == OldVad) {
02769 PhysicalView->
Vad = NewVad;
02770
UNLOCK_PFN2 (OldIrql2);
02771
UNLOCK_AWE (Process, OldIrql);
02772
return;
02773 }
02774
02775 NextEntry = NextEntry->Flink;
02776 }
02777
02778
ASSERT (
FALSE);
02779
02780
UNLOCK_PFN2 (OldIrql2);
02781
UNLOCK_AWE (Process, OldIrql);
02782 }
02783
02784 PVOID
02785 MiMapLockedPagesInUserSpace (
02786 IN
PMDL MemoryDescriptorList,
02787 IN PVOID StartingVa,
02788 IN MEMORY_CACHING_TYPE CacheType,
02789 IN PVOID BaseVa
02790 )
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832 {
02833 PFN_NUMBER NumberOfPages;
02834 PPFN_NUMBER Page;
02835
PMMPTE PointerPte;
02836
PMMPTE PointerPde;
02837
PMMPTE PointerPpe;
02838 PCHAR Va;
02839
MMPTE TempPte;
02840 PVOID EndingAddress;
02841
PMMVAD Vad;
02842
PEPROCESS Process;
02843
PMMPFN Pfn2;
02844 PVOID UsedPageTableHandle;
02845
PMI_PHYSICAL_VIEW PhysicalView;
02846
#if defined (_WIN64)
02847
PVOID UsedPageDirectoryHandle;
02848
#endif
02849
02850
PAGED_CODE ();
02851 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
02852 NumberOfPages =
COMPUTE_PAGES_SPANNED (StartingVa,
02853 MemoryDescriptorList->ByteCount);
02854
02855
if (MemoryDescriptorList->MdlFlags &
MDL_IO_SPACE) {
02856
ExRaiseStatus (STATUS_INVALID_ADDRESS);
02857
return NULL;
02858 }
02859
02860
02861
02862
02863
02864
02865 TempPte =
ValidUserPte;
02866
02867
switch (CacheType) {
02868
02869
case MmNonCached:
02870
MI_DISABLE_CACHING (TempPte);
02871
break;
02872
02873
case MmCached:
02874
break;
02875
02876
case MmWriteCombined:
02877
MI_SET_PTE_WRITE_COMBINE (TempPte);
02878
break;
02879
02880
case MmHardwareCoherentCached:
02881
break;
02882
02883
#if 0
02884
case MmNonCachedUnordered:
02885
break;
02886
#endif
02887
02888
default:
02889
break;
02890 }
02891
02892 Process =
PsGetCurrentProcess ();
02893
02894
02895
02896
02897
02898
02899
if (BaseVa !=
NULL) {
02900
02901
if ((ULONG_PTR)BaseVa & (
PAGE_SIZE - 1)) {
02902
02903
02904
02905
02906
02907
ExRaiseStatus (STATUS_INVALID_ADDRESS);
02908
return NULL;
02909 }
02910
02911 EndingAddress = (PVOID)((PCHAR)BaseVa + ((ULONG_PTR)NumberOfPages *
PAGE_SIZE) - 1);
02912
02913
if (EndingAddress <= BaseVa) {
02914
02915
02916
02917
02918
02919
ExRaiseStatus (STATUS_INVALID_ADDRESS);
02920
return NULL;
02921 }
02922
02923
if (EndingAddress >
MM_HIGHEST_VAD_ADDRESS) {
02924
02925
02926
02927
02928
02929
ExRaiseStatus (STATUS_INVALID_ADDRESS);
02930
return NULL;
02931 }
02932
02933
LOCK_WS_AND_ADDRESS_SPACE (Process);
02934
02935
02936
02937
02938
02939
if (Process->
AddressSpaceDeleted != 0) {
02940
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
02941
ExRaiseStatus (STATUS_PROCESS_IS_TERMINATING);
02942
return NULL;
02943 }
02944
02945 Vad =
MiCheckForConflictingVad (BaseVa, EndingAddress);
02946
02947
02948
02949
02950
02951
if (Vad != (
PMMVAD)
NULL) {
02952
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
02953
ExRaiseStatus (STATUS_CONFLICTING_ADDRESSES);
02954
return NULL;
02955 }
02956 }
02957
else {
02958
02959
02960
02961
02962
02963
LOCK_WS_AND_ADDRESS_SPACE (Process);
02964
02965
02966
02967
02968
02969
if (Process->
AddressSpaceDeleted != 0) {
02970
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
02971
ExRaiseStatus (STATUS_PROCESS_IS_TERMINATING);
02972
return NULL;
02973 }
02974
02975
try {
02976
02977 BaseVa =
MiFindEmptyAddressRange ( (ULONG_PTR)NumberOfPages *
PAGE_SIZE,
02978
X64K,
02979 0 );
02980
02981 EndingAddress = (PVOID)((PCHAR)BaseVa + ((ULONG_PTR)NumberOfPages *
PAGE_SIZE) - 1);
02982
02983 } except (
EXCEPTION_EXECUTE_HANDLER) {
02984 BaseVa =
NULL;
02985
goto Done;
02986 }
02987 }
02988
02989 PhysicalView = (
PMI_PHYSICAL_VIEW)
ExAllocatePoolWithTag (
NonPagedPool,
02990
sizeof(
MI_PHYSICAL_VIEW),
02991
MI_PHYSICAL_VIEW_KEY);
02992
if (PhysicalView ==
NULL) {
02993 BaseVa =
NULL;
02994
goto Done;
02995 }
02996
02997 Vad =
ExAllocatePoolWithTag (
NonPagedPool,
sizeof(
MMVAD), ' daV');
02998
02999
if (Vad ==
NULL) {
03000
ExFreePool (PhysicalView);
03001 BaseVa =
NULL;
03002
goto Done;
03003 }
03004
03005 PhysicalView->
Vad = Vad;
03006 PhysicalView->
StartVa = BaseVa;
03007 PhysicalView->
EndVa = EndingAddress;
03008
03009 Vad->
StartingVpn =
MI_VA_TO_VPN (BaseVa);
03010 Vad->
EndingVpn =
MI_VA_TO_VPN (EndingAddress);
03011 Vad->
ControlArea =
NULL;
03012 Vad->
FirstPrototypePte =
NULL;
03013 Vad->
u.LongFlags = 0;
03014 Vad->
u.VadFlags.Protection =
MM_READWRITE;
03015 Vad->
u.VadFlags.PhysicalMapping = 1;
03016 Vad->
u.VadFlags.PrivateMemory = 1;
03017 Vad->
u4.Banked =
NULL;
03018
03019
try {
03020
03021
MiInsertVad (Vad);
03022
03023 } except (
EXCEPTION_EXECUTE_HANDLER) {
03024
ExFreePool (PhysicalView);
03025
ExFreePool (Vad);
03026 BaseVa =
NULL;
03027
goto Done;
03028 }
03029
03030
MiPhysicalViewInserter (Process, PhysicalView);
03031
03032
#if defined(_IA64_)
03033
if (CacheType !=
MmCached) {
03034
KeFlushEntireTb(
FALSE,
TRUE);
03035 }
03036
#endif
03037
03038
03039
03040
03041
03042 Va = BaseVa;
03043 PointerPte =
MiGetPteAddress (BaseVa);
03044
03045
do {
03046
03047
if (*Page ==
MM_EMPTY_LIST) {
03048
break;
03049 }
03050
03051
ASSERT (*Page <=
MmHighestPhysicalPage);
03052
03053 PointerPde =
MiGetPteAddress (PointerPte);
03054 PointerPpe =
MiGetPdeAddress (PointerPte);
03055
03056
#if defined (_WIN64)
03057
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
03058
if (PointerPde->
u.Long == 0) {
03059 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
03060
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
03061 }
03062
#endif
03063
03064
MiMakePdeExistAndMakeValid(PointerPde, Process,
FALSE);
03065
03066
ASSERT (PointerPte->
u.Hard.Valid == 0);
03067 TempPte.
u.Hard.PageFrameNumber = *Page;
03068
MI_WRITE_VALID_PTE (PointerPte, TempPte);
03069
03070
03071
03072
03073
03074
03075
03076
03077 Pfn2 =
MI_PFN_ELEMENT(PointerPde->
u.Hard.PageFrameNumber);
03078 Pfn2->
u2.ShareCount += 1;
03079
03080
03081
03082
03083
03084 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (Va);
03085
03086
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
03087
03088 Page += 1;
03089 PointerPte += 1;
03090 NumberOfPages -= 1;
03091 Va +=
PAGE_SIZE;
03092 }
while (NumberOfPages != 0);
03093
03094
#if defined(_IA64_)
03095
if (CacheType !=
MmCached) {
03096
MiSweepCacheMachineDependent (BaseVa, MemoryDescriptorList->ByteCount, CacheType);
03097 }
03098
#endif
03099
03100 Done:
03101
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
03102
if (BaseVa ==
NULL) {
03103
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
03104
return NULL;
03105 }
03106
03107
#if defined(i386)
03108
03109
03110
03111
03112
if (CacheType ==
MmWriteCombined &&
MiWriteCombiningPtes ==
TRUE) {
03113
KeFlushEntireTb (
FALSE,
TRUE);
03114
KeInvalidateAllCaches (
TRUE);
03115 }
03116
#endif
03117
03118 BaseVa = (PVOID)((PCHAR)BaseVa + MemoryDescriptorList->ByteOffset);
03119
03120
return BaseVa;
03121 }
03122
03123
VOID
03124 MmUnmapLockedPages (
03125 IN PVOID BaseAddress,
03126 IN
PMDL MemoryDescriptorList
03127 )
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155 {
03156 PFN_NUMBER NumberOfPages;
03157 PFN_NUMBER i;
03158 PPFN_NUMBER Page;
03159
PMMPTE PointerPte;
03160
PMMPTE PointerBase;
03161 PVOID StartingVa;
03162 KIRQL OldIrql;
03163 PVOID PoolBlock;
03164
03165
ASSERT (MemoryDescriptorList->ByteCount != 0);
03166
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_PARENT_MAPPED_SYSTEM_VA) == 0);
03167
03168
if (
MI_IS_PHYSICAL_ADDRESS (BaseAddress)) {
03169
03170
03171
03172
03173
03174
03175 MemoryDescriptorList->MdlFlags &= ~(
MDL_MAPPED_TO_SYSTEM_VA |
03176
MDL_PARTIAL_HAS_BEEN_MAPPED);
03177
return;
03178 }
03179
03180
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) {
03181
03182 StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
03183 MemoryDescriptorList->ByteOffset);
03184
03185 NumberOfPages =
COMPUTE_PAGES_SPANNED (StartingVa,
03186 MemoryDescriptorList->ByteCount);
03187
03188 PointerBase =
MiGetPteAddress (BaseAddress);
03189
03190
03191
ASSERT ((MemoryDescriptorList->MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) != 0);
03192
03193
03194
#if DBG
03195
PointerPte = PointerBase;
03196 i = NumberOfPages;
03197 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
03198
if ((MemoryDescriptorList->MdlFlags &
MDL_LOCK_HELD) == 0) {
03199
LOCK_PFN2 (OldIrql);
03200 }
03201
03202
while (i != 0) {
03203
ASSERT (PointerPte->
u.Hard.Valid == 1);
03204
ASSERT (*Page ==
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte));
03205
if ((MemoryDescriptorList->MdlFlags & (
MDL_IO_SPACE |
MDL_PHYSICAL_VIEW)) == 0) {
03206
PMMPFN Pfn3;
03207 Pfn3 =
MI_PFN_ELEMENT (*Page);
03208
ASSERT (Pfn3->
u3.e2.ReferenceCount != 0);
03209 }
03210
03211 Page += 1;
03212 PointerPte += 1;
03213 i -= 1;
03214 }
03215
03216
if ((MemoryDescriptorList->MdlFlags &
MDL_LOCK_HELD) == 0) {
03217
UNLOCK_PFN2 (OldIrql);
03218 }
03219
#endif //DBG
03220
03221 MemoryDescriptorList->MdlFlags &= ~(
MDL_MAPPED_TO_SYSTEM_VA |
03222
MDL_PARTIAL_HAS_BEEN_MAPPED);
03223
03224
if (
MmTrackPtes != 0) {
03225
MiLockSystemSpace(OldIrql);
03226 PoolBlock =
MiRemovePteTracker (MemoryDescriptorList,
03227 PointerBase,
03228 NumberOfPages);
03229
MiUnlockSystemSpace(OldIrql);
03230
03231
03232
03233
03234
03235
03236
03237
if (PoolBlock) {
03238
MiInsertDeadPteTrackingBlock (PoolBlock);
03239 }
03240 }
03241
03242
MiReleaseSystemPtes (PointerBase, (ULONG)NumberOfPages,
SystemPteSpace);
03243
return;
03244
03245 }
else {
03246
03247
MiUnmapLockedPagesInUserSpace (BaseAddress,
03248 MemoryDescriptorList);
03249 }
03250 }
03251
03252
VOID
03253 MiUnmapLockedPagesInUserSpace (
03254 IN PVOID BaseAddress,
03255 IN
PMDL MemoryDescriptorList
03256 )
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284 {
03285 PFN_NUMBER NumberOfPages;
03286 PPFN_NUMBER Page;
03287
PMMPTE PointerPte;
03288
PMMPTE PointerBase;
03289
PMMPTE PointerPde;
03290 PVOID StartingVa;
03291 KIRQL OldIrql;
03292
PMMVAD Vad;
03293 PVOID TempVa;
03294
PEPROCESS Process;
03295 PVOID UsedPageTableHandle;
03296
#if defined (_WIN64)
03297
PVOID UsedPageDirectoryHandle;
03298
#endif
03299
03300
MmLockPagableSectionByHandle (
ExPageLockHandle);
03301
03302 StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
03303 MemoryDescriptorList->ByteOffset);
03304
03305 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
03306 NumberOfPages =
COMPUTE_PAGES_SPANNED (StartingVa,
03307 MemoryDescriptorList->ByteCount);
03308
03309 PointerPte =
MiGetPteAddress (BaseAddress);
03310 PointerBase = PointerPte;
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321 Process =
PsGetCurrentProcess ();
03322
03323
LOCK_WS_AND_ADDRESS_SPACE (Process);
03324
03325 Vad =
MiLocateAddress (BaseAddress);
03326
ASSERT (Vad !=
NULL);
03327
03328
MiPhysicalViewRemover (Process, Vad);
03329
03330
MiRemoveVad (Vad);
03331
03332
03333
03334
03335
03336
03337
LOCK_PFN (OldIrql);
03338
03339
do {
03340
03341
if (*Page ==
MM_EMPTY_LIST) {
03342
break;
03343 }
03344
03345
ASSERT64 (
MiGetPdeAddress(PointerPte)->u.Hard.Valid == 1);
03346
ASSERT (
MiGetPteAddress(PointerPte)->u.Hard.Valid == 1);
03347
ASSERT (PointerPte->u.Hard.Valid == 1);
03348
03349 (
VOID)
KeFlushSingleTb (BaseAddress,
03350
TRUE,
03351
FALSE,
03352 (PHARDWARE_PTE)PointerPte,
03353
ZeroPte.
u.Flush);
03354
03355 PointerPde =
MiGetPteAddress(PointerPte);
03356
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
03357
03358
03359
03360
03361
03362 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (BaseAddress);
03363
03364
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
03365
03366
03367
03368
03369
03370
03371
03372
if (
MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) {
03373
03374 TempVa =
MiGetVirtualAddressMappedByPte (PointerPde);
03375
MiDeletePte (PointerPde,
03376 TempVa,
03377
FALSE,
03378 Process,
03379 (
PMMPTE)
NULL,
03380
NULL);
03381
03382
#if defined (_WIN64)
03383
UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
03384
03385
MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
03386
03387
if (
MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) {
03388
03389 TempVa =
MiGetVirtualAddressMappedByPte(
MiGetPteAddress(PointerPde));
03390
MiDeletePte (
MiGetPteAddress(PointerPde),
03391 TempVa,
03392
FALSE,
03393 Process,
03394
NULL,
03395
NULL);
03396 }
03397
#endif
03398
}
03399
03400 Page += 1;
03401 PointerPte += 1;
03402 NumberOfPages -= 1;
03403 BaseAddress = (PVOID)((PCHAR)BaseAddress +
PAGE_SIZE);
03404 }
while (NumberOfPages != 0);
03405
03406
UNLOCK_PFN (OldIrql);
03407
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
03408
ExFreePool (Vad);
03409
MmUnlockPagableImageSection(
ExPageLockHandle);
03410
return;
03411 }
03412
03413
03414 PVOID
03415 MmMapIoSpace (
03416 IN PHYSICAL_ADDRESS PhysicalAddress,
03417 IN SIZE_T NumberOfBytes,
03418 IN MEMORY_CACHING_TYPE CacheType
03419 )
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459 {
03460 PFN_NUMBER NumberOfPages;
03461 PFN_NUMBER PageFrameIndex;
03462
PMMPTE PointerPte;
03463 PVOID BaseVa;
03464
MMPTE TempPte;
03465 KIRQL OldIrql;
03466
PMDL TempMdl;
03467 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + 1];
03468 PPFN_NUMBER Page;
03469
PLOCK_TRACKER Tracker;
03470 PVOID CallingAddress;
03471 PVOID CallersCaller;
03472
#ifdef i386
03473
NTSTATUS Status;
03474
#endif
03475
03476
#if !defined (_X86_)
03477
CallingAddress = (PVOID)_ReturnAddress();
03478 CallersCaller = (PVOID)0;
03479
#endif
03480
03481
03482
03483
03484
03485
03486 CacheType &= 0xFF;
03487
03488
if (CacheType >=
MmMaximumCacheType) {
03489
return (
NULL);
03490 }
03491
03492
#if defined (i386) && !defined (_X86PAE_)
03493
ASSERT (PhysicalAddress.HighPart == 0);
03494
#endif
03495
03496
ASSERT (NumberOfBytes != 0);
03497 NumberOfPages =
COMPUTE_PAGES_SPANNED (PhysicalAddress.LowPart,
03498 NumberOfBytes);
03499
03500 PointerPte =
MiReserveSystemPtes((ULONG)NumberOfPages,
03501
SystemPteSpace,
03502
MM_COLOR_ALIGNMENT,
03503 (PhysicalAddress.LowPart &
03504
MM_COLOR_MASK_VIRTUAL),
03505
FALSE);
03506
if (PointerPte ==
NULL) {
03507
return(
NULL);
03508 }
03509
03510 BaseVa = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte);
03511 BaseVa = (PVOID)((PCHAR)BaseVa +
BYTE_OFFSET(PhysicalAddress.LowPart));
03512
03513 TempPte =
ValidKernelPte;
03514
03515
#ifdef i386
03516
03517
03518
03519
03520
03521
03522
03523
if (
KeFeatureBits &
KF_PAT) {
03524
if ((CacheType ==
MmWriteCombined) || (CacheType ==
MmUSWCCached)) {
03525
if (
MiWriteCombiningPtes ==
TRUE) {
03526
MI_SET_PTE_WRITE_COMBINE(TempPte);
03527
Status = STATUS_SUCCESS;
03528 }
else {
03529
Status = STATUS_UNSUCCESSFUL;
03530 }
03531 }
else {
03532
03533
03534
03535
03536
03537
Status = STATUS_SUCCESS;
03538 }
03539 }
else {
03540
03541
03542
03543
Status =
KeSetPhysicalCacheTypeRange(
03544 PhysicalAddress,
03545 NumberOfBytes,
03546 CacheType
03547 );
03548 }
03549
03550
03551
03552
03553
03554
if (!
NT_SUCCESS(
Status)) {
03555
03556
if ((
Status == STATUS_NOT_SUPPORTED) &&
03557 ((CacheType ==
MmNonCached) || (CacheType ==
MmCached))) {
03558
03559
03560
03561
03562
03563
03564
03565 NOTHING;
03566
03567 }
else if (
Status == STATUS_UNSUCCESSFUL && CacheType ==
MmCached) {
03568
03569
03570
03571
03572
03573
03574
03575
03576 NOTHING;
03577
03578 }
else {
03579
03580
03581
03582
03583
03584
MiReleaseSystemPtes(PointerPte, NumberOfPages,
SystemPteSpace);
03585
03586
return(
NULL);
03587 }
03588 }
03589
#endif
03590
03591
if (CacheType ==
MmNonCached) {
03592
MI_DISABLE_CACHING (TempPte);
03593 }
03594
03595
#if defined(_IA64_)
03596
if (CacheType !=
MmCached) {
03597
KeFlushEntireTb(
FALSE,
TRUE);
03598 }
03599
#endif
03600
03601 PageFrameIndex = (PFN_NUMBER)(PhysicalAddress.QuadPart >>
PAGE_SHIFT);
03602
03603
do {
03604
ASSERT (PointerPte->
u.Hard.Valid == 0);
03605 TempPte.
u.Hard.PageFrameNumber = PageFrameIndex;
03606
MI_WRITE_VALID_PTE (PointerPte, TempPte);
03607 PointerPte += 1;
03608 PageFrameIndex += 1;
03609 NumberOfPages -= 1;
03610 }
while (NumberOfPages != 0);
03611
03612
#if defined(i386)
03613
03614
03615
03616
03617
03618
03619
if ((
KeFeatureBits &
KF_PAT) && ((CacheType ==
MmWriteCombined)
03620 || (CacheType ==
MmUSWCCached)) && (
MiWriteCombiningPtes ==
TRUE)) {
03621
KeFlushEntireTb (
FALSE,
TRUE);
03622
KeInvalidateAllCaches (
TRUE);
03623 }
03624
#endif
03625
03626
#if defined(_IA64_)
03627
if (CacheType !=
MmCached) {
03628
MiSweepCacheMachineDependent(BaseVa, NumberOfBytes, CacheType);
03629 }
03630
#endif
03631
03632
if (
MmTrackPtes != 0) {
03633
03634
03635
03636
03637
03638
MiReleaseDeadPteTrackers ();
03639
03640 Tracker =
ExAllocatePoolWithTag (
NonPagedPool,
03641
sizeof (
PTE_TRACKER),
03642 'ySmM');
03643
03644
if (Tracker !=
NULL) {
03645
#if defined (_X86_)
03646
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
03647
#endif
03648
03649 TempMdl = (
PMDL) &MdlHack;
03650 TempMdl->
MappedSystemVa = BaseVa;
03651 TempMdl->
StartVa = (PVOID)(ULONG_PTR)PhysicalAddress.QuadPart;
03652 TempMdl->
ByteOffset =
BYTE_OFFSET(PhysicalAddress.LowPart);
03653 TempMdl->
ByteCount = (ULONG)NumberOfBytes;
03654
03655 Page = (PPFN_NUMBER) (TempMdl + 1);
03656 Page = (PPFN_NUMBER)-1;
03657
03658
MiLockSystemSpace(OldIrql);
03659
03660
MiInsertPteTracker (Tracker,
03661 TempMdl,
03662
COMPUTE_PAGES_SPANNED (PhysicalAddress.LowPart,
03663 NumberOfBytes),
03664 CallingAddress,
03665 CallersCaller);
03666
03667
MiUnlockSystemSpace(OldIrql);
03668 }
03669
else {
03670
MiTrackPtesAborted =
TRUE;
03671 }
03672 }
03673
03674
return BaseVa;
03675 }
03676
03677
VOID
03678 MmUnmapIoSpace (
03679 IN PVOID BaseAddress,
03680 IN SIZE_T NumberOfBytes
03681 )
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709 {
03710 PFN_NUMBER NumberOfPages;
03711
PMMPTE FirstPte;
03712 KIRQL OldIrql;
03713 PVOID PoolBlock;
03714
03715
PAGED_CODE();
03716
ASSERT (NumberOfBytes != 0);
03717 NumberOfPages =
COMPUTE_PAGES_SPANNED (BaseAddress, NumberOfBytes);
03718 FirstPte =
MiGetPteAddress (BaseAddress);
03719
MiReleaseSystemPtes(FirstPte, (ULONG)NumberOfPages,
SystemPteSpace);
03720
03721
if (
MmTrackPtes != 0) {
03722
MiLockSystemSpace(OldIrql);
03723
03724 PoolBlock =
MiRemovePteTracker (
NULL,
03725 FirstPte,
03726 NumberOfPages);
03727
MiUnlockSystemSpace(OldIrql);
03728
03729
03730
03731
03732
03733
03734
03735
if (PoolBlock) {
03736
MiInsertDeadPteTrackingBlock (PoolBlock);
03737 }
03738 }
03739
03740
return;
03741 }
03742
03743 PVOID
03744 MmAllocateContiguousMemorySpecifyCache (
03745 IN SIZE_T NumberOfBytes,
03746 IN PHYSICAL_ADDRESS LowestAcceptableAddress,
03747 IN PHYSICAL_ADDRESS HighestAcceptableAddress,
03748 IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
03749 IN MEMORY_CACHING_TYPE CacheType
03750 )
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801 {
03802 PVOID BaseAddress;
03803 PVOID NewVa;
03804 PFN_NUMBER LowestPfn;
03805 PFN_NUMBER HighestPfn;
03806 PFN_NUMBER BoundaryPfn;
03807
PMMPTE PointerPte;
03808 PHYSICAL_ADDRESS PhysicalAddress;
03809 PVOID CallingAddress;
03810
03811
#if defined (_X86_)
03812
PVOID CallersCaller;
03813
03814
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
03815
#else
03816
CallingAddress = (PVOID)_ReturnAddress();
03817
#endif
03818
03819
ASSERT (NumberOfBytes != 0);
03820
03821 LowestPfn = (PFN_NUMBER)(LowestAcceptableAddress.QuadPart >>
PAGE_SHIFT);
03822
if (
BYTE_OFFSET(LowestAcceptableAddress.LowPart)) {
03823 LowestPfn += 1;
03824 }
03825
03826
if (
BYTE_OFFSET(BoundaryAddressMultiple.LowPart)) {
03827
return NULL;
03828 }
03829
03830 BoundaryPfn = (PFN_NUMBER)(BoundaryAddressMultiple.QuadPart >>
PAGE_SHIFT);
03831
03832 HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >>
PAGE_SHIFT);
03833
03834 BaseAddress =
MiAllocateContiguousMemory(NumberOfBytes,
03835 LowestPfn,
03836 HighestPfn,
03837 BoundaryPfn,
03838 CallingAddress);
03839
03840
if (BaseAddress) {
03841
03842
if (CacheType !=
MmCached) {
03843
03844
03845
03846
03847
03848
03849
03850
03851 PhysicalAddress =
MmGetPhysicalAddress (BaseAddress);
03852
03853 NewVa =
MmMapIoSpace (PhysicalAddress,
03854 NumberOfBytes + (2 *
PAGE_SIZE),
03855 CacheType);
03856
03857
if (NewVa) {
03858
03859 PointerPte =
MiGetPteAddress(NewVa);
03860
03861 PointerPte += ((NumberOfBytes +
PAGE_SIZE - 1) >>
PAGE_SHIFT);
03862 PointerPte->
u.Long = (ULONG_PTR)BaseAddress;
03863
03864 PointerPte += 1;
03865 PointerPte->
u.Long = NumberOfBytes;
03866
03867
KeSweepDcache (
TRUE);
03868 BaseAddress = NewVa;
03869 }
03870
else {
03871
MmFreeContiguousMemory (BaseAddress);
03872 BaseAddress =
NULL;
03873 }
03874 }
03875 }
03876
03877
return BaseAddress;
03878 }
03879
03880 PVOID
03881 MmAllocateContiguousMemory (
03882 IN SIZE_T NumberOfBytes,
03883 IN PHYSICAL_ADDRESS HighestAcceptableAddress
03884 )
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 {
03921 PFN_NUMBER HighestPfn;
03922 PVOID CallingAddress;
03923
03924
#if defined (_X86_)
03925
PVOID CallersCaller;
03926
03927
RtlGetCallersAddress(&CallingAddress, &CallersCaller);
03928
#else
03929
CallingAddress = (PVOID)_ReturnAddress();
03930
#endif
03931
03932 HighestPfn = (PFN_NUMBER)(HighestAcceptableAddress.QuadPart >>
PAGE_SHIFT);
03933
03934
return MiAllocateContiguousMemory(NumberOfBytes,
03935 0,
03936 HighestPfn,
03937 0,
03938 CallingAddress);
03939 }
03940
03941 PVOID
03942 MmAllocateIndependentPages(
03943 IN SIZE_T NumberOfBytes
03944 )
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967 {
03968 PFN_NUMBER NumberOfPages;
03969
PMMPTE PointerPte;
03970
MMPTE TempPte;
03971 PFN_NUMBER PageFrameIndex;
03972 PVOID BaseAddress;
03973 KIRQL OldIrql;
03974
03975 NumberOfPages =
BYTES_TO_PAGES (NumberOfBytes);
03976
03977 PointerPte =
MiReserveSystemPtes ((ULONG)NumberOfPages,
03978
SystemPteSpace,
03979 0,
03980 0,
03981
FALSE);
03982
if (PointerPte ==
NULL) {
03983
return NULL;
03984 }
03985
03986 BaseAddress = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte);
03987
03988
LOCK_PFN (OldIrql);
03989
03990
if ((SPFN_NUMBER)NumberOfPages >
MI_NONPAGABLE_MEMORY_AVAILABLE()) {
03991
UNLOCK_PFN (OldIrql);
03992
MiReleaseSystemPtes (PointerPte, (ULONG)NumberOfPages,
SystemPteSpace);
03993
return NULL;
03994 }
03995
03996
MmResidentAvailablePages -= NumberOfPages;
03997
MM_BUMP_COUNTER(28, NumberOfPages);
03998
03999
do {
04000
ASSERT (PointerPte->
u.Hard.Valid == 0);
04001
MiEnsureAvailablePageOrWait (
NULL,
NULL);
04002 PageFrameIndex =
MiRemoveAnyPage (
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
04003
04004
MI_MAKE_VALID_PTE (TempPte,
04005 PageFrameIndex,
04006
MM_READWRITE,
04007 PointerPte);
04008
04009
MI_SET_PTE_DIRTY (TempPte);
04010
MI_WRITE_VALID_PTE (PointerPte, TempPte);
04011
MiInitializePfn (PageFrameIndex, PointerPte, 1);
04012
04013 PointerPte += 1;
04014 NumberOfPages -= 1;
04015 }
while (NumberOfPages != 0);
04016
04017
UNLOCK_PFN (OldIrql);
04018
04019
MiChargeCommitmentCantExpand (NumberOfPages,
TRUE);
04020
04021
MM_TRACK_COMMIT (
MM_DBG_COMMIT_INDEPENDENT_PAGES, NumberOfPages);
04022
04023
return BaseAddress;
04024 }
04025
04026 BOOLEAN
04027 MmSetPageProtection(
04028 IN PVOID VirtualAddress,
04029 IN SIZE_T NumberOfBytes,
04030 IN ULONG NewProtect
04031 )
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059 {
04060 PFN_NUMBER i;
04061 PFN_NUMBER NumberOfPages;
04062
PMMPTE PointerPte;
04063
MMPTE TempPte;
04064
MMPTE NewPteContents;
04065 KIRQL OldIrql;
04066 ULONG ProtectionMask;
04067
04068
if (
MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) {
04069
return FALSE;
04070 }
04071
04072
try {
04073 ProtectionMask =
MiMakeProtectionMask (NewProtect);
04074 } except (
EXCEPTION_EXECUTE_HANDLER) {
04075
return FALSE;
04076 }
04077
04078 PointerPte =
MiGetPteAddress (VirtualAddress);
04079 NumberOfPages =
BYTES_TO_PAGES (NumberOfBytes);
04080
04081
LOCK_PFN (OldIrql);
04082
04083
for (i = 0; i < NumberOfPages; i += 1) {
04084 TempPte.
u.Long = PointerPte->
u.Long;
04085
04086
MI_MAKE_VALID_PTE (NewPteContents,
04087 TempPte.
u.Hard.PageFrameNumber,
04088 ProtectionMask,
04089 PointerPte);
04090
04091
KeFlushSingleTb ((PVOID)((PUCHAR)VirtualAddress + (i <<
PAGE_SHIFT)),
04092
TRUE,
04093
TRUE,
04094 (PHARDWARE_PTE)PointerPte,
04095 NewPteContents.
u.Flush);
04096
04097 PointerPte += 1;
04098 }
04099
04100
UNLOCK_PFN (OldIrql);
04101
04102
return TRUE;
04103 }
04104
04105
04106 PVOID
04107 MiAllocateContiguousMemory (
04108 IN SIZE_T NumberOfBytes,
04109 IN PFN_NUMBER LowestAcceptablePfn,
04110 IN PFN_NUMBER HighestAcceptablePfn,
04111 IN PFN_NUMBER BoundaryPfn,
04112 PVOID CallingAddress
04113 )
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159 {
04160 PVOID BaseAddress;
04161 PFN_NUMBER SizeInPages;
04162 PFN_NUMBER LowestPfn;
04163 PFN_NUMBER HighestPfn;
04164 PFN_NUMBER i;
04165
04166
ASSERT (NumberOfBytes != 0);
04167
04168
#if defined (_X86PAE_)
04169
if (
MiNoLowMemory ==
TRUE) {
04170
if (HighestAcceptablePfn <= 0xFFFFF) {
04171
return MiAllocateLowMemory (NumberOfBytes,
04172 LowestAcceptablePfn,
04173 HighestAcceptablePfn,
04174 BoundaryPfn,
04175 CallingAddress,
04176 'tnoC');
04177 }
04178 LowestPfn = 0x100000;
04179 }
04180
#endif
04181
04182 BaseAddress =
ExAllocatePoolWithTag (
NonPagedPoolCacheAligned,
04183 NumberOfBytes,
04184 'mCmM');
04185
04186
04187
04188
04189
04190
04191
04192
04193 SizeInPages =
BYTES_TO_PAGES (NumberOfBytes);
04194
04195 LowestPfn = LowestAcceptablePfn;
04196 HighestPfn = HighestAcceptablePfn;
04197
04198
if (BaseAddress !=
NULL) {
04199
if (
MiCheckForContiguousMemory( BaseAddress,
04200 SizeInPages,
04201 SizeInPages,
04202 LowestPfn,
04203 HighestPfn,
04204 BoundaryPfn)) {
04205
04206
return BaseAddress;
04207 }
04208
04209
04210
04211
04212
04213
04214
04215
ExFreePool (BaseAddress);
04216
04217 }
else {
04218
04219
04220
04221
04222
04223
return NULL;
04224 }
04225
04226
if (KeGetCurrentIrql() >
APC_LEVEL) {
04227
return NULL;
04228 }
04229
04230 BaseAddress =
NULL;
04231
04232 i = 3;
04233
04234 InterlockedIncrement (&
MiDelayPageFaults);
04235
04236
for (; ; ) {
04237 BaseAddress =
MiFindContiguousMemory (LowestPfn,
04238 HighestPfn,
04239 BoundaryPfn,
04240 SizeInPages,
04241 CallingAddress);
04242
04243
if ((BaseAddress !=
NULL) || (i == 0)) {
04244
break;
04245 }
04246
04247
04248
04249
04250
04251
MiEmptyAllWorkingSets ();
04252
MiFlushAllPages();
04253
04254
KeDelayExecutionThread (
KernelMode,
04255
FALSE,
04256 (PLARGE_INTEGER)&
MmHalfSecond);
04257
04258 i -= 1;
04259 }
04260 InterlockedDecrement (&
MiDelayPageFaults);
04261
return BaseAddress;
04262 }
04263
04264 PFN_NUMBER
MiLastCallLowPage;
04265 PFN_NUMBER
MiLastCallHighPage;
04266 ULONG
MiLastCallColor;
04267
04268
04269
PMDL
04270 MmAllocatePagesForMdl (
04271 IN PHYSICAL_ADDRESS LowAddress,
04272 IN PHYSICAL_ADDRESS HighAddress,
04273 IN PHYSICAL_ADDRESS SkipBytes,
04274 IN SIZE_T TotalBytes
04275 )
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324 {
04325
PMDL MemoryDescriptorList;
04326
PMDL MemoryDescriptorList2;
04327
PMMPFN Pfn1;
04328
PMMPFN PfnNextColored;
04329
PMMPFN PfnNextFlink;
04330
PMMPFN PfnLastColored;
04331 KIRQL OldIrql;
04332 PFN_NUMBER start;
04333 PFN_NUMBER count;
04334 PFN_NUMBER Page;
04335 PFN_NUMBER LastPage;
04336 PFN_NUMBER found;
04337 PFN_NUMBER BasePage;
04338 PFN_NUMBER LowPage;
04339 PFN_NUMBER HighPage;
04340 PFN_NUMBER SizeInPages;
04341 PFN_NUMBER MdlPageSpan;
04342 PFN_NUMBER SkipPages;
04343 PFN_NUMBER MaxPages;
04344 PPFN_NUMBER MdlPage;
04345 PPFN_NUMBER LastMdlPage;
04346 ULONG Color;
04347
PMMCOLOR_TABLES ColorHead;
04348
MMLISTS MemoryList;
04349 PPFN_NUMBER FirstMdlPageToZero;
04350 PFN_NUMBER LowPage1;
04351 PFN_NUMBER HighPage1;
04352 LOGICAL PagePlacementOk;
04353 PFN_NUMBER PageNextColored;
04354 PFN_NUMBER PageNextFlink;
04355 PFN_NUMBER PageLastColored;
04356
PMMPFNLIST ListHead;
04357 PPFN_NUMBER ColorAnchorsHead;
04358 PPFN_NUMBER ColorAnchor;
04359 ULONG FullAnchorCount;
04360
#if DBG
04361
ULONG FinishedCount;
04362
#endif
04363
04364
ASSERT (KeGetCurrentIrql() <=
APC_LEVEL);
04365
04366
04367
04368
04369
04370
if (
BYTE_OFFSET(SkipBytes.LowPart)) {
04371
return (
PMDL)0;
04372 }
04373
04374
MmLockPagableSectionByHandle (
ExPageLockHandle);
04375
04376 LowPage = (PFN_NUMBER)(LowAddress.QuadPart >>
PAGE_SHIFT);
04377 HighPage = (PFN_NUMBER)(HighAddress.QuadPart >>
PAGE_SHIFT);
04378
04379
04380
04381
04382
04383
if (TotalBytes > (SIZE_T)((ULONG)(MAXULONG -
PAGE_SIZE))) {
04384 TotalBytes = (SIZE_T)((ULONG)(MAXULONG -
PAGE_SIZE));
04385 }
04386
04387 SizeInPages = (PFN_NUMBER)
ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, TotalBytes);
04388
04389 SkipPages = (PFN_NUMBER)(SkipBytes.QuadPart >>
PAGE_SHIFT);
04390
04391 BasePage = LowPage;
04392
04393
LOCK_PFN (OldIrql);
04394
04395 MaxPages =
MI_NONPAGABLE_MEMORY_AVAILABLE() - 1024;
04396
04397
if ((SPFN_NUMBER)MaxPages <= 0) {
04398 SizeInPages = 0;
04399 }
04400
else if (SizeInPages > MaxPages) {
04401 SizeInPages = MaxPages;
04402 }
04403
04404
if (SizeInPages == 0) {
04405
UNLOCK_PFN (OldIrql);
04406
MmUnlockPagableImageSection (
ExPageLockHandle);
04407
return (
PMDL)0;
04408 }
04409
04410
UNLOCK_PFN (OldIrql);
04411
04412
#if DBG
04413
if (SizeInPages < (PFN_NUMBER)
ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, TotalBytes)) {
04414
if (MiPrintAwe != 0) {
04415
DbgPrint(
"MmAllocatePagesForMdl1: unable to get %p pages, trying for %p instead\n",
04416
ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, TotalBytes),
04417 SizeInPages);
04418 }
04419 }
04420
#endif
04421
04422
04423
04424
04425
04426
do {
04427 MemoryDescriptorList =
MmCreateMdl ((
PMDL)0,
04428 (PVOID)0,
04429 SizeInPages <<
PAGE_SHIFT);
04430
04431
if (MemoryDescriptorList != (
PMDL)0) {
04432
break;
04433 }
04434 SizeInPages -= (SizeInPages >> 4);
04435 }
while (SizeInPages != 0);
04436
04437
if (MemoryDescriptorList == (
PMDL)0) {
04438
MmUnlockPagableImageSection (
ExPageLockHandle);
04439
return (
PMDL)0;
04440 }
04441
04442
04443
04444
04445
04446 ColorAnchorsHead = (PPFN_NUMBER)
ExAllocatePoolWithTag (
NonPagedPool,
04447
MmSecondaryColors *
sizeof (PFN_NUMBER),
04448 'ldmM');
04449
04450
if (ColorAnchorsHead ==
NULL) {
04451
MmUnlockPagableImageSection (
ExPageLockHandle);
04452
ExFreePool (MemoryDescriptorList);
04453
return (
PMDL)0;
04454 }
04455
04456 MdlPageSpan = SizeInPages;
04457
04458
04459
04460
04461
04462 start = 0;
04463 found = 0;
04464
04465 MdlPage = (PPFN_NUMBER)(MemoryDescriptorList + 1);
04466
04467 ExAcquireFastMutex (&
MmDynamicMemoryMutex);
04468
04469
LOCK_PFN (OldIrql);
04470
04471 MaxPages =
MI_NONPAGABLE_MEMORY_AVAILABLE() - 1024;
04472
04473
if ((SPFN_NUMBER)MaxPages <= 0) {
04474 SizeInPages = 0;
04475 }
04476
else if (SizeInPages > MaxPages) {
04477 SizeInPages = MaxPages;
04478 }
04479
04480
if (SizeInPages == 0) {
04481
UNLOCK_PFN (OldIrql);
04482 ExReleaseFastMutex (&
MmDynamicMemoryMutex);
04483
MmUnlockPagableImageSection (
ExPageLockHandle);
04484
ExFreePool (MemoryDescriptorList);
04485
ExFreePool (ColorAnchorsHead);
04486
return (
PMDL)0;
04487 }
04488
04489
04490
04491
04492
04493
04494
if (
MiChargeCommitmentCantExpand (SizeInPages,
FALSE) ==
FALSE) {
04495
UNLOCK_PFN (OldIrql);
04496 ExReleaseFastMutex (&
MmDynamicMemoryMutex);
04497
MmUnlockPagableImageSection (
ExPageLockHandle);
04498
ExFreePool (MemoryDescriptorList);
04499
ExFreePool (ColorAnchorsHead);
04500
return (
PMDL)0;
04501 }
04502
04503
MM_TRACK_COMMIT (
MM_DBG_COMMIT_MDL_PAGES, SizeInPages);
04504
04505
if ((
MiLastCallLowPage != LowPage) || (
MiLastCallHighPage != HighPage)) {
04506
MiLastCallColor = 0;
04507 }
04508
04509
MiLastCallLowPage = LowPage;
04510
MiLastCallHighPage = HighPage;
04511
04512 FirstMdlPageToZero = MdlPage;
04513
04514
do {
04515
04516
04517
04518
04519
04520
04521
04522
04523
for (MemoryList =
ZeroedPageList; MemoryList <=
FreePageList; MemoryList += 1) {
04524
04525 ListHead =
MmPageLocationList[MemoryList];
04526
04527 FullAnchorCount = 0;
04528
04529
for (Color = 0; Color <
MmSecondaryColors; Color += 1) {
04530 ColorAnchorsHead[Color] =
MM_EMPTY_LIST;
04531 }
04532
04533 Color =
MiLastCallColor;
04534
ASSERT (Color <
MmSecondaryColors);
04535
04536
do {
04537
04538 ColorHead = &
MmFreePagesByColor[MemoryList][Color];
04539 ColorAnchor = &ColorAnchorsHead[Color];
04540
04541 Color += 1;
04542
if (Color >=
MmSecondaryColors) {
04543 Color = 0;
04544 }
04545
04546
if (*ColorAnchor == (
MM_EMPTY_LIST - 1)) {
04547
04548
04549
04550
04551
04552
continue;
04553 }
04554
04555
if (ColorHead->
Flink ==
MM_EMPTY_LIST) {
04556
04557
04558
04559
04560
04561 FullAnchorCount += 1;
04562 *ColorAnchor = (
MM_EMPTY_LIST - 1);
04563
continue;
04564 }
04565
04566
while (ColorHead->
Flink !=
MM_EMPTY_LIST) {
04567
04568 Page = ColorHead->
Flink;
04569
04570 Pfn1 =
MI_PFN_ELEMENT(Page);
04571
04572
ASSERT ((
MMLISTS)Pfn1->
u3.e1.PageLocation == MemoryList);
04573
04574
04575
04576
04577
04578 PagePlacementOk =
FALSE;
04579
04580 LowPage1 = LowPage;
04581 HighPage1 = HighPage;
04582
04583
do {
04584
if ((Page >= LowPage1) && (Page <= HighPage1)) {
04585 PagePlacementOk =
TRUE;
04586
break;
04587 }
04588
04589
if (SkipPages == 0) {
04590
break;
04591 }
04592
04593 LowPage1 += SkipPages;
04594 HighPage1 += SkipPages;
04595
04596
if (LowPage1 >
MmHighestPhysicalPage) {
04597
break;
04598 }
04599
if (HighPage1 >
MmHighestPhysicalPage) {
04600 HighPage1 =
MmHighestPhysicalPage;
04601 }
04602 }
while (
TRUE);
04603
04604
04605
04606
04607
04608
04609
04610
ASSERT (Pfn1->
u1.Flink != 0);
04611
ASSERT (Pfn1->
u2.Blink != 0);
04612
04613
if (PagePlacementOk ==
FALSE) {
04614
04615
04616
04617
04618
04619
if (*ColorAnchor ==
MM_EMPTY_LIST) {
04620 *ColorAnchor = Page;
04621 }
04622
else if (Page == *ColorAnchor) {
04623
04624
04625
04626
04627
04628 FullAnchorCount += 1;
04629 *ColorAnchor = (
MM_EMPTY_LIST - 1);
04630
break;
04631 }
04632
04633
04634
04635
04636
04637
04638 PageNextColored = (PFN_NUMBER)Pfn1->
OriginalPte.
u.Long;
04639
04640
if (PageNextColored ==
MM_EMPTY_LIST) {
04641
04642
04643
04644
04645
04646 FullAnchorCount += 1;
04647 *ColorAnchor = (
MM_EMPTY_LIST - 1);
04648
break;
04649 }
04650
04651
ASSERT (Pfn1->
u1.Flink != 0);
04652
ASSERT (Pfn1->
u1.Flink !=
MM_EMPTY_LIST);
04653
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04654
04655 PfnNextColored =
MI_PFN_ELEMENT(PageNextColored);
04656
ASSERT ((
MMLISTS)PfnNextColored->
u3.e1.PageLocation == MemoryList);
04657
ASSERT (PfnNextColored->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04658
04659
04660
04661
04662
04663
04664 PageNextFlink = Pfn1->
u1.Flink;
04665 PfnNextFlink =
MI_PFN_ELEMENT(PageNextFlink);
04666
04667
ASSERT ((
MMLISTS)PfnNextFlink->
u3.e1.PageLocation == MemoryList);
04668
ASSERT (PfnNextFlink->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04669
04670 PfnLastColored = ColorHead->
Blink;
04671
ASSERT (PfnLastColored != (
PMMPFN)
MM_EMPTY_LIST);
04672
ASSERT (PfnLastColored->
OriginalPte.
u.Long ==
MM_EMPTY_LIST);
04673
ASSERT (PfnLastColored->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04674
ASSERT (PfnLastColored->
u2.Blink !=
MM_EMPTY_LIST);
04675
04676
ASSERT ((
MMLISTS)PfnLastColored->
u3.e1.PageLocation == MemoryList);
04677 PageLastColored = PfnLastColored -
MmPfnDatabase;
04678
04679
if (ListHead->
Flink == Page) {
04680
04681
ASSERT (Pfn1->
u2.Blink ==
MM_EMPTY_LIST);
04682
ASSERT (ListHead->
Blink != Page);
04683
04684 ListHead->
Flink = PageNextFlink;
04685
04686 PfnNextFlink->
u2.Blink =
MM_EMPTY_LIST;
04687 }
04688
else {
04689
04690
ASSERT (Pfn1->
u2.Blink !=
MM_EMPTY_LIST);
04691
ASSERT ((
MMLISTS)(
MI_PFN_ELEMENT((
MI_PFN_ELEMENT(Pfn1->
u2.Blink)->u1.Flink)))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04692
ASSERT ((
MMLISTS)(
MI_PFN_ELEMENT((
MI_PFN_ELEMENT(Pfn1->
u2.Blink)->u1.Flink)))->u3.e1.PageLocation == MemoryList);
04693
04694
MI_PFN_ELEMENT(Pfn1->
u2.Blink)->u1.Flink = PageNextFlink;
04695 PfnNextFlink->
u2.Blink = Pfn1->
u2.Blink;
04696 }
04697
04698
#if DBG
04699
if (PfnLastColored->
u1.Flink ==
MM_EMPTY_LIST) {
04700
ASSERT (ListHead->
Blink == PageLastColored);
04701 }
04702
#endif
04703
04704 Pfn1->
u1.Flink = PfnLastColored->
u1.Flink;
04705 Pfn1->
u2.Blink = PageLastColored;
04706
04707
if (ListHead->
Blink == PageLastColored) {
04708 ListHead->
Blink = Page;
04709 }
04710
04711
04712
04713
04714
04715
if (PfnLastColored->
u1.Flink !=
MM_EMPTY_LIST) {
04716
ASSERT (
MI_PFN_ELEMENT(PfnLastColored->
u1.Flink)->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
04717
ASSERT ((
MMLISTS)(
MI_PFN_ELEMENT(PfnLastColored->
u1.Flink)->u3.e1.PageLocation) == MemoryList);
04718
MI_PFN_ELEMENT(PfnLastColored->
u1.Flink)->u2.Blink = Page;
04719 }
04720
04721 PfnLastColored->
u1.Flink = Page;
04722
04723 ColorHead->
Flink = PageNextColored;
04724 Pfn1->
OriginalPte.
u.Long =
MM_EMPTY_LIST;
04725
04726
ASSERT (PfnLastColored->
OriginalPte.
u.Long ==
MM_EMPTY_LIST);
04727 PfnLastColored->
OriginalPte.
u.Long = Page;
04728 ColorHead->
Blink = Pfn1;
04729
04730
continue;
04731 }
04732
04733 found += 1;
04734
ASSERT (Pfn1->
u3.e1.ReadInProgress == 0);
04735
MiUnlinkFreeOrZeroedPage (Page);
04736 Pfn1->
u3.e1.PageColor = 0;
04737
04738 Pfn1->
u3.e2.ReferenceCount = 1;
04739 Pfn1->
u2.ShareCount = 1;
04740
MI_SET_PFN_DELETED(Pfn1);
04741 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
04742
#if DBG
04743
Pfn1->
PteFrame =
MI_MAGIC_AWE_PTEFRAME;
04744
#endif
04745
Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
04746
04747 Pfn1->
u3.e1.StartOfAllocation = 1;
04748 Pfn1->
u3.e1.EndOfAllocation = 1;
04749 Pfn1->
u3.e1.VerifierAllocation = 0;
04750 Pfn1->
u3.e1.LargeSessionAllocation = 0;
04751
04752 *MdlPage = Page;
04753 MdlPage += 1;
04754
04755
if (found == SizeInPages) {
04756
04757
04758
04759
04760
04761
if (MemoryList ==
ZeroedPageList) {
04762 FirstMdlPageToZero = MdlPage;
04763
MiLastCallColor = Color;
04764 }
04765
04766
#if DBG
04767
FinishedCount = 0;
04768
for (Color = 0; Color <
MmSecondaryColors; Color += 1) {
04769
if (ColorAnchorsHead[Color] == (
MM_EMPTY_LIST - 1)) {
04770 FinishedCount += 1;
04771 }
04772 }
04773
ASSERT (FinishedCount == FullAnchorCount);
04774
#endif
04775
04776
goto pass2_done;
04777 }
04778
04779
04780
04781
04782
04783
04784
break;
04785 }
04786
04787 }
while (FullAnchorCount !=
MmSecondaryColors);
04788
04789
#if DBG
04790
FinishedCount = 0;
04791
for (Color = 0; Color <
MmSecondaryColors; Color += 1) {
04792
if (ColorAnchorsHead[Color] == (
MM_EMPTY_LIST - 1)) {
04793 FinishedCount += 1;
04794 }
04795 }
04796
ASSERT (FinishedCount == FullAnchorCount);
04797
#endif
04798
04799
if (MemoryList ==
ZeroedPageList) {
04800 FirstMdlPageToZero = MdlPage;
04801 }
04802
04803
MiLastCallColor = 0;
04804 }
04805
04806 start = 0;
04807
04808
do {
04809
04810 count =
MmPhysicalMemoryBlock->
Run[start].
PageCount;
04811 Page =
MmPhysicalMemoryBlock->
Run[start].
BasePage;
04812
04813
if (count != 0) {
04814
04815
04816
04817
04818
04819 LastPage = Page + count;
04820
04821
if (LastPage - 1 > HighPage) {
04822 LastPage = HighPage + 1;
04823 }
04824
04825
if (Page < LowPage) {
04826 Page = LowPage;
04827 }
04828
04829
if ((Page < LastPage) &&
04830 (Page >=
MmPhysicalMemoryBlock->
Run[start].
BasePage) &&
04831 (LastPage <=
MmPhysicalMemoryBlock->
Run[start].
BasePage +
04832
MmPhysicalMemoryBlock->
Run[start].
PageCount)) {
04833
04834 Pfn1 =
MI_PFN_ELEMENT (Page);
04835
do {
04836
04837
if (Pfn1->
u3.e1.PageLocation ==
StandbyPageList) {
04838
04839
if ((Pfn1->
u1.Flink != 0) &&
04840 (Pfn1->
u2.Blink != 0) &&
04841 (Pfn1->
u3.e2.ReferenceCount == 0)) {
04842
04843
ASSERT (Pfn1->
u3.e1.ReadInProgress == 0);
04844
04845 found += 1;
04846
04847
04848
04849
04850
04851
MiUnlinkPageFromList (Pfn1);
04852
MiRestoreTransitionPte (Page);
04853
04854 Pfn1->
u3.e1.PageColor = 0;
04855
04856 Pfn1->
u3.e2.ReferenceCount = 1;
04857 Pfn1->
u2.ShareCount = 1;
04858
MI_SET_PFN_DELETED(Pfn1);
04859 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
04860
#if DBG
04861
Pfn1->
PteFrame =
MI_MAGIC_AWE_PTEFRAME;
04862
#endif
04863
Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
04864
04865 Pfn1->
u3.e1.StartOfAllocation = 1;
04866 Pfn1->
u3.e1.EndOfAllocation = 1;
04867 Pfn1->
u3.e1.VerifierAllocation = 0;
04868 Pfn1->
u3.e1.LargeSessionAllocation = 0;
04869
04870 *MdlPage = Page;
04871 MdlPage += 1;
04872
04873
if (found == SizeInPages) {
04874
04875
04876
04877
04878
04879
goto pass2_done;
04880 }
04881 }
04882 }
04883 Page += 1;
04884 Pfn1 += 1;
04885
04886 }
while (Page < LastPage);
04887 }
04888 }
04889 start += 1;
04890 }
while (start !=
MmPhysicalMemoryBlock->
NumberOfRuns);
04891
04892
if (SkipPages == 0) {
04893
break;
04894 }
04895 LowPage += SkipPages;
04896 HighPage += SkipPages;
04897
if (LowPage >
MmHighestPhysicalPage) {
04898
break;
04899 }
04900
if (HighPage >
MmHighestPhysicalPage) {
04901 HighPage =
MmHighestPhysicalPage;
04902 }
04903 }
while (1);
04904
04905 pass2_done:
04906
04907
MmMdlPagesAllocated += found;
04908
04909
MmResidentAvailablePages -= found;
04910
MM_BUMP_COUNTER(34, found);
04911
04912
UNLOCK_PFN (OldIrql);
04913
04914 ExReleaseFastMutex (&
MmDynamicMemoryMutex);
04915
MmUnlockPagableImageSection (
ExPageLockHandle);
04916
04917
ExFreePool (ColorAnchorsHead);
04918
04919
if (found != SizeInPages) {
04920
ASSERT (found < SizeInPages);
04921
MiReturnCommitment (SizeInPages - found);
04922
MM_TRACK_COMMIT (
MM_DBG_COMMIT_MDL_PAGES, 0 - (SizeInPages - found));
04923 }
04924
04925
if (found == 0) {
04926
ExFreePool (MemoryDescriptorList);
04927
return (
PMDL)0;
04928 }
04929
04930 MemoryDescriptorList->
ByteCount = (ULONG)(found <<
PAGE_SHIFT);
04931
04932
if (found != SizeInPages) {
04933 *MdlPage =
MM_EMPTY_LIST;
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
if ((MdlPageSpan - found) > ((4 *
PAGE_SIZE) /
sizeof (PFN_NUMBER))) {
04943 MemoryDescriptorList2 =
MmCreateMdl ((
PMDL)0,
04944 (PVOID)0,
04945 found <<
PAGE_SHIFT);
04946
04947
if (MemoryDescriptorList2 != (
PMDL)0) {
04948 RtlMoveMemory ((PVOID)(MemoryDescriptorList2 + 1),
04949 (PVOID)(MemoryDescriptorList + 1),
04950 found *
sizeof (PFN_NUMBER));
04951 FirstMdlPageToZero = (PPFN_NUMBER)(MemoryDescriptorList2 + 1) +
04952 (FirstMdlPageToZero -
04953 (PPFN_NUMBER)(MemoryDescriptorList + 1));
04954
ExFreePool (MemoryDescriptorList);
04955 MemoryDescriptorList = MemoryDescriptorList2;
04956 }
04957 }
04958
04959 MdlPage = (PPFN_NUMBER)(MemoryDescriptorList + 1);
04960 LastMdlPage = MdlPage + found;
04961
04962
#if DBG
04963
04964
04965
04966
04967 LowPage = (PFN_NUMBER)(LowAddress.QuadPart >>
PAGE_SHIFT);
04968 HighPage = (PFN_NUMBER)(HighAddress.QuadPart >>
PAGE_SHIFT);
04969
04970
while (MdlPage < FirstMdlPageToZero) {
04971 Page = *MdlPage;
04972 PagePlacementOk =
FALSE;
04973 LowPage1 = LowPage;
04974 HighPage1 = HighPage;
04975
04976
do {
04977
if ((Page >= LowPage1) && (Page <= HighPage1)) {
04978 PagePlacementOk =
TRUE;
04979
break;
04980 }
04981
04982
if (SkipPages == 0) {
04983
break;
04984 }
04985
04986 LowPage1 += SkipPages;
04987 HighPage1 += SkipPages;
04988
04989
if (LowPage1 >
MmHighestPhysicalPage) {
04990
break;
04991 }
04992
if (HighPage1 >
MmHighestPhysicalPage) {
04993 HighPage1 =
MmHighestPhysicalPage;
04994 }
04995 }
while (
TRUE);
04996
04997
ASSERT (PagePlacementOk ==
TRUE);
04998 Pfn1 =
MI_PFN_ELEMENT(*MdlPage);
04999
ASSERT (Pfn1->
PteFrame ==
MI_MAGIC_AWE_PTEFRAME);
05000 MdlPage += 1;
05001 }
05002
#endif
05003
05004
while (FirstMdlPageToZero < LastMdlPage) {
05005
05006
#if DBG
05007
05008
05009
05010
05011 Page = *FirstMdlPageToZero;
05012
05013 PagePlacementOk =
FALSE;
05014 LowPage1 = LowPage;
05015 HighPage1 = HighPage;
05016
05017
do {
05018
if ((Page >= LowPage1) && (Page <= HighPage1)) {
05019 PagePlacementOk =
TRUE;
05020
break;
05021 }
05022
05023
if (SkipPages == 0) {
05024
break;
05025 }
05026
05027 LowPage1 += SkipPages;
05028 HighPage1 += SkipPages;
05029
05030
if (LowPage1 >
MmHighestPhysicalPage) {
05031
break;
05032 }
05033
if (HighPage1 >
MmHighestPhysicalPage) {
05034 HighPage1 =
MmHighestPhysicalPage;
05035 }
05036 }
while (
TRUE);
05037
05038
ASSERT (PagePlacementOk ==
TRUE);
05039 Pfn1 =
MI_PFN_ELEMENT(*FirstMdlPageToZero);
05040
ASSERT (Pfn1->
PteFrame ==
MI_MAGIC_AWE_PTEFRAME);
05041
#endif
05042
MiZeroPhysicalPage (*FirstMdlPageToZero, 0);
05043 FirstMdlPageToZero += 1;
05044 }
05045
05046
return MemoryDescriptorList;
05047 }
05048
05049
05050
VOID
05051 MmFreePagesFromMdl (
05052 IN
PMDL MemoryDescriptorList
05053 )
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076 {
05077
PMMPFN Pfn1;
05078 KIRQL OldIrql;
05079 PVOID StartingAddress;
05080 PVOID AlignedVa;
05081 PPFN_NUMBER Page;
05082 PFN_NUMBER NumberOfPages;
05083 PFN_NUMBER PagesFreed;
05084
05085
ASSERT (KeGetCurrentIrql() <=
APC_LEVEL);
05086
05087 PagesFreed = 0;
05088
05089
MmLockPagableSectionByHandle (
ExPageLockHandle);
05090
05091 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
05092
05093
ASSERT ((MemoryDescriptorList->MdlFlags & (
MDL_IO_SPACE |
MDL_PHYSICAL_VIEW)) == 0);
05094
05095
ASSERT (((ULONG_PTR)MemoryDescriptorList->StartVa & (
PAGE_SIZE - 1)) == 0);
05096 AlignedVa = (PVOID)MemoryDescriptorList->StartVa;
05097
05098 StartingAddress = (PVOID)((PCHAR)AlignedVa +
05099 MemoryDescriptorList->ByteOffset);
05100
05101 NumberOfPages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartingAddress,
05102 MemoryDescriptorList->ByteCount);
05103
05104
MI_MAKING_MULTIPLE_PTES_INVALID (
TRUE);
05105
05106
LOCK_PFN (OldIrql);
05107
05108
do {
05109
05110
if (*Page ==
MM_EMPTY_LIST) {
05111
05112
05113
05114
05115
05116
break;
05117 }
05118
05119
ASSERT (*Page <=
MmHighestPhysicalPage);
05120
05121 Pfn1 =
MI_PFN_ELEMENT (*Page);
05122
ASSERT (Pfn1->
u2.ShareCount == 1);
05123
ASSERT (
MI_IS_PFN_DELETED (Pfn1) ==
TRUE);
05124
ASSERT (
MI_PFN_IS_AWE (Pfn1) ==
TRUE);
05125
ASSERT (Pfn1->PteFrame ==
MI_MAGIC_AWE_PTEFRAME);
05126
05127 Pfn1->u3.e1.StartOfAllocation = 0;
05128 Pfn1->u3.e1.EndOfAllocation = 0;
05129 Pfn1->u2.ShareCount = 0;
05130
#if DBG
05131
Pfn1->PteFrame -= 1;
05132 Pfn1->u3.e1.PageLocation =
StandbyPageList;
05133
#endif
05134
05135
MiDecrementReferenceCount (*Page);
05136
05137 PagesFreed += 1;
05138
05139 StartingAddress = (PVOID)((PCHAR)StartingAddress +
PAGE_SIZE);
05140
05141 *Page++ =
MM_EMPTY_LIST;
05142 NumberOfPages -= 1;
05143
05144 }
while (NumberOfPages != 0);
05145
05146
MmMdlPagesAllocated -= PagesFreed;
05147
05148
MmResidentAvailablePages += PagesFreed;
05149
MM_BUMP_COUNTER(35, PagesFreed);
05150
05151
UNLOCK_PFN (OldIrql);
05152
05153
MmUnlockPagableImageSection (
ExPageLockHandle);
05154
05155
MiReturnCommitment (PagesFreed);
05156
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_MDL_PAGES, PagesFreed);
05157 }
05158
05159
05160
NTSTATUS
05161 MmMapUserAddressesToPage (
05162 IN PVOID BaseAddress,
05163 IN SIZE_T NumberOfBytes,
05164 IN PVOID PageAddress
05165 )
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194
05195
05196
05197
05198
05199 {
05200
PMMVAD Vad;
05201
PMMPTE PointerPte;
05202
MMPTE PteContents;
05203
PMMPTE LastPte;
05204
PEPROCESS Process;
05205
NTSTATUS Status;
05206 PVOID EndingAddress;
05207 PFN_NUMBER PageFrameNumber;
05208 SIZE_T NumberOfPtes;
05209 PHYSICAL_ADDRESS PhysicalAddress;
05210 KIRQL OldIrql;
05211
05212
PAGED_CODE();
05213
05214
if (BaseAddress > MM_HIGHEST_USER_ADDRESS) {
05215
return STATUS_INVALID_PARAMETER_1;
05216 }
05217
05218
if ((ULONG_PTR)BaseAddress + NumberOfBytes > (ULONG64)MM_HIGHEST_USER_ADDRESS) {
05219
return STATUS_INVALID_PARAMETER_2;
05220 }
05221
05222 Process =
PsGetCurrentProcess();
05223
05224 EndingAddress = (PVOID)((PCHAR)BaseAddress + NumberOfBytes - 1);
05225
05226
LOCK_WS_AND_ADDRESS_SPACE (Process);
05227
05228
05229
05230
05231
05232
if (Process->
AddressSpaceDeleted != 0) {
05233
Status = STATUS_PROCESS_IS_TERMINATING;
05234
goto ErrorReturn;
05235 }
05236
05237 Vad = (
PMMVAD)
MiLocateAddress (BaseAddress);
05238
05239
if (Vad ==
NULL) {
05240
05241
05242
05243
05244
05245
Status = STATUS_MEMORY_NOT_ALLOCATED;
05246
goto ErrorReturn;
05247 }
05248
05249
if (NumberOfBytes == 0) {
05250
05251
05252
05253
05254
05255
05256
05257
if (
MI_VA_TO_VPN (BaseAddress) != Vad->
StartingVpn) {
05258
Status = STATUS_FREE_VM_NOT_AT_BASE;
05259
goto ErrorReturn;
05260 }
05261
05262 BaseAddress =
MI_VPN_TO_VA (Vad->
StartingVpn);
05263 EndingAddress =
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn);
05264 NumberOfBytes = (PCHAR)EndingAddress - (PCHAR)BaseAddress + 1;
05265 }
05266
05267
05268
05269
05270
05271
if (Vad->
EndingVpn <
MI_VA_TO_VPN (EndingAddress)) {
05272
05273
05274
05275
05276
05277
05278
Status = STATUS_INVALID_PARAMETER_2;
05279
goto ErrorReturn;
05280 }
05281
05282
if (Vad->
u.VadFlags.PhysicalMapping == 0) {
05283
05284
05285
05286
05287
05288
Status = STATUS_INVALID_ADDRESS;
05289
goto ErrorReturn;
05290 }
05291
05292 PointerPte =
MiGetPteAddress (BaseAddress);
05293 LastPte =
MiGetPteAddress (EndingAddress);
05294 NumberOfPtes = LastPte - PointerPte + 1;
05295
05296 PhysicalAddress =
MmGetPhysicalAddress (PageAddress);
05297 PageFrameNumber = (PFN_NUMBER)(PhysicalAddress.QuadPart >>
PAGE_SHIFT);
05298
05299 PteContents = *PointerPte;
05300 PteContents.
u.Hard.PageFrameNumber = PageFrameNumber;
05301
05302
#if DBG
05303
05304
05305
05306
05307
05308
05309
do {
05310
ASSERT (PointerPte->u.Hard.Valid == 1);
05311 PointerPte += 1;
05312 }
while (PointerPte < LastPte);
05313 PointerPte =
MiGetPteAddress (BaseAddress);
05314
#endif
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
LOCK_PFN (OldIrql);
05325
05326
#if !defined (_X86PAE_)
05327
MiFillMemoryPte (PointerPte,
05328 NumberOfPtes *
sizeof (
MMPTE),
05329 PteContents.
u.Long);
05330
#else
05331
05332
05333
05334
05335
05336
do {
05337
ASSERT (PointerPte->u.Hard.Valid == 1);
05338 PointerPte += 1;
05339 (
VOID)KeInterlockedSwapPte ((PHARDWARE_PTE)PointerPte,
05340 (PHARDWARE_PTE)&PteContents);
05341 }
while (PointerPte < LastPte);
05342 PointerPte =
MiGetPteAddress (BaseAddress);
05343
05344
#endif
05345
05346
if (NumberOfPtes == 1) {
05347
05348 (
VOID)
KeFlushSingleTb (BaseAddress,
05349
TRUE,
05350
TRUE,
05351 (PHARDWARE_PTE)PointerPte,
05352 PteContents.
u.Flush);
05353 }
05354
else {
05355
KeFlushEntireTb (
TRUE,
TRUE);
05356 }
05357
05358
UNLOCK_PFN (OldIrql);
05359
05360
Status = STATUS_SUCCESS;
05361
05362 ErrorReturn:
05363
05364
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
05365
05366
return Status;
05367 }
05368
05369
05370
05371
VOID
05372 MmFreeContiguousMemory (
05373 IN PVOID BaseAddress
05374 )
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398 {
05399
PAGED_CODE();
05400
05401
#if defined (_X86PAE_)
05402
if (
MiNoLowMemory ==
TRUE) {
05403
if (
MiFreeLowMemory (BaseAddress, 'tnoC') ==
TRUE) {
05404
return;
05405 }
05406 }
05407
#endif
05408
05409
ExFreePool (BaseAddress);
05410 }
05411
05412
05413
VOID
05414 MmFreeContiguousMemorySpecifyCache (
05415 IN PVOID BaseAddress,
05416 IN SIZE_T NumberOfBytes,
05417 IN MEMORY_CACHING_TYPE CacheType
05418 )
05419
05420
05421
05422
05423
05424
05425
05426
05427
05428
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448 {
05449 PVOID PoolAddress;
05450
PMMPTE PointerPte;
05451
05452
PAGED_CODE();
05453
05454
if (CacheType !=
MmCached) {
05455
05456
05457
05458
05459
05460 PointerPte =
MiGetPteAddress(BaseAddress);
05461
05462 PointerPte += ((NumberOfBytes +
PAGE_SIZE - 1) >>
PAGE_SHIFT);
05463 PoolAddress = (PVOID)(ULONG_PTR)PointerPte->
u.Long;
05464
05465 PointerPte += 1;
05466
ASSERT (NumberOfBytes == PointerPte->
u.Long);
05467
05468 NumberOfBytes += (2 *
PAGE_SIZE);
05469
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
05470 BaseAddress = PoolAddress;
05471 }
05472
else {
05473
ASSERT (BaseAddress <
MmNonPagedSystemStart ||
05474 BaseAddress >= (PVOID)((PCHAR)
MmNonPagedSystemStart + (
MmNumberOfSystemPtes <<
PAGE_SHIFT)));
05475 }
05476
05477
#if defined (_X86PAE_)
05478
if (
MiNoLowMemory ==
TRUE) {
05479
if (
MiFreeLowMemory (BaseAddress, 'tnoC') ==
TRUE) {
05480
return;
05481 }
05482 }
05483
#endif
05484
05485
ExFreePool (BaseAddress);
05486 }
05487
05488
05489 PHYSICAL_ADDRESS
05490 MmGetPhysicalAddress (
05491 IN PVOID BaseAddress
05492 )
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516 {
05517
PMMPTE PointerPte;
05518 PHYSICAL_ADDRESS PhysicalAddress;
05519
05520
if (
MI_IS_PHYSICAL_ADDRESS(BaseAddress)) {
05521 PhysicalAddress.QuadPart =
MI_CONVERT_PHYSICAL_TO_PFN (BaseAddress);
05522 }
else {
05523
05524 PointerPte =
MiGetPteAddress(BaseAddress);
05525
05526
if (PointerPte->
u.Hard.Valid == 0) {
05527 KdPrint((
"MM:MmGetPhysicalAddressFailed base address was %lx",
05528 BaseAddress));
05529
ZERO_LARGE (PhysicalAddress);
05530
return PhysicalAddress;
05531 }
05532 PhysicalAddress.QuadPart =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
05533 }
05534
05535 PhysicalAddress.QuadPart = PhysicalAddress.QuadPart <<
PAGE_SHIFT;
05536 PhysicalAddress.LowPart +=
BYTE_OFFSET(BaseAddress);
05537
05538
return PhysicalAddress;
05539 }
05540
05541 PVOID
05542 MmGetVirtualForPhysical (
05543 IN PHYSICAL_ADDRESS PhysicalAddress
05544 )
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568 {
05569 PFN_NUMBER PageFrameIndex;
05570
PMMPFN Pfn;
05571
05572 PageFrameIndex = (PFN_NUMBER)(PhysicalAddress.QuadPart >>
PAGE_SHIFT);
05573
05574 Pfn =
MI_PFN_ELEMENT (PageFrameIndex);
05575
05576
return (PVOID)((PCHAR)
MiGetVirtualAddressMappedByPte (Pfn->
PteAddress) +
05577
BYTE_OFFSET (PhysicalAddress.LowPart));
05578 }
05579
05580 PVOID
05581 MmAllocateNonCachedMemory (
05582 IN SIZE_T NumberOfBytes
05583 )
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614 {
05615
PMMPTE PointerPte;
05616
MMPTE TempPte;
05617 PFN_NUMBER NumberOfPages;
05618 PFN_NUMBER PageFrameIndex;
05619 PVOID BaseAddress;
05620 KIRQL OldIrql;
05621
05622
ASSERT (NumberOfBytes != 0);
05623
05624 NumberOfPages =
BYTES_TO_PAGES(NumberOfBytes);
05625
05626
05627
05628
05629
05630 PointerPte =
MiReserveSystemPtes ((ULONG)NumberOfPages,
05631
SystemPteSpace,
05632 0,
05633 0,
05634
FALSE);
05635
05636
if (PointerPte ==
NULL) {
05637
return NULL;
05638 }
05639
05640
05641
05642
05643
05644
if (
MiChargeCommitmentCantExpand (NumberOfPages,
FALSE) ==
FALSE) {
05645
MiReleaseSystemPtes (PointerPte, (ULONG)NumberOfPages,
SystemPteSpace);
05646
return NULL;
05647 }
05648
05649
MM_TRACK_COMMIT (
MM_DBG_COMMIT_NONCACHED_PAGES, NumberOfPages);
05650
05651
MmLockPagableSectionByHandle (
ExPageLockHandle);
05652
05653
05654
05655
05656
05657
LOCK_PFN (OldIrql);
05658
05659
05660
05661
05662
05663
05664
if ((SPFN_NUMBER)NumberOfPages >
MI_NONPAGABLE_MEMORY_AVAILABLE()) {
05665
UNLOCK_PFN (OldIrql);
05666
MmUnlockPagableImageSection (
ExPageLockHandle);
05667
MiReleaseSystemPtes (PointerPte, (ULONG)NumberOfPages,
SystemPteSpace);
05668
MiReturnCommitment (NumberOfPages);
05669
return NULL;
05670 }
05671
05672
#if defined(_IA64_)
05673
KeFlushEntireTb(
FALSE,
TRUE);
05674
#endif
05675
05676
MmResidentAvailablePages -= NumberOfPages;
05677
MM_BUMP_COUNTER(4, NumberOfPages);
05678
05679 BaseAddress = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte);
05680
05681
do {
05682
ASSERT (PointerPte->
u.Hard.Valid == 0);
05683
MiEnsureAvailablePageOrWait (
NULL,
NULL);
05684 PageFrameIndex =
MiRemoveAnyPage (
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
05685
05686
MI_MAKE_VALID_PTE (TempPte,
05687 PageFrameIndex,
05688
MM_READWRITE,
05689 PointerPte);
05690
05691
MI_SET_PTE_DIRTY (TempPte);
05692
MI_DISABLE_CACHING (TempPte);
05693
MI_WRITE_VALID_PTE (PointerPte, TempPte);
05694
MiInitializePfn (PageFrameIndex, PointerPte, 1);
05695
05696 PointerPte += 1;
05697 NumberOfPages -= 1;
05698 }
while (NumberOfPages != 0);
05699
05700
05701
05702
05703
05704
#if !defined(_IA64_)
05705
05706
05707
05708
05709
KeSweepDcache (
TRUE);
05710
#else
05711
MiSweepCacheMachineDependent(BaseAddress, NumberOfBytes,
MmNonCached);
05712
#endif
05713
05714
UNLOCK_PFN (OldIrql);
05715
MmUnlockPagableImageSection (
ExPageLockHandle);
05716
05717
return BaseAddress;
05718 }
05719
05720
VOID
05721 MmFreeNonCachedMemory (
05722 IN PVOID BaseAddress,
05723 IN SIZE_T NumberOfBytes
05724 )
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751
05752 {
05753
05754
PMMPTE PointerPte;
05755
PMMPFN Pfn1;
05756 PFN_NUMBER NumberOfPages;
05757 PFN_NUMBER i;
05758 PFN_NUMBER PageFrameIndex;
05759 KIRQL OldIrql;
05760
05761
ASSERT (NumberOfBytes != 0);
05762
ASSERT (
PAGE_ALIGN (BaseAddress) == BaseAddress);
05763
05764
MI_MAKING_MULTIPLE_PTES_INVALID (
TRUE);
05765
05766 NumberOfPages =
BYTES_TO_PAGES(NumberOfBytes);
05767
05768 PointerPte =
MiGetPteAddress (BaseAddress);
05769
05770 i = NumberOfPages;
05771
05772
MmLockPagableSectionByHandle (
ExPageLockHandle);
05773
05774
LOCK_PFN (OldIrql);
05775
05776
do {
05777
05778 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
05779
05780
05781
05782
05783
05784 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05785
ASSERT (Pfn1->
u2.ShareCount == 1);
05786
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
05787
MI_SET_PFN_DELETED (Pfn1);
05788
MiDecrementShareCountOnly (PageFrameIndex);
05789 PointerPte += 1;
05790 i -= 1;
05791 }
while (i != 0);
05792
05793 PointerPte -= NumberOfPages;
05794
05795
05796
05797
05798
05799
MmResidentAvailablePages += NumberOfPages;
05800
MM_BUMP_COUNTER(5, NumberOfPages);
05801
05802
UNLOCK_PFN (OldIrql);
05803
05804
MmUnlockPagableImageSection (
ExPageLockHandle);
05805
05806
MiReleaseSystemPtes (PointerPte, (ULONG)NumberOfPages,
SystemPteSpace);
05807
05808
MiReturnCommitment (NumberOfPages);
05809
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_NONCACHED_PAGES, NumberOfPages);
05810
05811
return;
05812 }
05813
05814 SIZE_T
05815 MmSizeOfMdl (
05816 IN PVOID Base,
05817 IN SIZE_T Length
05818 )
05819
05820
05821
05822
05823
05824
05825
05826
05827
05828
05829
05830
05831
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843 {
05844
return(
sizeof(
MDL ) +
05845 (
ADDRESS_AND_SIZE_TO_SPAN_PAGES( Base, Length ) *
05846
sizeof( PFN_NUMBER ))
05847 );
05848 }
05849
05850
05851
PMDL
05852 MmCreateMdl (
05853 IN
PMDL MemoryDescriptorList OPTIONAL,
05854 IN PVOID Base,
05855 IN SIZE_T Length
05856 )
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883
05884
05885 {
05886 SIZE_T MdlSize;
05887
05888 MdlSize =
MmSizeOfMdl( Base, Length );
05889
05890
if (!ARGUMENT_PRESENT( MemoryDescriptorList )) {
05891
05892
05893
05894
05895
05896
05897
05898
if (MdlSize >
POOL_BUDDY_MAX) {
05899 MemoryDescriptorList = (
PMDL)
ExAllocatePoolWithTag (
05900
NonPagedPool,
05901 MdlSize,
05902 'ldmM');
05903
if (MemoryDescriptorList == (
PMDL)0) {
05904
return (
PMDL)0;
05905 }
05906 }
05907
else {
05908 MemoryDescriptorList = (
PMDL)
ExAllocatePoolWithTag (
05909
NonPagedPoolMustSucceed,
05910 MdlSize,
05911 'ldmM');
05912 }
05913 }
05914
05915
MmInitializeMdl (MemoryDescriptorList, Base, Length);
05916
return MemoryDescriptorList;
05917 }
05918
05919 BOOLEAN
05920 MmSetAddressRangeModified (
05921 IN PVOID Address,
05922 IN SIZE_T Length
05923 )
05924
05925
05926
05927
05928
05929
05930
05931
05932
05933
05934
05935
05936
05937
05938
05939
05940
05941
05942
05943
05944
05945
05946
05947
05948
05949
05950
05951
05952 {
05953
PMMPTE PointerPte;
05954
PMMPTE LastPte;
05955
PMMPFN Pfn1;
05956
PMMPTE FlushPte;
05957
MMPTE PteContents;
05958
MMPTE FlushContents;
05959 KIRQL OldIrql;
05960 PVOID VaFlushList[
MM_MAXIMUM_FLUSH_COUNT];
05961 ULONG
Count;
05962 BOOLEAN Result;
05963
05964
Count = 0;
05965 Result =
FALSE;
05966
05967
05968
05969
05970
05971
05972 PointerPte =
MiGetPteAddress (Address);
05973 LastPte =
MiGetPteAddress ((PVOID)((PCHAR)Address + Length - 1));
05974
05975
LOCK_PFN2 (OldIrql);
05976
05977
do {
05978
05979 PteContents = *PointerPte;
05980
05981
if (PteContents.
u.Hard.Valid == 1) {
05982
05983 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
05984 Pfn1->
u3.e1.Modified = 1;
05985
05986
if ((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
05987 (Pfn1->
u3.e1.WriteInProgress == 0)) {
05988
MiReleasePageFileSpace (Pfn1->
OriginalPte);
05989 Pfn1->
OriginalPte.
u.Soft.PageFileHigh = 0;
05990 }
05991
05992
#ifdef NT_UP
05993
05994
05995
05996
05997
05998
if (
MI_IS_PTE_DIRTY (PteContents)) {
05999 Result =
TRUE;
06000
#else //NT_UP
06001
Result |= (BOOLEAN)(
MI_IS_PTE_DIRTY (PteContents));
06002
#endif //NT_UP
06003
MI_SET_PTE_CLEAN (PteContents);
06004
MI_WRITE_VALID_PTE_NEW_PROTECTION (PointerPte, PteContents);
06005 FlushContents = PteContents;
06006 FlushPte = PointerPte;
06007
06008
06009
06010
06011
06012
if (
Count !=
MM_MAXIMUM_FLUSH_COUNT) {
06013 VaFlushList[
Count] = Address;
06014
Count += 1;
06015 }
06016
#ifdef NT_UP
06017
}
06018
#endif //NT_UP
06019
}
06020 PointerPte += 1;
06021 Address = (PVOID)((PCHAR)Address +
PAGE_SIZE);
06022 }
while (PointerPte <= LastPte);
06023
06024
if (
Count != 0) {
06025
if (
Count == 1) {
06026
06027 (
VOID)
KeFlushSingleTb (VaFlushList[0],
06028
FALSE,
06029
TRUE,
06030 (PHARDWARE_PTE)FlushPte,
06031 FlushContents.
u.Flush);
06032
06033 }
else if (
Count !=
MM_MAXIMUM_FLUSH_COUNT) {
06034
06035
KeFlushMultipleTb (
Count,
06036 &VaFlushList[0],
06037
FALSE,
06038
TRUE,
06039
NULL,
06040 *(PHARDWARE_PTE)&
ZeroPte.
u.Flush);
06041
06042 }
else {
06043
KeFlushEntireTb (
FALSE,
TRUE);
06044 }
06045 }
06046
UNLOCK_PFN2 (OldIrql);
06047
return Result;
06048 }
06049
06050
06051 PVOID
06052 MiCheckForContiguousMemory (
06053 IN PVOID BaseAddress,
06054 IN PFN_NUMBER BaseAddressPages,
06055 IN PFN_NUMBER SizeInPages,
06056 IN PFN_NUMBER LowestPfn,
06057 IN PFN_NUMBER HighestPfn,
06058 IN PFN_NUMBER BoundaryPfn
06059 )
06060
06061
06062
06063
06064
06065
06066
06067
06068
06069
06070
06071
06072
06073
06074
06075
06076
06077
06078
06079
06080
06081
06082
06083
06084
06085
06086
06087
06088
06089
06090
06091
06092
06093
06094
06095
06096
06097
06098 {
06099
PMMPTE PointerPte;
06100
PMMPTE LastPte;
06101 PFN_NUMBER PreviousPage;
06102 PFN_NUMBER Page;
06103 PFN_NUMBER HighestStartPage;
06104 PFN_NUMBER LastPage;
06105 PFN_NUMBER OriginalPage;
06106 PFN_NUMBER OriginalLastPage;
06107 PVOID BoundaryAllocation;
06108 PFN_NUMBER BoundaryMask;
06109 ULONG PageCount;
06110
MMPTE PteContents;
06111
06112 BoundaryMask = ~(BoundaryPfn - 1);
06113
06114
if (LowestPfn > HighestPfn) {
06115
return NULL;
06116 }
06117
06118
if (LowestPfn + SizeInPages <= LowestPfn) {
06119
return NULL;
06120 }
06121
06122
if (LowestPfn + SizeInPages > HighestPfn + 1) {
06123
return NULL;
06124 }
06125
06126
if (BaseAddressPages < SizeInPages) {
06127
return NULL;
06128 }
06129
06130
if (
MI_IS_PHYSICAL_ADDRESS (BaseAddress)) {
06131
06132 OriginalPage =
MI_CONVERT_PHYSICAL_TO_PFN(BaseAddress);
06133 OriginalLastPage = OriginalPage + BaseAddressPages;
06134
06135 Page = OriginalPage;
06136 LastPage = OriginalLastPage;
06137
06138
06139
06140
06141
06142
if (Page < LowestPfn) {
06143 Page = LowestPfn;
06144 }
06145
06146
if (LastPage > HighestPfn + 1) {
06147 LastPage = HighestPfn + 1;
06148 }
06149
06150 HighestStartPage = LastPage - SizeInPages;
06151
06152
if (Page > HighestStartPage) {
06153
return NULL;
06154 }
06155
06156
if (BoundaryPfn != 0) {
06157
do {
06158
if (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask) == 0) {
06159
06160
06161
06162
06163
06164
06165
break;
06166 }
06167 Page |= (BoundaryPfn - 1);
06168 Page += 1;
06169 }
while (Page <= HighestStartPage);
06170
06171
if (Page > HighestStartPage) {
06172
return NULL;
06173 }
06174 BoundaryAllocation = (PVOID)((PCHAR)BaseAddress + ((Page - OriginalPage) <<
PAGE_SHIFT));
06175
06176
06177
06178
06179
06180
06181
return BoundaryAllocation;
06182 }
06183
06184
06185
06186
06187
06188
if (LastPage == OriginalLastPage) {
06189
return (PVOID)((PCHAR)BaseAddress + ((BaseAddressPages - SizeInPages) <<
PAGE_SHIFT));
06190 }
06191
06192
06193
06194
06195
06196
06197
06198
return (PVOID)((PCHAR)BaseAddress + ((Page - OriginalPage) <<
PAGE_SHIFT));
06199 }
06200
06201
06202
06203
06204
06205 PointerPte =
MiGetPteAddress (BaseAddress);
06206 LastPte = PointerPte + BaseAddressPages;
06207
06208 HighestStartPage = HighestPfn + 1 - SizeInPages;
06209 PageCount = 0;
06210
06211
while (PointerPte < LastPte) {
06212
06213 PteContents = *PointerPte;
06214
ASSERT (PteContents.
u.Hard.Valid == 1);
06215 Page =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
06216
06217
06218
06219
06220
06221
06222
if (PageCount == 0) {
06223
06224
if ((Page >= LowestPfn) && (Page <= HighestStartPage)) {
06225
06226
if (BoundaryPfn == 0) {
06227 PageCount += 1;
06228 }
06229
else if (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask) == 0) {
06230
06231
06232
06233
06234
06235 PageCount += 1;
06236 }
06237 }
06238
06239
if (PageCount == SizeInPages) {
06240
06241
06242
06243
06244
06245 BaseAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
06246
return BaseAddress;
06247 }
06248
06249 PreviousPage = Page;
06250 PointerPte += 1;
06251
continue;
06252 }
06253
06254
if (Page != PreviousPage + 1) {
06255
06256
06257
06258
06259
06260 PageCount = 0;
06261
continue;
06262 }
06263
06264 PageCount += 1;
06265
06266
if (PageCount == SizeInPages) {
06267
06268
06269
06270
06271
06272 BaseAddress =
MiGetVirtualAddressMappedByPte (PointerPte - PageCount + 1);
06273
return BaseAddress;
06274 }
06275
06276 PointerPte += 1;
06277 }
06278
06279
return NULL;
06280 }
06281
06282
06283
VOID
06284 MmLockPagableSectionByHandle (
06285 IN PVOID ImageSectionHandle
06286 )
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326 {
06327 PIMAGE_SECTION_HEADER NtSection;
06328 PVOID BaseAddress;
06329 ULONG SizeToLock;
06330
PMMPTE PointerPte;
06331
PMMPTE LastPte;
06332 KIRQL OldIrql;
06333 KIRQL OldIrqlWs;
06334 ULONG Collision;
06335
06336
if (
MI_IS_PHYSICAL_ADDRESS(ImageSectionHandle)) {
06337
06338
06339
06340
06341
06342
return;
06343 }
06344
06345 NtSection = (PIMAGE_SECTION_HEADER)ImageSectionHandle;
06346
06347 BaseAddress =
SECTION_BASE_ADDRESS(NtSection);
06348
06349
ASSERT (!
MI_IS_SYSTEM_CACHE_ADDRESS(BaseAddress));
06350
06351
ASSERT (BaseAddress >=
MmSystemRangeStart);
06352
06353 SizeToLock = NtSection->SizeOfRawData;
06354 PointerPte =
MiGetPteAddress(BaseAddress);
06355 LastPte =
MiGetPteAddress((PCHAR)BaseAddress + SizeToLock - 1);
06356
06357
ASSERT (SizeToLock != 0);
06358
06359
06360
06361
06362
06363 RetryLock:
06364
06365
LOCK_SYSTEM_WS (OldIrqlWs);
06366
LOCK_PFN2 (OldIrql);
06367
06368
MiMakeSystemAddressValidPfnSystemWs (&NtSection->NumberOfLinenumbers);
06369
06370
06371
06372
06373
06374
06375
06376
06377
06378
06379
06380
06381
06382 NtSection->NumberOfLinenumbers += 1;
06383
06384
if (NtSection->NumberOfLinenumbers >= 3) {
06385
06386
06387
06388
06389
06390
UNLOCK_PFN2 (OldIrql);
06391
UNLOCK_SYSTEM_WS (OldIrqlWs);
06392
return;
06393 }
06394
06395
if (NtSection->NumberOfLinenumbers == 2) {
06396
06397
06398
06399
06400
06401
06402 NtSection->NumberOfLinenumbers = 1;
06403
MmCollidedLockWait =
TRUE;
06404
06405
KeEnterCriticalRegion();
06406
06407
06408
06409
06410
06411
06412
UNLOCK_SYSTEM_WS_NO_IRQL ();
06413
UNLOCK_PFN_AND_THEN_WAIT (OldIrqlWs);
06414
06415
KeWaitForSingleObject(&
MmCollidedLockEvent,
06416
WrVirtualMemory,
06417
KernelMode,
06418
FALSE,
06419 (PLARGE_INTEGER)
NULL);
06420
KeLeaveCriticalRegion();
06421
goto RetryLock;
06422 }
06423
06424
06425
06426
06427
06428
06429
MiLockCode (PointerPte, LastPte,
MM_LOCK_BY_REFCOUNT);
06430
06431
06432
06433
06434
06435
06436
MiMakeSystemAddressValidPfnSystemWs (&NtSection->NumberOfLinenumbers);
06437 NtSection->NumberOfLinenumbers += 1;
06438
06439
ASSERT (NtSection->NumberOfLinenumbers == 2);
06440
06441 Collision =
MmCollidedLockWait;
06442
MmCollidedLockWait =
FALSE;
06443
06444
UNLOCK_PFN2 (OldIrql);
06445
UNLOCK_SYSTEM_WS (OldIrqlWs);
06446
06447
if (Collision) {
06448
06449
06450
06451
06452
06453
KePulseEvent (&
MmCollidedLockEvent, 0,
FALSE);
06454 }
06455
06456
return;
06457 }
06458
06459
06460
VOID
06461 MiLockCode (
06462 IN
PMMPTE FirstPte,
06463 IN
PMMPTE LastPte,
06464 IN ULONG LockType
06465 )
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490
06491
06492
06493
06494
06495
06496
06497
06498
06499
06500
06501
06502
06503
06504
06505
06506
06507
06508
06509 {
06510
PMMPFN Pfn1;
06511
PMMPTE PointerPte;
06512
MMPTE TempPte;
06513
MMPTE PteContents;
06514
WSLE_NUMBER WorkingSetIndex;
06515
WSLE_NUMBER SwapEntry;
06516 PFN_NUMBER PageFrameIndex;
06517 KIRQL OldIrql;
06518 LOGICAL SessionSpace;
06519
PMMWSL WorkingSetList;
06520
PMMSUPPORT Vm;
06521
#if PFN_CONSISTENCY
06522
KIRQL PfnIrql;
06523
#endif
06524
06525
MM_PFN_LOCK_ASSERT();
06526
06527 SessionSpace =
MI_IS_SESSION_IMAGE_ADDRESS (
MiGetVirtualAddressMappedByPte(FirstPte));
06528
06529
if (SessionSpace ==
TRUE) {
06530 Vm = &
MmSessionSpace->
Vm;
06531 WorkingSetList =
MmSessionSpace->
Vm.
VmWorkingSetList;
06532 }
06533
06534
06535
06536
06537
06538
ASSERT ((SessionSpace ==
FALSE) || (LockType !=
MM_LOCK_BY_REFCOUNT));
06539
06540
ASSERT (!
MI_IS_PHYSICAL_ADDRESS(
MiGetVirtualAddressMappedByPte(FirstPte)));
06541 PointerPte = FirstPte;
06542
06543
MmLockedCode += 1 + LastPte - FirstPte;
06544
06545
do {
06546
06547 PteContents = *PointerPte;
06548
ASSERT (PteContents.
u.Long !=
ZeroKernelPte.
u.Long);
06549
if (PteContents.
u.Hard.Valid == 0) {
06550
06551
if (PteContents.
u.Soft.Prototype == 1) {
06552
06553
06554
06555
06556
06557
MiMakeSystemAddressValidPfnSystemWs (
06558
MiGetVirtualAddressMappedByPte(PointerPte));
06559
06560
continue;
06561 }
06562
else if (PteContents.
u.Soft.Transition == 1) {
06563
06564 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
06565
06566 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06567
if ((Pfn1->
u3.e1.ReadInProgress) ||
06568 (Pfn1->
u3.e1.InPageError)) {
06569
06570
06571
06572
06573
06574
MiMakeSystemAddressValidPfnSystemWs (
06575
MiGetVirtualAddressMappedByPte(PointerPte));
06576
06577
continue;
06578 }
06579
06580
06581
06582
06583
06584
06585
06586
if (Pfn1->
u3.e1.PageLocation ==
ActiveAndValid) {
06587
06588
ASSERT (((Pfn1->
PteAddress >=
MiGetPteAddress(
MmPagedPoolStart)) &&
06589 (Pfn1->
PteAddress <=
MiGetPteAddress(
MmPagedPoolEnd))) ||
06590 ((Pfn1->
PteAddress >=
MiGetPteAddress(
MmSpecialPoolStart)) &&
06591 (Pfn1->
PteAddress <=
MiGetPteAddress(
MmSpecialPoolEnd))));
06592
06593
06594
06595
06596
06597
06598
ASSERT (Pfn1->
u2.ShareCount != 0);
06599
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
06600 Pfn1->
u2.ShareCount += 1;
06601 }
06602
else {
06603
06604
MiUnlinkPageFromList (Pfn1);
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614 Pfn1->
u3.e2.ReferenceCount += 1;
06615 Pfn1->
u2.ShareCount = 1;
06616 }
06617
06618 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
06619
06620
MI_MAKE_VALID_PTE (TempPte,
06621 PageFrameIndex,
06622 Pfn1->
OriginalPte.
u.Soft.Protection,
06623 PointerPte);
06624
06625
MI_WRITE_VALID_PTE (PointerPte, TempPte);
06626
06627
06628
06629
06630
06631
06632
if (LockType ==
MM_LOCK_BY_REFCOUNT) {
06633
06634
06635
06636
06637
06638
06639
MI_ADD_LOCKED_PAGE_CHARGE (Pfn1, 34);
06640 Pfn1->
u3.e2.ReferenceCount += 1;
06641 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
06642
06643
UNLOCK_PFN (
APC_LEVEL);
06644 WorkingSetIndex =
MiLocateAndReserveWsle (&
MmSystemCacheWs);
06645
06646
MiUpdateWsle (&WorkingSetIndex,
06647
MiGetVirtualAddressMappedByPte (PointerPte),
06648
MmSystemCacheWorkingSetList,
06649 Pfn1);
06650
06651
MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex);
06652
06653
LOCK_PFN (OldIrql);
06654
06655 }
else {
06656
06657
06658
06659
06660
06661
06662
ASSERT (Pfn1->
u1.WsIndex == 0);
06663
06664
06665
06666
06667
06668
06669
06670
06671
MmResidentAvailablePages -= 1;
06672
if (Pfn1->
u3.e1.PrototypePte == 0) {
06673
MmTotalSystemDriverPages -= 1;
06674 }
06675
MM_BUMP_COUNTER(29, 1);
06676 }
06677 }
else {
06678
06679
06680
06681
06682
06683
MiMakeSystemAddressValidPfnSystemWs (
06684
MiGetVirtualAddressMappedByPte(PointerPte));
06685
06686
continue;
06687 }
06688
06689 }
06690
else {
06691
06692
06693
06694
06695
06696 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
06697
06698
06699
06700
06701
06702
MI_ADD_LOCKED_PAGE_CHARGE (Pfn1, 36);
06703 Pfn1->
u3.e2.ReferenceCount += 1;
06704
06705
if (LockType !=
MM_LOCK_BY_REFCOUNT) {
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
if (Pfn1->
u1.WsIndex != 0) {
06722
06723
UNLOCK_PFN (
APC_LEVEL);
06724
06725
if (SessionSpace ==
TRUE) {
06726
06727 WorkingSetIndex =
MiLocateWsle (
06728
MiGetVirtualAddressMappedByPte(PointerPte),
06729 WorkingSetList,
06730 Pfn1->
u1.WsIndex);
06731
06732
if (WorkingSetIndex >= WorkingSetList->
FirstDynamic) {
06733
06734 SwapEntry = WorkingSetList->
FirstDynamic;
06735
06736
if (WorkingSetIndex != WorkingSetList->
FirstDynamic) {
06737
06738
06739
06740
06741
06742
06743
06744
MiSwapWslEntries (WorkingSetIndex,
06745 SwapEntry,
06746 Vm);
06747 }
06748
06749 WorkingSetList->
FirstDynamic += 1;
06750 }
06751
else {
06752 SwapEntry = WorkingSetIndex;
06753 }
06754
06755
06756
06757
06758
06759
MmSessionSpace->
Wsle[SwapEntry].
u1.e1.LockedInWs = 1;
06760 }
06761
else {
06762
MiRemoveWsle (Pfn1->
u1.WsIndex,
MmSystemCacheWorkingSetList);
06763
MiReleaseWsle (Pfn1->
u1.WsIndex, &
MmSystemCacheWs);
06764
06765
MI_SET_PTE_IN_WORKING_SET (PointerPte, 0);
06766 }
06767
06768
LOCK_PFN (OldIrql);
06769
06770
MI_ZERO_WSINDEX (Pfn1);
06771
06772
06773
06774
06775
06776
06777
MmResidentAvailablePages -= 1;
06778
MM_BUMP_COUNTER(29, 1);
06779
if (Pfn1->
u3.e1.PrototypePte == 0) {
06780
MmTotalSystemDriverPages -= 1;
06781 }
06782 }
06783
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
06784
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 37);
06785 Pfn1->
u3.e2.ReferenceCount -= 1;
06786 }
06787 }
06788
06789 PointerPte += 1;
06790 }
while (PointerPte <= LastPte);
06791
06792
return;
06793 }
06794
06795
06796
NTSTATUS
06797 MmGetSectionRange(
06798 IN PVOID AddressWithinSection,
06799 OUT PVOID *StartingSectionAddress,
06800 OUT PULONG SizeofSection
06801 )
06802 {
06803 PLDR_DATA_TABLE_ENTRY DataTableEntry;
06804 ULONG i;
06805 PIMAGE_NT_HEADERS NtHeaders;
06806 PIMAGE_SECTION_HEADER NtSection;
06807
NTSTATUS Status;
06808 ULONG_PTR Rva;
06809
06810
PAGED_CODE();
06811
06812
06813
06814
06815
06816
06817
06818
06819
Status = STATUS_NOT_FOUND;
06820
06821
KeEnterCriticalRegion();
06822
ExAcquireResourceShared (&
PsLoadedModuleResource,
TRUE);
06823
06824 DataTableEntry =
MiLookupDataTableEntry (AddressWithinSection,
TRUE);
06825
if (DataTableEntry) {
06826
06827 Rva = (ULONG_PTR)((PUCHAR)AddressWithinSection - (ULONG_PTR)DataTableEntry->DllBase);
06828
06829 NtHeaders = (PIMAGE_NT_HEADERS)
RtlImageNtHeader(DataTableEntry->DllBase);
06830
06831 NtSection = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders +
06832
sizeof(ULONG) +
06833
sizeof(IMAGE_FILE_HEADER) +
06834 NtHeaders->FileHeader.SizeOfOptionalHeader
06835 );
06836
06837
for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i += 1) {
06838
06839
if ( Rva >= NtSection->VirtualAddress &&
06840 Rva < NtSection->VirtualAddress + NtSection->SizeOfRawData ) {
06841
06842
06843
06844
06845
06846 *StartingSectionAddress = (PVOID)
06847 ((PCHAR) DataTableEntry->DllBase + NtSection->VirtualAddress);
06848 *SizeofSection = NtSection->SizeOfRawData;
06849
Status = STATUS_SUCCESS;
06850
break;
06851 }
06852
06853 NtSection += 1;
06854 }
06855 }
06856
06857
ExReleaseResource (&
PsLoadedModuleResource);
06858
KeLeaveCriticalRegion();
06859
return Status;
06860 }
06861
06862
06863 PVOID
06864 MmLockPagableDataSection(
06865 IN PVOID AddressWithinSection
06866 )
06867
06868
06869
06870
06871
06872
06873
06874
06875
06876
06877
06878
06879
06880
06881
06882
06883
06884
06885
06886
06887
06888
06889
06890 {
06891 PLDR_DATA_TABLE_ENTRY DataTableEntry;
06892 ULONG i;
06893 PIMAGE_NT_HEADERS NtHeaders;
06894 PIMAGE_SECTION_HEADER NtSection;
06895 PIMAGE_SECTION_HEADER FoundSection;
06896 ULONG_PTR Rva;
06897
06898
PAGED_CODE();
06899
06900
if (
MI_IS_PHYSICAL_ADDRESS(AddressWithinSection)) {
06901
06902
06903
06904
06905
06906
return AddressWithinSection;
06907 }
06908
06909
06910
06911
06912
06913
06914
06915
06916 FoundSection =
NULL;
06917
06918
KeEnterCriticalRegion();
06919
ExAcquireResourceShared (&
PsLoadedModuleResource,
TRUE);
06920
06921 DataTableEntry =
MiLookupDataTableEntry (AddressWithinSection,
TRUE);
06922
06923 Rva = (ULONG_PTR)((PUCHAR)AddressWithinSection - (ULONG_PTR)DataTableEntry->DllBase);
06924
06925 NtHeaders = (PIMAGE_NT_HEADERS)
RtlImageNtHeader(DataTableEntry->DllBase);
06926
06927 NtSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders +
06928
sizeof(ULONG) +
06929
sizeof(IMAGE_FILE_HEADER) +
06930 NtHeaders->FileHeader.SizeOfOptionalHeader
06931 );
06932
06933
for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i += 1) {
06934
06935
if ( Rva >= NtSection->VirtualAddress &&
06936 Rva < NtSection->VirtualAddress + NtSection->SizeOfRawData ) {
06937 FoundSection = NtSection;
06938
06939
if (
SECTION_BASE_ADDRESS(NtSection) != ((PUCHAR)DataTableEntry->DllBase +
06940 NtSection->VirtualAddress)) {
06941
06942
06943
06944
06945
06946
06947
06948
06949
SECTION_BASE_ADDRESS(NtSection) = ((PUCHAR)DataTableEntry->DllBase +
06950 NtSection->VirtualAddress);
06951 NtSection->NumberOfLinenumbers = 0;
06952 }
06953
06954
06955
06956
06957
06958
#if DBG
06959
if (MmDebug &
MM_DBG_LOCK_CODE) {
06960
DbgPrint(
"MM Lock %wZ %8s %p -> %p : %p %3ld.\n",
06961 &DataTableEntry->BaseDllName,
06962 NtSection->Name,
06963 AddressWithinSection,
06964 NtSection,
06965
SECTION_BASE_ADDRESS(NtSection),
06966 NtSection->NumberOfLinenumbers);
06967 }
06968
#endif //DBG
06969
06970
MmLockPagableSectionByHandle ((PVOID)NtSection);
06971
06972
break;
06973 }
06974 NtSection += 1;
06975 }
06976
06977
ExReleaseResource (&
PsLoadedModuleResource);
06978
KeLeaveCriticalRegion();
06979
if (!FoundSection) {
06980
KeBugCheckEx (MEMORY_MANAGEMENT,
06981 0x1234,
06982 (ULONG_PTR)AddressWithinSection,
06983 0,
06984 0);
06985 }
06986
return (PVOID)FoundSection;
06987 }
06988
06989
06990 PLDR_DATA_TABLE_ENTRY
06991 MiLookupDataTableEntry (
06992 IN PVOID AddressWithinSection,
06993 IN ULONG ResourceHeld
06994 )
06995
06996
06997
06998
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017 {
07018 PLDR_DATA_TABLE_ENTRY DataTableEntry;
07019 PLDR_DATA_TABLE_ENTRY FoundEntry =
NULL;
07020 PLIST_ENTRY NextEntry;
07021
07022
PAGED_CODE();
07023
07024
07025
07026
07027
07028
07029
07030
07031
if (!ResourceHeld) {
07032
KeEnterCriticalRegion();
07033
ExAcquireResourceShared (&
PsLoadedModuleResource,
TRUE);
07034 }
07035
07036 NextEntry =
PsLoadedModuleList.Flink;
07037
do {
07038
07039 DataTableEntry = CONTAINING_RECORD(NextEntry,
07040 LDR_DATA_TABLE_ENTRY,
07041 InLoadOrderLinks);
07042
07043
07044
07045
07046
07047
if ( AddressWithinSection >= DataTableEntry->DllBase &&
07048 AddressWithinSection < (PVOID)((PUCHAR)DataTableEntry->DllBase+DataTableEntry->SizeOfImage) ) {
07049
07050 FoundEntry = DataTableEntry;
07051
break;
07052 }
07053
07054 NextEntry = NextEntry->Flink;
07055 }
while (NextEntry != &
PsLoadedModuleList);
07056
07057
if (!ResourceHeld) {
07058
ExReleaseResource (&
PsLoadedModuleResource);
07059
KeLeaveCriticalRegion();
07060 }
07061
return FoundEntry;
07062 }
07063
07064
VOID
07065 MmUnlockPagableImageSection(
07066 IN PVOID ImageSectionHandle
07067 )
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087 {
07088 PIMAGE_SECTION_HEADER NtSection;
07089
PMMPTE PointerPte;
07090
PMMPTE LastPte;
07091 PFN_NUMBER PageFrameIndex;
07092
PMMPFN Pfn1;
07093 KIRQL OldIrql;
07094 PVOID BaseAddress;
07095 ULONG SizeToUnlock;
07096 ULONG Collision;
07097
07098
if (
MI_IS_PHYSICAL_ADDRESS(ImageSectionHandle)) {
07099
07100
07101
07102
07103
07104
return;
07105 }
07106
07107 NtSection = (PIMAGE_SECTION_HEADER)ImageSectionHandle;
07108
07109 BaseAddress =
SECTION_BASE_ADDRESS(NtSection);
07110 SizeToUnlock = NtSection->SizeOfRawData;
07111
07112 PointerPte =
MiGetPteAddress(BaseAddress);
07113 LastPte =
MiGetPteAddress((PCHAR)BaseAddress + SizeToUnlock - 1);
07114
07115
07116
07117
07118
07119
LOCK_PFN2 (OldIrql);
07120
07121
07122
07123
07124
07125
07126
ASSERT (NtSection->NumberOfLinenumbers >= 2);
07127 NtSection->NumberOfLinenumbers -= 1;
07128
07129
if (NtSection->NumberOfLinenumbers != 1) {
07130
UNLOCK_PFN2 (OldIrql);
07131
return;
07132 }
07133
07134
do {
07135
ASSERT (PointerPte->
u.Hard.Valid == 1);
07136
07137 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
07138 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
07139
07140
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
07141
07142
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 37);
07143
07144
MiDecrementReferenceCount (PageFrameIndex);
07145
07146 PointerPte += 1;
07147
07148 }
while (PointerPte <= LastPte);
07149
07150 NtSection->NumberOfLinenumbers -= 1;
07151
ASSERT (NtSection->NumberOfLinenumbers == 0);
07152 Collision =
MmCollidedLockWait;
07153
MmCollidedLockWait =
FALSE;
07154
MmLockedCode -= SizeToUnlock;
07155
07156
UNLOCK_PFN2 (OldIrql);
07157
07158
if (Collision) {
07159
KePulseEvent (&
MmCollidedLockEvent, 0,
FALSE);
07160 }
07161
07162
return;
07163 }
07164
07165
07166 BOOLEAN
07167 MmIsRecursiveIoFault(
07168 VOID
07169 )
07170
07171
07172
07173
07174
07175
07176
07177
07178
07179
07180
07181
07182
07183
07184
07185
07186
07187
07188
07189
07190 {
07191
return (BOOLEAN)(
PsGetCurrentThread()->DisablePageFaultClustering |
07192
PsGetCurrentThread()->ForwardClusterOnly);
07193 }
07194
07195
07196
VOID
07197 MmMapMemoryDumpMdl(
07198 IN OUT
PMDL MemoryDumpMdl
07199 )
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07217
07218
07219 {
07220 PFN_NUMBER NumberOfPages;
07221
PMMPTE PointerPte;
07222 PCHAR BaseVa;
07223
MMPTE TempPte;
07224 PPFN_NUMBER Page;
07225
07226 NumberOfPages =
BYTES_TO_PAGES (MemoryDumpMdl->ByteCount + MemoryDumpMdl->ByteOffset);
07227
07228
ASSERT (NumberOfPages <= 16);
07229
07230 PointerPte =
MmCrashDumpPte;
07231 BaseVa = (PCHAR)
MiGetVirtualAddressMappedByPte(PointerPte);
07232 MemoryDumpMdl->MappedSystemVa = (PCHAR)BaseVa + MemoryDumpMdl->ByteOffset;
07233 TempPte =
ValidKernelPte;
07234 Page = (PPFN_NUMBER)(MemoryDumpMdl + 1);
07235
07236
07237
07238
07239
07240
07241
07242
if (NumberOfPages < 16) {
07243
KiFlushSingleTb (
TRUE, BaseVa + (NumberOfPages <<
PAGE_SHIFT));
07244 (PointerPte + NumberOfPages)->u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
07245 }
07246
07247
do {
07248
07249
KiFlushSingleTb (
TRUE, BaseVa);
07250
07251 TempPte.
u.Hard.PageFrameNumber = *Page;
07252
07253
07254
07255
07256
07257 *PointerPte = TempPte;
07258
07259 Page += 1;
07260 PointerPte += 1;
07261 BaseVa +=
PAGE_SIZE;
07262 NumberOfPages -= 1;
07263 }
while (NumberOfPages != 0);
07264
07265
return;
07266 }
07267
07268
07269
VOID
07270 MmReleaseDumpAddresses (
07271 IN PFN_NUMBER Pages
07272 )
07273
07274
07275
07276
07277
07278
07279
07280
07281
07282
07283
07284
07285
07286
07287
07288
07289
07290
07291 {
07292
PMMPTE PointerPte;
07293 PCHAR BaseVa;
07294
07295 PointerPte =
MmCrashDumpPte;
07296 BaseVa = (PCHAR)
MiGetVirtualAddressMappedByPte(PointerPte);
07297
07298
while (Pages) {
07299
07300
KiFlushSingleTb (
TRUE, BaseVa);
07301
07302 PointerPte->
u.Long =
MM_ZERO_PTE;
07303 PointerPte += 1;
07304 BaseVa +=
PAGE_SIZE;
07305 Pages -= 1;
07306 }
07307 }
07308
07309
07310
NTSTATUS
07311 MmSetBankedSection (
07312 IN HANDLE ProcessHandle,
07313 IN PVOID VirtualAddress,
07314 IN ULONG BankLength,
07315 IN BOOLEAN ReadWriteBank,
07316 IN
PBANKED_SECTION_ROUTINE BankRoutine,
07317 IN PVOID Context
07318 )
07319
07320
07321
07322
07323
07324
07325
07326
07327
07328
07329
07330
07331
07332
07333
07334
07335
07336
07337
07338
07339
07340
07341
07342
07343
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366
07367 {
07368
NTSTATUS Status;
07369
PEPROCESS Process;
07370
PMMVAD Vad;
07371
PMMPTE PointerPte;
07372
PMMPTE LastPte;
07373
MMPTE TempPte;
07374 ULONG_PTR size;
07375 LONG count;
07376 ULONG NumberOfPtes;
07377
PMMBANKED_SECTION Bank;
07378
07379
PAGED_CODE ();
07380
07381 UNREFERENCED_PARAMETER (ReadWriteBank);
07382
07383
07384
07385
07386
07387
Status =
ObReferenceObjectByHandle ( ProcessHandle,
07388 PROCESS_VM_OPERATION,
07389
PsProcessType,
07390
KernelMode,
07391 (PVOID *)&Process,
07392
NULL );
07393
07394
if (!
NT_SUCCESS(
Status)) {
07395
return Status;
07396 }
07397
07398
KeAttachProcess (&Process->Pcb);
07399
07400
07401
07402
07403
07404
07405
07406
07407
07408
LOCK_WS_AND_ADDRESS_SPACE (Process);
07409
07410
07411
07412
07413
07414
if (Process->AddressSpaceDeleted != 0) {
07415
Status = STATUS_PROCESS_IS_TERMINATING;
07416
goto ErrorReturn;
07417 }
07418
07419 Vad =
MiLocateAddress (VirtualAddress);
07420
07421
if ((Vad ==
NULL) ||
07422 (Vad->
StartingVpn !=
MI_VA_TO_VPN (VirtualAddress)) ||
07423 (Vad->
u.VadFlags.PhysicalMapping == 0)) {
07424
Status = STATUS_NOT_MAPPED_DATA;
07425
goto ErrorReturn;
07426 }
07427
07428 size =
PAGE_SIZE + ((Vad->
EndingVpn - Vad->
StartingVpn) <<
PAGE_SHIFT);
07429
if ((size % BankLength) != 0) {
07430
Status = STATUS_INVALID_VIEW_SIZE;
07431
goto ErrorReturn;
07432 }
07433
07434 count = -1;
07435 NumberOfPtes = BankLength;
07436
07437
do {
07438 NumberOfPtes = NumberOfPtes >> 1;
07439 count += 1;
07440 }
while (NumberOfPtes != 0);
07441
07442
07443
07444
07445
07446 NumberOfPtes = BankLength >>
PAGE_SHIFT;
07447
07448 Bank =
ExAllocatePoolWithTag (
NonPagedPool,
07449
sizeof (
MMBANKED_SECTION) +
07450 (NumberOfPtes - 1) *
sizeof(
MMPTE),
07451 ' mM');
07452
if (Bank ==
NULL) {
07453
Status = STATUS_INSUFFICIENT_RESOURCES;
07454
goto ErrorReturn;
07455 }
07456
07457 Bank->
BankShift =
PTE_SHIFT + count -
PAGE_SHIFT;
07458
07459 PointerPte =
MiGetPteAddress(
MI_VPN_TO_VA (Vad->
StartingVpn));
07460
ASSERT (PointerPte->
u.Hard.Valid == 1);
07461
07462 Vad->
u4.Banked = Bank;
07463 Bank->
BasePhysicalPage =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
07464 Bank->
BasedPte = PointerPte;
07465 Bank->
BankSize = BankLength;
07466 Bank->
BankedRoutine = BankRoutine;
07467 Bank->
Context = Context;
07468 Bank->
CurrentMappedPte = PointerPte;
07469
07470
07471
07472
07473
07474 count = 0;
07475 TempPte =
ZeroPte;
07476
07477
MI_MAKE_VALID_PTE (TempPte,
07478 Bank->
BasePhysicalPage,
07479
MM_READWRITE,
07480 PointerPte);
07481
07482
if (TempPte.
u.Hard.Write) {
07483
MI_SET_PTE_DIRTY (TempPte);
07484 }
07485
07486
do {
07487 Bank->
BankTemplate[count] = TempPte;
07488 TempPte.
u.Hard.PageFrameNumber += 1;
07489 count += 1;
07490 }
while ((ULONG)count < NumberOfPtes );
07491
07492 LastPte =
MiGetPteAddress (
MI_VPN_TO_VA (Vad->
EndingVpn));
07493
07494
07495
07496
07497
07498
07499
07500 RtlFillMemory (PointerPte,
07501 (size >> (
PAGE_SHIFT -
PTE_SHIFT)),
07502 (UCHAR)
ZeroPte.
u.Long);
07503
07504
KeFlushEntireTb (
TRUE,
TRUE);
07505
07506
Status = STATUS_SUCCESS;
07507 ErrorReturn:
07508
07509
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
07510
KeDetachProcess();
07511
ObDereferenceObject (Process);
07512
return Status;
07513 }
07514
07515 PVOID
07516 MmMapVideoDisplay (
07517 IN PHYSICAL_ADDRESS PhysicalAddress,
07518 IN SIZE_T NumberOfBytes,
07519 IN MEMORY_CACHING_TYPE CacheType
07520 )
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532
07533
07534
07535
07536
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553 {
07554
PMMPTE PointerPte;
07555 PVOID BaseVa;
07556
#ifdef LARGE_PAGES
07557
MMPTE TempPte;
07558 PFN_NUMBER PageFrameIndex;
07559 PFN_NUMBER NumberOfPages;
07560 ULONG size;
07561
PMMPTE protoPte;
07562
PMMPTE largePte;
07563 ULONG pageSize;
07564
PSUBSECTION Subsection;
07565 ULONG Alignment;
07566 ULONG EmPageSize;
07567
#endif LARGE_PAGES
07568
ULONG LargePages;
07569
07570 LargePages =
FALSE;
07571 PointerPte =
NULL;
07572
07573
#if defined (i386) && !defined (_X86PAE_)
07574
ASSERT (PhysicalAddress.HighPart == 0);
07575
#endif
07576
07577
PAGED_CODE();
07578
07579
ASSERT (NumberOfBytes != 0);
07580
07581
#ifdef LARGE_PAGES
07582
NumberOfPages =
COMPUTE_PAGES_SPANNED (PhysicalAddress.LowPart,
07583 NumberOfBytes);
07584
07585 TempPte =
ValidKernelPte;
07586
MI_DISABLE_CACHING (TempPte);
07587 PageFrameIndex = (PFN_NUMBER)(PhysicalAddress.QuadPart >>
PAGE_SHIFT);
07588 TempPte.
u.Hard.PageFrameNumber = PageFrameIndex;
07589
07590
if ((NumberOfBytes >
X64K) && (!MmLargeVideoMapped)) {
07591 size = (NumberOfBytes - 1) >> (
PAGE_SHIFT + 1);
07592 pageSize =
PAGE_SIZE;
07593
07594
while (size != 0) {
07595 size = size >> 2;
07596 pageSize = pageSize << 2;
07597 }
07598
07599 Alignment = pageSize << 1;
07600
if (Alignment <
MM_VA_MAPPED_BY_PDE) {
07601 Alignment =
MM_VA_MAPPED_BY_PDE;
07602 }
07603
07604
#if defined(_IA64_)
07605
07606
07607
07608
07609
07610 EmPageSize = 0;
07611 size = pageSize - 1 ;
07612
07613
while (size) {
07614 size = size >> 1;
07615 EmPageSize += 1;
07616 }
07617
07618
if (NumberOfBytes > pageSize) {
07619
07620
if (
MmPageSizeInfo & (pageSize << 1)) {
07621
07622
07623
07624
07625
07626 pageSize = pageSize << 1;
07627 EmPageSize += 1;
07628
07629 }
07630
else {
07631
07632 EmPageSize = EmPageSize | pageSize;
07633
07634 }
07635 }
07636
07637 pageSize = EmPageSize;
07638
#endif
07639
07640 NumberOfPages = Alignment >>
PAGE_SHIFT;
07641
07642 PointerPte =
MiReserveSystemPtes(NumberOfPages,
07643
SystemPteSpace,
07644 Alignment,
07645 0,
07646
FALSE);
07647
07648
if (PointerPte ==
NULL) {
07649
goto MapWithSmallPages;
07650 }
07651
07652 protoPte =
ExAllocatePoolWithTag (
PagedPool,
07653
sizeof (
MMPTE),
07654 'bSmM');
07655
07656
if (protoPte ==
NULL) {
07657
MiReleaseSystemPtes(PointerPte, NumberOfPages,
SystemPteSpace);
07658
goto MapWithSmallPages;
07659 }
07660
07661 Subsection =
ExAllocatePoolWithTag (
NonPagedPool,
07662
sizeof(
SUBSECTION) + (4 *
sizeof(
MMPTE)),
07663 'bSmM');
07664
07665
if (Subsection ==
NULL) {
07666
ExFreePool (protoPte);
07667
MiReleaseSystemPtes(PointerPte, NumberOfPages,
SystemPteSpace);
07668
goto MapWithSmallPages;
07669 }
07670
07671
MiFillMemoryPte (PointerPte,
07672 Alignment >> (
PAGE_SHIFT -
PTE_SHIFT),
07673
MM_ZERO_KERNEL_PTE);
07674
07675
07676
07677
07678
07679 Subsection->
StartingSector = pageSize;
07680 Subsection->EndingSector = (ULONG)NumberOfPages;
07681 Subsection->
u.LongFlags = 0;
07682 Subsection->
u.SubsectionFlags.LargePages = 1;
07683 Subsection->
u.SubsectionFlags.Protection =
MM_READWRITE |
MM_NOCACHE;
07684 Subsection->
PtesInSubsection = Alignment;
07685 Subsection->
SubsectionBase = PointerPte;
07686
07687 largePte = (
PMMPTE)(Subsection + 1);
07688
07689
07690
07691
07692
07693
07694 *largePte = TempPte;
07695 largePte += 1;
07696
07697
if (NumberOfBytes > pageSize) {
07698 *largePte = TempPte;
07699 largePte->
u.Hard.PageFrameNumber += (pageSize >>
PAGE_SHIFT);
07700 }
else {
07701 *largePte =
ZeroKernelPte;
07702 }
07703
07704
07705
07706
07707
07708
07709 protoPte->
u.Long =
MiGetSubsectionAddressForPte(Subsection);
07710 protoPte->
u.Soft.Prototype = 1;
07711 protoPte->
u.Soft.Protection =
MM_READWRITE |
MM_NOCACHE;
07712
07713
07714
07715
07716
07717
07718 TempPte.u.Long =
MiProtoAddressForPte (protoPte);
07719
MI_SET_GLOBAL_STATE (TempPte, 1);
07720 LargePages =
TRUE;
07721 MmLargeVideoMapped =
TRUE;
07722 }
07723
07724
if (PointerPte !=
NULL) {
07725 BaseVa = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte);
07726 BaseVa = (PVOID)((PCHAR)BaseVa +
BYTE_OFFSET(PhysicalAddress.LowPart));
07727
07728
do {
07729
ASSERT (PointerPte->
u.Hard.Valid == 0);
07730
MI_WRITE_VALID_PTE (PointerPte, TempPte);
07731 PointerPte += 1;
07732 NumberOfPages -= 1;
07733 }
while (NumberOfPages != 0);
07734 }
else {
07735
07736 MapWithSmallPages:
07737
07738
#endif //LARGE_PAGES
07739
07740 BaseVa =
MmMapIoSpace (PhysicalAddress,
07741 NumberOfBytes,
07742 CacheType);
07743
#ifdef LARGE_PAGES
07744
}
07745
#endif //LARGE_PAGES
07746
07747
return BaseVa;
07748 }
07749
07750
VOID
07751 MmUnmapVideoDisplay (
07752 IN PVOID BaseAddress,
07753 IN SIZE_T NumberOfBytes
07754 )
07755
07756
07757
07758
07759
07760
07761
07762
07763
07764
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774
07775
07776
07777
07778
07779
07780 {
07781
07782
#ifdef LARGE_PAGES
07783
PFN_NUMBER NumberOfPages;
07784 ULONG i;
07785
PMMPTE FirstPte;
07786 KIRQL OldIrql;
07787
PMMPTE LargePte;
07788
PSUBSECTION Subsection;
07789
07790
PAGED_CODE();
07791
07792
ASSERT (NumberOfBytes != 0);
07793 NumberOfPages =
COMPUTE_PAGES_SPANNED (BaseAddress, NumberOfBytes);
07794 FirstPte =
MiGetPteAddress (BaseAddress);
07795
07796
if ((NumberOfBytes >
X64K) && (FirstPte->
u.Hard.Valid == 0)) {
07797
07798
ASSERT (MmLargeVideoMapped);
07799 LargePte =
MiPteToProto (FirstPte);
07800 Subsection =
MiGetSubsectionAddress (LargePte);
07801
ASSERT (Subsection->
SubsectionBase == FirstPte);
07802
07803 NumberOfPages = Subsection->EndingSector;
07804
ExFreePool (Subsection);
07805
ExFreePool (LargePte);
07806 MmLargeVideoMapped =
FALSE;
07807 KeFillFixedEntryTb ((PHARDWARE_PTE)FirstPte, (PVOID)
KSEG0_BASE, LARGE_ENTRY);
07808 }
07809
MiReleaseSystemPtes(FirstPte, NumberOfPages,
SystemPteSpace);
07810
return;
07811
07812
#else // LARGE_PAGES
07813
07814
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
07815
return;
07816
#endif //LARGE_PAGES
07817
}
07818
07819
07820
VOID
07821 MmLockPagedPool (
07822 IN PVOID Address,
07823 IN SIZE_T SizeInBytes
07824 )
07825
07826
07827
07828
07829
07830
07831
07832
07833
07834
07835
07836
07837
07838
07839
07840
07841
07842
07843
07844
07845
07846
07847
07848
07849 {
07850
PMMPTE PointerPte;
07851
PMMPTE LastPte;
07852 KIRQL OldIrql;
07853 KIRQL OldIrqlWs;
07854
07855
MmLockPagableSectionByHandle(
ExPageLockHandle);
07856 PointerPte =
MiGetPteAddress (Address);
07857 LastPte =
MiGetPteAddress ((PVOID)((PCHAR)Address + (SizeInBytes - 1)));
07858
LOCK_SYSTEM_WS (OldIrqlWs);
07859
LOCK_PFN (OldIrql);
07860
MiLockCode (PointerPte, LastPte,
MM_LOCK_BY_REFCOUNT);
07861
UNLOCK_PFN (OldIrql);
07862
UNLOCK_SYSTEM_WS (OldIrqlWs);
07863
MmUnlockPagableImageSection(
ExPageLockHandle);
07864
return;
07865 }
07866
07867
NTKERNELAPI
07868
VOID
07869 MmUnlockPagedPool (
07870 IN PVOID Address,
07871 IN SIZE_T SizeInBytes
07872 )
07873
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887
07888
07889
07890
07891
07892
07893
07894
07895
07896 {
07897
PMMPTE PointerPte;
07898
PMMPTE LastPte;
07899 KIRQL OldIrql;
07900 PFN_NUMBER PageFrameIndex;
07901
PMMPFN Pfn1;
07902
07903
MmLockPagableSectionByHandle(
ExPageLockHandle);
07904 PointerPte =
MiGetPteAddress (Address);
07905 LastPte =
MiGetPteAddress ((PVOID)((PCHAR)Address + (SizeInBytes - 1)));
07906
LOCK_PFN2 (OldIrql);
07907
07908
do {
07909
ASSERT (PointerPte->
u.Hard.Valid == 1);
07910
07911 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
07912 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
07913
07914
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
07915
07916
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 35);
07917
07918
MiDecrementReferenceCount (PageFrameIndex);
07919
07920 PointerPte += 1;
07921 }
while (PointerPte <= LastPte);
07922
07923
UNLOCK_PFN2 (OldIrql);
07924
MmUnlockPagableImageSection(
ExPageLockHandle);
07925
return;
07926 }
07927
07928
NTKERNELAPI
07929 ULONG
07930 MmGatherMemoryForHibernate (
07931 IN
PMDL Mdl,
07932 IN BOOLEAN Wait
07933 )
07934
07935
07936
07937
07938
07939
07940
07941
07942
07943
07944
07945
07946
07947
07948
07949
07950
07951
07952
07953
07954
07955
07956
07957
07958
07959 {
07960 KIRQL OldIrql;
07961 PFN_NUMBER PagesNeeded;
07962 PPFN_NUMBER Pages;
07963 PFN_NUMBER i;
07964 PFN_NUMBER PageFrameIndex;
07965
PMMPFN Pfn1;
07966 ULONG status;
07967
07968 status =
FALSE;
07969
07970 PagesNeeded = Mdl->ByteCount >>
PAGE_SHIFT;
07971 Pages = (PPFN_NUMBER)(Mdl + 1);
07972
07973 i = Wait ? 100 : 1;
07974
07975 InterlockedIncrement (&
MiDelayPageFaults);
07976
07977
do {
07978
07979
LOCK_PFN2 (OldIrql);
07980
if (
MmAvailablePages > PagesNeeded) {
07981
07982
07983
07984
07985
07986
do {
07987 PageFrameIndex =
MiRemoveAnyPage (
MI_GET_PAGE_COLOR_FROM_PTE (
NULL));
07988 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
07989
MI_SET_PFN_DELETED (Pfn1);
07990 Pfn1->
u3.e2.ReferenceCount += 1;
07991 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
07992 *Pages = PageFrameIndex;
07993 Pages += 1;
07994 PagesNeeded -= 1;
07995 }
while (PagesNeeded);
07996
UNLOCK_PFN2 (OldIrql);
07997 Mdl->MdlFlags |=
MDL_PAGES_LOCKED;
07998 status =
TRUE;
07999
break;
08000 }
08001
08002
UNLOCK_PFN2 (OldIrql);
08003
08004
08005
08006
08007
08008
08009
if (OldIrql >
APC_LEVEL) {
08010
break;
08011 }
08012
08013
if (!i) {
08014
break;
08015 }
08016
08017
08018
08019
08020
08021
MiEmptyAllWorkingSets ();
08022
MiFlushAllPages();
08023
08024
KeDelayExecutionThread (
KernelMode,
08025
FALSE,
08026 (PLARGE_INTEGER)&
Mm30Milliseconds);
08027 i -= 1;
08028
08029 }
while (
TRUE);
08030
08031 InterlockedDecrement (&
MiDelayPageFaults);
08032
08033
return status;
08034 }
08035
08036
NTKERNELAPI
08037
VOID
08038 MmReturnMemoryForHibernate (
08039 IN
PMDL Mdl
08040 )
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054
08055
08056
08057
08058
08059
08060
08061
08062
08063 {
08064 KIRQL OldIrql;
08065 PFN_NUMBER PagesNeeded;
08066 PPFN_NUMBER Pages;
08067
08068 PagesNeeded = (Mdl->ByteCount >>
PAGE_SHIFT);
08069 Pages = (PPFN_NUMBER)(Mdl + 1);
08070
08071
LOCK_PFN2 (OldIrql);
08072
do {
08073
MiDecrementReferenceCount (*Pages);
08074 Pages += 1;
08075 PagesNeeded -= 1;
08076 }
while (PagesNeeded);
08077
UNLOCK_PFN2 (OldIrql);
08078
return;
08079 }
08080
08081
08082
VOID
08083 MmSetKernelDumpRange(
08084 IN OUT PVOID pDumpContext
08085 )
08086
08087
08088
08089
08090
08091
08092
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102
08103
08104
08105
08106
08107
08108
08109 {
08110 PLIST_ENTRY NextEntry;
08111 PLDR_DATA_TABLE_ENTRY DataTableEntry;
08112 PCHAR Kseg0Addr;
08113 PCHAR Kseg2Addr;
08114 PFN_NUMBER Pages;
08115 PCHAR Va;
08116 PCHAR HighVa;
08117 LOGICAL IsPhysicalAddress;
08118 ULONG
Index;
08119
#if defined(_X86_)
08120
PHYSICAL_ADDRESS DirBase;
08121 PKDESCRIPTOR Descriptor;
08122 PKPROCESSOR_STATE ProcessorState;
08123
#endif
08124
08125
08126
08127
08128
08129 Kseg0Addr = (PCHAR)
MmSystemRangeStart;
08130 Kseg2Addr = Kseg0Addr +
MM_PAGES_IN_KSEG0 *
PAGE_SIZE;
08131
08132
08133
08134
08135
08136
if (!
MmVirtualBias) {
08137
08138
08139
08140
08141
08142 NextEntry =
PsLoadedModuleList.Flink;
08143
08144
while (NextEntry != &
PsLoadedModuleList) {
08145
08146 DataTableEntry = CONTAINING_RECORD (NextEntry,
08147 LDR_DATA_TABLE_ENTRY,
08148 InLoadOrderLinks);
08149 Va = DataTableEntry->DllBase;
08150
08151
if (Va >= Kseg0Addr && Va < Kseg2Addr) {
08152
08153 Pages =
COMPUTE_PAGES_SPANNED(Va, DataTableEntry->SizeOfImage);
08154
08155
IoSetDumpRange (pDumpContext,
08156 Va,
08157 (ULONG)Pages,
08158 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08159 }
08160 NextEntry = NextEntry->Flink;
08161 }
08162 }
08163
08164
08165
08166
08167
08168
08169
08170 Va = (PCHAR)
KiProcessorBlock;
08171
08172 Pages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES (
08173 Va,
08174
sizeof (PKPRCB) *
KeNumberProcessors);
08175
08176
08177
IoSetDumpRange (pDumpContext,
08178 Va,
08179 (ULONG)Pages,
08180 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08181
08182
08183
08184
08185
08186
for (
Index = 0; (CCHAR)
Index <
KeNumberProcessors;
Index += 1) {
08187
08188 Va = (PCHAR)
KiProcessorBlock[
Index];
08189
08190 Pages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES (Va,
08191
sizeof (KPRCB));
08192
08193
IoSetDumpRange (pDumpContext,
08194 Va,
08195 (ULONG)Pages,
08196 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08197
08198
08199
#if defined (_X86_)
08200
08201
08202
08203
08204
08205 ProcessorState = &
KiProcessorBlock[
Index]->ProcessorState;
08206
08207 Descriptor = &ProcessorState->SpecialRegisters.Gdtr;
08208
08209 Va = (PCHAR) Descriptor->Base;
08210
08211
if (Va !=
NULL) {
08212
08213 Pages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES (Va, Descriptor->Limit);
08214
08215
IoSetDumpRange (pDumpContext,
08216 Va,
08217 (ULONG)Pages,
08218 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08219 }
08220
08221
08222
08223
08224
08225 Descriptor = &ProcessorState->SpecialRegisters.Idtr;
08226
08227 Va = (PCHAR) Descriptor->Base;
08228
08229
if (Va !=
NULL) {
08230
08231 Pages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES (Va, Descriptor->Limit);
08232
08233
IoSetDumpRange (pDumpContext,
08234 Va,
08235 (ULONG)Pages,
08236 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08237 }
08238 }
08239
08240
08241
08242
08243
08244
08245
08246 _asm {
08247 mov eax, cr3
08248 mov DirBase.LowPart, eax
08249 }
08250
08251
08252
08253
08254
08255 DirBase.HighPart = 0;
08256
08257 Va =
MmGetVirtualForPhysical (DirBase);
08258
08259
IoSetDumpRange (pDumpContext,
08260 Va,
08261 1,
08262 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08263
#endif
08264
08265
08266
08267
08268
08269
if (((PCHAR)
MmNonPagedPoolStart >= Kseg0Addr) &&
08270 ((PCHAR)
MmNonPagedPoolStart <= Kseg2Addr)) {
08271
08272 Va =
MmNonPagedPoolStart;
08273
08274 Pages = (ULONG)
COMPUTE_PAGES_SPANNED(Va,
MmSizeOfNonPagedPoolInBytes);
08275
08276
IoSetDumpRange (pDumpContext,
08277 Va,
08278 (ULONG)Pages,
08279 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08280 }
08281
08282
08283
08284
08285
08286
if (!
MmVirtualBias) {
08287 Va = Kseg2Addr;
08288 }
08289
else {
08290 Va = Kseg0Addr;
08291 }
08292
08293
do {
08294
08295
if (
MmIsAddressValid(Va)) {
08296
08297
IoSetDumpRange(pDumpContext,
08298 Va,
08299 1,
08300
FALSE);
08301 }
08302
08303 Va +=
PAGE_SIZE;
08304
08305 }
while ((LONG_PTR)Va < (
MM_SYSTEM_SPACE_END & ~(
PAGE_SIZE - 1)));
08306
08307
08308
08309
08310
08311
if ((PCHAR)
MmPfnDatabase < Kseg2Addr) {
08312
08313 IsPhysicalAddress =
MI_IS_PHYSICAL_ADDRESS(
MmPfnDatabase);
08314
08315
IoSetDumpRange (pDumpContext,
08316
MmPfnDatabase,
08317
ADDRESS_AND_SIZE_TO_SPAN_PAGES (
MmPfnDatabase,
08318 (
MmHighestPossiblePhysicalPage + 1) *
sizeof (
MMPFN)),
08319 (BOOLEAN) IsPhysicalAddress);
08320
08321
if (IsPhysicalAddress ==
FALSE) {
08322
08323
08324
08325
08326
08327
08328 Va = (PCHAR)
MmPfnDatabase;
08329 HighVa = Va + (
MmHighestPossiblePhysicalPage + 1) *
sizeof (
MMPFN);
08330
08331
do {
08332
if (!
MmIsAddressValid(Va)) {
08333
08334
IoFreeDumpRange (pDumpContext,
08335 Va,
08336 1,
08337
FALSE);
08338 }
08339
08340 Va +=
PAGE_SIZE;
08341
08342 }
while (Va < HighVa);
08343 }
08344 }
08345
08346
08347
08348
08349
08350
for (
Index = 0;
Index <
MI_MAX_FREE_LIST_HEADS;
Index += 1) {
08351
08352 NextEntry =
MmNonPagedPoolFreeListHead[
Index].Flink;
08353
08354
while (NextEntry != &
MmNonPagedPoolFreeListHead[
Index]) {
08355
08356
PMMFREE_POOL_ENTRY FreePageInfo;
08357
08358
08359
08360
08361
08362
if (
MmProtectFreedNonPagedPool ==
TRUE) {
08363
MiUnProtectFreeNonPagedPool ((PVOID)NextEntry, 0);
08364 }
08365
08366 FreePageInfo = CONTAINING_RECORD(NextEntry,
08367
MMFREE_POOL_ENTRY,
08368
List);
08369
08370
ASSERT (FreePageInfo->
Signature ==
MM_FREE_POOL_SIGNATURE);
08371
08372
if (FreePageInfo->
Size) {
08373
08374 Va = (PCHAR)FreePageInfo;
08375
08376 Pages =
COMPUTE_PAGES_SPANNED(FreePageInfo, FreePageInfo->
Size);
08377
08378
IoFreeDumpRange(pDumpContext,
08379 Va,
08380 (ULONG)Pages,
08381 (BOOLEAN)
MI_IS_PHYSICAL_ADDRESS (Va));
08382
08383 }
08384
08385 NextEntry = FreePageInfo->
List.Flink;
08386
08387
if (
MmProtectFreedNonPagedPool ==
TRUE) {
08388
MiProtectFreeNonPagedPool ((PVOID)FreePageInfo,
08389 (ULONG)FreePageInfo->
Size);
08390 }
08391 }
08392 }
08393
08394
08395
08396
08397
08398
for (Va = (PCHAR)
MmSystemCacheStart; Va < (PCHAR)
MmSystemCacheEnd; Va +=
PAGE_SIZE) {
08399
08400
if (
MmIsAddressValid(Va)) {
08401
08402
ASSERT (
MI_IS_PHYSICAL_ADDRESS(Va) ==
FALSE);
08403
08404
IoFreeDumpRange (pDumpContext,
08405 Va,
08406 1,
08407
FALSE);
08408 }
08409 }
08410
08411
#if defined(_X86_)
08412
if (
MiSystemCacheEndExtra !=
MmSystemCacheEnd) {
08413
for (Va = (PCHAR)
MiSystemCacheStartExtra; Va < (PCHAR)
MiSystemCacheEndExtra; Va +=
PAGE_SIZE) {
08414
08415
if (
MmIsAddressValid(Va)) {
08416
08417
ASSERT (
MI_IS_PHYSICAL_ADDRESS(Va) ==
FALSE);
08418
08419
IoFreeDumpRange(pDumpContext,
08420 Va,
08421 1,
08422
FALSE);
08423 }
08424 }
08425 }
08426
#endif
08427
}
08428
08429
08430
VOID
08431
MmEnablePAT (
08432 VOID
08433 )
08434
08435
08436
08437
08438
08439
08440
08441
08442
08443
08444
08445
08446
08447
08448
08449
08450
08451
08452
08453
08454
08455 {
08456
MiWriteCombiningPtes =
TRUE;
08457 }
08458
08459
NTSTATUS
08460
MmDispatchWin32Callout(
08461 IN
PKWIN32_CALLOUT CallbackRoutine,
08462 IN PKWIN32_CALLOUT WorkerCallback OPTIONAL,
08463 IN PVOID Parameter,
08464 IN PULONG SessionId OPTIONAL
08465 )
08466
08467
08468
08469
08470
08471
08472
08473
08474
08475
08476
08477
08478
08479
08480
08481
08482
08483
08484
08485
08486
08487
08488
08489
08490
08491
08492
08493
08494
08495
08496
08497
08498 {
08499 ULONG i;
08500 KIRQL OldIrql;
08501 PLIST_ENTRY NextEntry;
08502
PMM_SESSION_SPACE Session;
08503
PEPROCESS *Processes;
08504
NTSTATUS Status;
08505 ULONG SessionCount;
08506 BOOLEAN Signal;
08507
PEPROCESS SingleProcess;
08508 PLIST_ENTRY NextProcessEntry;
08509
PEPROCESS Process;
08510
08511
if (WorkerCallback ==
NULL) {
08512 WorkerCallback = CallbackRoutine;
08513 }
08514
08515
if (
MiHydra ==
FALSE) {
08516
return (*WorkerCallback)(Parameter);
08517 }
08518
08519
if (
MI_IS_SESSION_ADDRESS((ULONG_PTR)*CallbackRoutine) ==
FALSE) {
08520
return (*WorkerCallback)(Parameter);
08521 }
08522
08523
08524
08525
08526
08527
08528
08529
if (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 1) {
08530
ASSERT (
MmIsAddressValid(MmSessionSpace) == TRUE);
08531
return (*WorkerCallback)(Parameter);
08532 }
08533
08534
if (ARGUMENT_PRESENT(SessionId)) {
08535
08536
08537
08538
08539
08540
08541 SessionCount = 1;
08542
08543 Processes = &SingleProcess;
08544
08545
LOCK_EXPANSION (OldIrql);
08546 }
08547
else {
08548
08549
08550
08551
08552
08553
08554
08555
08556 ReAllocate:
08557
08558 SessionCount =
MiSessionCount + 10;
08559
08560 Processes = (
PEPROCESS *)
ExAllocatePoolWithTag(
08561 NonPagedPool,
08562 SessionCount *
sizeof(
PEPROCESS),
08563 '23WD'
08564 );
08565
08566
if (Processes ==
NULL) {
08567
return STATUS_NO_MEMORY;
08568 }
08569
08570
LOCK_EXPANSION (OldIrql);
08571
08572
if (SessionCount <
MiSessionCount) {
08573
UNLOCK_EXPANSION (OldIrql);
08574
ExFreePool (Processes);
08575
goto ReAllocate;
08576 }
08577 }
08578
08579 SessionCount = 0;
08580
08581 NextEntry =
MiSessionWsList.Flink;
08582
08583
while (NextEntry != &
MiSessionWsList) {
08584
08585 Session = CONTAINING_RECORD(NextEntry,
MM_SESSION_SPACE, WsListEntry);
08586
08587 NextProcessEntry = Session->
ProcessList.Flink;
08588
08589
if ((Session->
u.Flags.DeletePending == 0) &&
08590 (NextProcessEntry != &Session->
ProcessList)) {
08591
08592
if (ARGUMENT_PRESENT(SessionId) && Session->
SessionId != *SessionId)
08593 {
08594
08595
08596
08597
08598 NextEntry = NextEntry->Flink;
08599
continue;
08600 }
08601
08602 Process = CONTAINING_RECORD (NextProcessEntry,
08603
EPROCESS,
08604 SessionProcessLinks);
08605
08606
if (Process->
Vm.
u.Flags.SessionLeader == 1) {
08607
08608
08609
08610
08611
08612
08613
08614 NextEntry = NextEntry->Flink;
08615
continue;
08616 }
08617
08618
08619
08620
08621
08622
08623
08624 Processes[SessionCount] = CONTAINING_RECORD (NextProcessEntry,
08625
EPROCESS,
08626 SessionProcessLinks);
08627
08628
ObReferenceObject (Processes[SessionCount]);
08629 SessionCount += 1;
08630 Session->
AttachCount += 1;
08631
08632
if (ARGUMENT_PRESENT(SessionId) && Session->
SessionId != *SessionId)
08633 {
08634
break;
08635 }
08636 }
08637 NextEntry = NextEntry->Flink;
08638 }
08639
08640
UNLOCK_EXPANSION (OldIrql);
08641
08642
08643
08644
08645
08646
Status = STATUS_NOT_FOUND;
08647
08648
for (i = 0; i < SessionCount; i += 1) {
08649
08650
KeAttachProcess (&Processes[i]->Pcb);
08651
08652
if (Processes[i]->
SessionId == 0) {
08653
08654
08655
08656
08657
08658
Status = (*WorkerCallback)(Parameter);
08659 }
08660
else {
08661
08662 (
VOID)(*WorkerCallback)(Parameter);
08663 }
08664
08665 Signal =
FALSE;
08666
08667
LOCK_EXPANSION (OldIrql);
08668
08669
MmSessionSpace->
AttachCount -= 1;
08670
08671
if (
MmSessionSpace->
u.Flags.DeletePending == 1 &&
MmSessionSpace->
AttachCount == 0) {
08672 Signal =
TRUE;
08673 }
08674
08675
UNLOCK_EXPANSION (OldIrql);
08676
08677
if (Signal ==
TRUE) {
08678
KeSetEvent (&
MmSessionSpace->
AttachEvent, 0, FALSE);
08679 }
08680
08681
KeDetachProcess();
08682
08683
ObDereferenceObject (Processes[i]);
08684 }
08685
08686
if (ARGUMENT_PRESENT(SessionId) == 0) {
08687
ExFreePool (Processes);
08688 }
08689
08690
return Status;
08691 }
08692
08693 LOGICAL
08694
MmIsSystemAddressLocked(
08695 IN PVOID VirtualAddress
08696 )
08697
08698
08699
08700
08701
08702
08703
08704
08705
08706
08707
08708
08709
08710
08711
08712
08713
08714
08715
08716
08717
08718
08719
08720
08721
08722 {
08723
PMMPFN Pfn1;
08724 KIRQL OldIrql;
08725
PMMPTE PointerPte;
08726 PFN_NUMBER PageFrameIndex;
08727
08728
if (
IS_SYSTEM_ADDRESS (VirtualAddress) ==
FALSE) {
08729
return FALSE;
08730 }
08731
08732
if (
MI_IS_PHYSICAL_ADDRESS (VirtualAddress)) {
08733
return TRUE;
08734 }
08735
08736
08737
08738
08739
08740
if (
MI_IS_PROCESS_SPACE_ADDRESS (VirtualAddress) ==
TRUE) {
08741
return FALSE;
08742 }
08743
08744
#if defined (_IA64_)
08745
if (
MI_IS_KERNEL_PTE_ADDRESS (VirtualAddress) ==
TRUE) {
08746
return FALSE;
08747 }
08748
#endif
08749
08750
LOCK_PFN2 (OldIrql);
08751
08752
if (
MmIsAddressValid (VirtualAddress) ==
FALSE) {
08753
UNLOCK_PFN2 (OldIrql);
08754
return FALSE;
08755 }
08756
08757 PointerPte =
MiGetPteAddress (VirtualAddress);
08758
08759 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
08760
08761
08762
08763
08764
08765
08766
08767
08768
if (PageFrameIndex >
MmHighestPhysicalPage) {
08769
UNLOCK_PFN2 (OldIrql);
08770
return FALSE;
08771 }
08772
08773 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
08774
08775
08776
08777
08778
08779
if (Pfn1->
u3.e2.ReferenceCount > 1) {
08780
UNLOCK_PFN2 (OldIrql);
08781
return TRUE;
08782 }
08783
08784
if (Pfn1->
u3.e2.ReferenceCount > Pfn1->
u2.ShareCount) {
08785
UNLOCK_PFN2 (OldIrql);
08786
return TRUE;
08787 }
08788
08789
08790
08791
08792
08793
if (Pfn1->
u1.Event ==
NULL) {
08794
UNLOCK_PFN2 (OldIrql);
08795
return TRUE;
08796 }
08797
08798
UNLOCK_PFN2 (OldIrql);
08799
08800
return FALSE;
08801 }
08802
08803
#if DBG
08804
08805
VOID
08806 MiVerifyLockedPageCharges (
08807 VOID
08808 )
08809 {
08810
PMMPFN Pfn1;
08811 KIRQL OldIrql;
08812 PFN_NUMBER start;
08813 PFN_NUMBER count;
08814 PFN_NUMBER Page;
08815 PFN_NUMBER LockCharged;
08816
08817
if (MiPrintLockedPages == 0) {
08818
return;
08819 }
08820
08821
if (KeGetCurrentIrql() >
APC_LEVEL) {
08822
return;
08823 }
08824
08825 start = 0;
08826 LockCharged = 0;
08827
08828 ExAcquireFastMutex (&MmDynamicMemoryMutex);
08829
08830
LOCK_PFN2 (OldIrql);
08831
08832
do {
08833
08834 count =
MmPhysicalMemoryBlock->
Run[start].
PageCount;
08835 Page =
MmPhysicalMemoryBlock->
Run[start].
BasePage;
08836
08837
if (count != 0) {
08838 Pfn1 =
MI_PFN_ELEMENT (Page);
08839
do {
08840
if (Pfn1->
u3.e1.LockCharged == 1) {
08841
if (MiPrintLockedPages & 0x4) {
08842
DbgPrint (
"%x ", Pfn1 - MmPfnDatabase);
08843 }
08844 LockCharged += 1;
08845 }
08846 count -= 1;
08847 Pfn1 += 1;
08848 }
while (count != 0);
08849 }
08850
08851 start += 1;
08852 }
while (start !=
MmPhysicalMemoryBlock->
NumberOfRuns);
08853
08854
if (LockCharged !=
MmSystemLockPagesCount) {
08855
if (MiPrintLockedPages & 0x1) {
08856
DbgPrint (
"MM: Locked pages MISMATCH %u %u\n",
08857 LockCharged, MmSystemLockPagesCount);
08858 }
08859 }
08860
else {
08861
if (MiPrintLockedPages & 0x2) {
08862
DbgPrint (
"MM: Locked pages ok %u\n",
08863 LockCharged);
08864 }
08865 }
08866
08867
UNLOCK_PFN2 (OldIrql);
08868
08869 ExReleaseFastMutex (&MmDynamicMemoryMutex);
08870
08871
return;
08872 }
08873
#endif