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
#if defined ( _WIN64)
00025
#if DBGXX
00026
VOID
00027 MiCheckPageTableInPage(
00028 IN
PMMPFN Pfn,
00029 IN
PMMINPAGE_SUPPORT Support
00030 );
00031
#endif
00032
#endif
00033
00034 #define STATUS_ISSUE_PAGING_IO (0xC0033333)
00035 #define STATUS_PTE_CHANGED 0x87303000
00036 #define STATUS_REFAULT 0xC7303001
00037
00038 extern MMPTE MmSharedUserDataPte;
00039
00040 extern PVOID
MmSpecialPoolStart;
00041 extern PVOID
MmSpecialPoolEnd;
00042
00043 #define MI_PROTOTYPE_WSINDEX ((ULONG)-1)
00044
00045 MMINPAGE_SUPPORT_LIST MmInPageSupportList;
00046
00047
VOID
00048
MiHandleBankedSection (
00049 IN PVOID VirtualAddress,
00050 IN
PMMVAD Vad
00051 );
00052
00053
NTSTATUS
00054
MiCompleteProtoPteFault (
00055 IN BOOLEAN StoreInstruction,
00056 IN PVOID FaultingAddress,
00057 IN
PMMPTE PointerPte,
00058 IN
PMMPTE PointerProtoPte
00059 );
00060
00061
#ifdef ALLOC_PRAGMA
00062
#pragma alloc_text(PAGEHYDRA, MiCheckPdeForSessionSpace)
00063
#pragma alloc_text(PAGEHYDRA, MiSessionCopyOnWrite)
00064
#endif
00065
00066
00067
NTSTATUS
00068 MiDispatchFault (
00069 IN BOOLEAN StoreInstruction,
00070 IN PVOID VirtualAddress,
00071 IN
PMMPTE PointerPte,
00072 IN
PMMPTE PointerProtoPte,
00073 IN
PEPROCESS Process,
00074 OUT PLOGICAL ApcNeeded
00075 )
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 {
00127
MMPTE TempPte;
00128
NTSTATUS status;
00129
PMMINPAGE_SUPPORT ReadBlock;
00130
MMPTE SavedPte;
00131
PMMINPAGE_SUPPORT CapturedEvent;
00132 KIRQL OldIrql;
00133 PPFN_NUMBER Page;
00134 PFN_NUMBER PageFrameIndex;
00135 LONG NumberOfBytes;
00136
PMMPTE CheckPte;
00137
PMMPTE ReadPte;
00138
PMMPFN PfnClusterPage;
00139
PMMPFN Pfn1;
00140
PHARD_FAULT_NOTIFY_ROUTINE NotifyRoutine;
00141 KIRQL PreviousIrql;
00142 LOGICAL WsLockChanged;
00143
PETHREAD CurrentThread;
00144
00145
PERFINFO_DISPATCHFAULT_DECL();
00146
00147 WsLockChanged =
FALSE;
00148
00149 ProtoPteNotResident:
00150
00151
if (PointerProtoPte !=
NULL) {
00152
00153
00154
00155
00156
00157
00158
00159
LOCK_PFN (OldIrql);
00160
00161
00162
00163
00164
00165
00166
if (!
MI_IS_PHYSICAL_ADDRESS(PointerProtoPte)) {
00167 CheckPte =
MiGetPteAddress (PointerProtoPte);
00168
00169
if (CheckPte->
u.Hard.Valid == 0) {
00170
00171
ASSERT (Process ==
NULL || (
MiHydra ==
TRUE && Process ==
HYDRA_PROCESS));
00172
00173
00174
00175
00176
00177 VirtualAddress = PointerProtoPte;
00178 PointerPte = CheckPte;
00179 PointerProtoPte =
NULL;
00180
UNLOCK_PFN (OldIrql);
00181
00182
if (Process ==
HYDRA_PROCESS) {
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
ASSERT (
MiHydra ==
TRUE);
00197
UNLOCK_SESSION_SPACE_WS (
APC_LEVEL);
00198
00199
00200
00201
00202
00203
LOCK_SYSTEM_WS (PreviousIrql);
00204
00205
00206
00207
00208
00209 Process =
NULL;
00210
00211 WsLockChanged =
TRUE;
00212
00213
ASSERT (
MI_IS_SESSION_ADDRESS (VirtualAddress) ==
FALSE);
00214 }
00215
else {
00216
ASSERT (Process ==
NULL);
00217 }
00218
00219
goto ProtoPteNotResident;
00220 }
00221 }
00222
00223
if (PointerPte->u.Hard.Valid == 1) {
00224
00225
00226
00227
00228
00229
00230
UNLOCK_PFN (OldIrql);
00231
00232
if (WsLockChanged ==
TRUE) {
00233
UNLOCK_SYSTEM_WS (
APC_LEVEL);
00234
LOCK_SESSION_SPACE_WS (PreviousIrql);
00235 }
00236
00237
return STATUS_SUCCESS;
00238 }
00239
00240 ReadPte = PointerProtoPte;
00241
00242
PERFINFO_HARDFAULT_INFO(PointerProtoPte);
00243
00244 status =
MiResolveProtoPteFault (StoreInstruction,
00245 VirtualAddress,
00246 PointerPte,
00247 PointerProtoPte,
00248 &ReadBlock,
00249 Process,
00250 ApcNeeded);
00251
00252
00253
00254
00255
ASSERT (KeGetCurrentIrql() ==
APC_LEVEL);
00256
00257 }
else {
00258
00259 TempPte = *PointerPte;
00260
ASSERT (TempPte.
u.Long != 0);
00261
00262
if (TempPte.
u.Soft.Transition != 0) {
00263
00264
00265
00266
00267
00268 status =
MiResolveTransitionFault (VirtualAddress,
00269 PointerPte,
00270 Process,
00271
FALSE,
00272 ApcNeeded);
00273
00274 }
else if (TempPte.
u.Soft.PageFileHigh == 0) {
00275
00276
00277
00278
00279
00280 status =
MiResolveDemandZeroFault (VirtualAddress,
00281 PointerPte,
00282 Process,
00283
FALSE);
00284 }
else {
00285
00286
00287
00288
00289
00290 ReadPte = PointerPte;
00291
LOCK_PFN (OldIrql);
00292 status =
MiResolvePageFileFault (VirtualAddress,
00293 PointerPte,
00294 &ReadBlock,
00295 Process);
00296 }
00297 }
00298
00299
ASSERT (KeGetCurrentIrql() ==
APC_LEVEL);
00300
00301
if (
NT_SUCCESS(status)) {
00302
00303
if (WsLockChanged ==
TRUE) {
00304
UNLOCK_SYSTEM_WS (
APC_LEVEL);
00305
LOCK_SESSION_SPACE_WS (OldIrql);
00306 }
00307
00308
return status;
00309 }
00310
00311
if (status ==
STATUS_ISSUE_PAGING_IO) {
00312
00313 SavedPte = *ReadPte;
00314
00315 CapturedEvent = (
PMMINPAGE_SUPPORT)ReadBlock->
Pfn->
u1.Event;
00316
00317 CurrentThread =
NULL;
00318
00319
if (Process ==
HYDRA_PROCESS) {
00320
UNLOCK_SESSION_SPACE_WS(
APC_LEVEL);
00321 }
00322
else if (Process !=
NULL) {
00323
00324
00325
00326
00327
00328
00329
00330
00331 CurrentThread =
PsGetCurrentThread();
00332
00333
ASSERT (CurrentThread->
NestedFaultCount <= 2);
00334 CurrentThread->
NestedFaultCount += 1;
00335
00336
KeEnterCriticalRegion();
00337
UNLOCK_WS (Process);
00338 }
00339
else {
00340
UNLOCK_SYSTEM_WS(
APC_LEVEL);
00341 }
00342
00343
#if DBG
00344
if (MmDebug &
MM_DBG_PAGEFAULT) {
00345
DbgPrint (
"MMFAULT: va: %p size: %lx process: %s file: %Z\n",
00346 VirtualAddress,
00347 ReadBlock->
Mdl.
ByteCount,
00348 Process ==
HYDRA_PROCESS ? (PUCHAR)
"Session Space" : (Process ? Process->ImageFileName : (PUCHAR)
"SystemVa"),
00349 &ReadBlock->
FilePointer->
FileName
00350 );
00351 }
00352
#endif //DBG
00353
00354
PERFINFO_HARDFAULT(VirtualAddress, ReadBlock);
00355
00356
#if defined(_PREFETCH_)
00357
00358
00359
00360
00361
00362
ASSERT (ReadBlock->PrefetchMdl ==
NULL);
00363
00364
#endif
00365
00366
00367
00368
00369
00370 status =
IoPageRead ( ReadBlock->
FilePointer,
00371 &ReadBlock->
Mdl,
00372 &ReadBlock->
ReadOffset,
00373 &ReadBlock->
Event,
00374 &ReadBlock->
IoStatus);
00375
if (!
NT_SUCCESS(status)) {
00376
00377
00378
00379
00380
00381
00382 ReadBlock->
IoStatus.Status = status;
00383 ReadBlock->
IoStatus.Information = 0;
00384
KeSetEvent (&ReadBlock->
Event,
00385 0,
00386
FALSE);
00387 }
00388
00389
00390
00391
00392
00393 status =
MiWaitForInPageComplete (ReadBlock->
Pfn,
00394 ReadPte,
00395 VirtualAddress,
00396 &SavedPte,
00397 CapturedEvent,
00398 Process);
00399
00400
if (CurrentThread !=
NULL) {
00401
KeLeaveCriticalRegion();
00402
00403
ASSERT (CurrentThread->
NestedFaultCount <= 3);
00404
ASSERT (CurrentThread->
NestedFaultCount != 0);
00405
00406 CurrentThread->
NestedFaultCount -= 1;
00407
00408
if ((CurrentThread->
ApcNeeded == 1) &&
00409 (CurrentThread->
NestedFaultCount == 0)) {
00410 *ApcNeeded =
TRUE;
00411 CurrentThread->
ApcNeeded = 0;
00412 }
00413 }
00414
00415
PERFINFO_HARDFAULT_IOTIME();
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 Pfn1 = ReadBlock->
Pfn;
00428 Page = &ReadBlock->
Page[0];
00429 NumberOfBytes = (LONG)ReadBlock->
Mdl.
ByteCount;
00430 CheckPte = ReadBlock->
BasePte;
00431
00432
while (NumberOfBytes > 0) {
00433
00434
00435
00436
00437
00438
00439
if (CheckPte != ReadPte) {
00440 PfnClusterPage =
MI_PFN_ELEMENT (*Page);
00441
ASSERT (PfnClusterPage->
PteFrame == Pfn1->
PteFrame);
00442
#if DBG
00443
if (PfnClusterPage->
u3.e1.InPageError) {
00444
ASSERT (status != STATUS_SUCCESS);
00445 }
00446
#endif //DBG
00447
if (PfnClusterPage->
u3.e1.ReadInProgress != 0) {
00448
00449
ASSERT (PfnClusterPage->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
00450 PfnClusterPage->
u3.e1.ReadInProgress = 0;
00451
00452
if (PfnClusterPage->
u3.e1.InPageError == 0) {
00453 PfnClusterPage->
u1.Event = (
PKEVENT)
NULL;
00454 }
00455 }
00456
MI_REMOVE_LOCKED_PAGE_CHARGE(PfnClusterPage, 9);
00457
MiDecrementReferenceCount (*Page);
00458 }
else {
00459 PageFrameIndex = *Page;
00460 }
00461
00462 CheckPte += 1;
00463 Page += 1;
00464 NumberOfBytes -=
PAGE_SIZE;
00465 }
00466
00467
if (status != STATUS_SUCCESS) {
00468
00469
MI_REMOVE_LOCKED_PAGE_CHARGE(
MI_PFN_ELEMENT(PageFrameIndex), 9);
00470
MiDecrementReferenceCount (PageFrameIndex);
00471
00472
if (status ==
STATUS_PTE_CHANGED) {
00473
00474
00475
00476
00477
00478
00479
UNLOCK_PFN (
APC_LEVEL);
00480
00481
if (WsLockChanged ==
TRUE) {
00482
UNLOCK_SYSTEM_WS (
APC_LEVEL);
00483
LOCK_SESSION_SPACE_WS (OldIrql);
00484 }
00485
00486
return STATUS_SUCCESS;
00487
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 Page = &ReadBlock->
Page[0];
00499
00500 NumberOfBytes = ReadBlock->
Mdl.
ByteCount;
00501
00502
while (NumberOfBytes > 0) {
00503
00504 PfnClusterPage =
MI_PFN_ELEMENT (*Page);
00505
00506
if (PfnClusterPage->
u3.e1.InPageError == 1) {
00507
00508
if (PfnClusterPage->
u3.e2.ReferenceCount == 0) {
00509
00510 PfnClusterPage->
u3.e1.InPageError = 0;
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
if (PfnClusterPage->
u3.e1.PageLocation !=
FreePageList) {
00521
ASSERT (PfnClusterPage->
u3.e1.PageLocation ==
00522
StandbyPageList);
00523
MiUnlinkPageFromList (PfnClusterPage);
00524
MiRestoreTransitionPte (*Page);
00525
MiInsertPageInList (
MmPageLocationList[
FreePageList],
00526 *Page);
00527 }
00528 }
00529 }
00530 Page += 1;
00531 NumberOfBytes -=
PAGE_SIZE;
00532 }
00533
UNLOCK_PFN (
APC_LEVEL);
00534
00535
if (WsLockChanged ==
TRUE) {
00536
UNLOCK_SYSTEM_WS (
APC_LEVEL);
00537
LOCK_SESSION_SPACE_WS (OldIrql);
00538 }
00539
00540
if (status ==
STATUS_REFAULT) {
00541
00542
00543
00544
00545
00546
00547
00548
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
00549
return STATUS_SUCCESS;
00550 }
00551
00552
return status;
00553 }
00554
00555
00556
00557
00558
00559
ASSERT (Pfn1->
u3.e1.InPageError == 0);
00560
00561
if (Pfn1->
u2.ShareCount == 0) {
00562
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9);
00563 }
00564
00565 Pfn1->
u2.ShareCount += 1;
00566 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
00567
00568
MI_MAKE_TRANSITION_PTE_VALID (TempPte, ReadPte);
00569
if (StoreInstruction && TempPte.
u.Hard.Write) {
00570
MI_SET_PTE_DIRTY (TempPte);
00571 }
00572
MI_WRITE_VALID_PTE (ReadPte, TempPte);
00573
00574
if (PointerProtoPte !=
NULL) {
00575
00576
00577
00578
00579
00580
00581
if (PointerPte->u.Hard.Valid == 0) {
00582
#if DBG
00583
NTSTATUS oldstatus = status;
00584
#endif //DBG
00585
00586
00587
00588
00589
00590 status =
MiCompleteProtoPteFault (StoreInstruction,
00591 VirtualAddress,
00592 PointerPte,
00593 PointerProtoPte);
00594
00595
00596
00597
00598
00599
#if DBG
00600
if (PointerPte->u.Hard.Valid == 0) {
00601
DbgPrint (
"MM:PAGFAULT - va %p %p %p status:%lx\n",
00602 VirtualAddress, PointerPte, PointerProtoPte, oldstatus);
00603 }
00604
#endif //DBG
00605
}
00606 }
else {
00607
00608
#if PFN_CONSISTENCY
00609
if (
MiGetPteAddress(ReadPte) ==
MiGetPdeAddress(PTE_BASE)) {
00610 Pfn1->
u3.e1.PageTablePage = 1;
00611 }
00612
#endif
00613
00614
if (Pfn1->
u1.Event == 0) {
00615 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
00616 }
00617
00618
UNLOCK_PFN (
APC_LEVEL);
00619
MiAddValidPageToWorkingSet (VirtualAddress,
00620 ReadPte,
00621 Pfn1,
00622 0);
00623 }
00624
00625
00626
00627
00628
00629
LOCK_PFN (OldIrql);
00630
MiFlushInPageSupportBlock();
00631
UNLOCK_PFN (
APC_LEVEL);
00632
00633
if (status == STATUS_SUCCESS) {
00634 status = STATUS_PAGE_FAULT_PAGING_FILE;
00635 }
00636 NotifyRoutine =
MmHardFaultNotifyRoutine;
00637
if (NotifyRoutine) {
00638 (*NotifyRoutine) (
00639 ReadBlock->
FilePointer,
00640 VirtualAddress
00641 );
00642 }
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
if (
MmIsRetryIoStatus(status)) {
00653
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
00654 status = STATUS_SUCCESS;
00655 }
00656
00657
if ((status ==
STATUS_REFAULT) ||
00658 (status ==
STATUS_PTE_CHANGED)) {
00659 status = STATUS_SUCCESS;
00660 }
00661
00662
ASSERT (KeGetCurrentIrql() ==
APC_LEVEL);
00663
00664
if (WsLockChanged ==
TRUE) {
00665
UNLOCK_SYSTEM_WS (
APC_LEVEL);
00666
LOCK_SESSION_SPACE_WS (OldIrql);
00667 }
00668
00669
return status;
00670 }
00671
00672
00673
NTSTATUS
00674 MiResolveDemandZeroFault (
00675 IN PVOID VirtualAddress,
00676 IN
PMMPTE PointerPte,
00677 IN
PEPROCESS Process,
00678 IN ULONG PrototypePte
00679 )
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 {
00715
PMMPFN Pfn1;
00716 PFN_NUMBER PageFrameIndex;
00717
MMPTE TempPte;
00718 ULONG PageColor;
00719 KIRQL OldIrql;
00720 LOGICAL NeedToZero;
00721 LOGICAL BarrierNeeded;
00722 ULONG BarrierStamp;
00723
00724 NeedToZero =
FALSE;
00725 BarrierNeeded =
FALSE;
00726
00727
PERFINFO_PRIVATE_PAGE_DEMAND_ZERO(VirtualAddress);
00728
00729
00730
00731
00732
00733
00734
if (!
PrototypePte) {
00735
LOCK_PFN (OldIrql);
00736 }
00737
00738
MM_PFN_LOCK_ASSERT();
00739
00740
if (PointerPte->u.Hard.Valid == 0) {
00741
if (!
MiEnsureAvailablePageOrWait (Process,
00742 VirtualAddress)) {
00743
00744
if (Process !=
NULL && Process !=
HYDRA_PROCESS && (!
PrototypePte)) {
00745
00746
00747
00748
00749
00750
00751
if ((Process->ForkInProgress !=
NULL) &&
00752 (Process->ForkInProgress !=
PsGetCurrentThread())) {
00753
MiWaitForForkToComplete (Process);
00754
UNLOCK_PFN (
APC_LEVEL);
00755
return STATUS_REFAULT;
00756 }
00757
00758 Process->NumberOfPrivatePages += 1;
00759 PageColor =
MI_PAGE_COLOR_VA_PROCESS (VirtualAddress,
00760 &Process->NextPageColor);
00761
00762
ASSERT (
MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
00763
00764 PageFrameIndex =
MiRemoveZeroPageIfAny (PageColor);
00765
if (PageFrameIndex) {
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
00776 BarrierStamp = (ULONG)Pfn1->
PteFrame;
00777 }
00778
else {
00779 PageFrameIndex =
MiRemoveAnyPage (PageColor);
00780 NeedToZero =
TRUE;
00781 }
00782 BarrierNeeded =
TRUE;
00783
00784 }
else {
00785 PageColor =
MI_PAGE_COLOR_VA_PROCESS (VirtualAddress,
00786 &
MmSystemPageColor);
00787
00788
00789
00790
00791
00792
00793
if (
PrototypePte) {
00794 PageFrameIndex =
MiRemoveZeroPage (PageColor);
00795 }
else {
00796 PageFrameIndex =
MiRemoveAnyPage (PageColor);
00797 }
00798 }
00799
00800
MmInfoCounters.
DemandZeroCount += 1;
00801
00802
MiInitializePfn (PageFrameIndex, PointerPte, 1);
00803
00804
if (!
PrototypePte) {
00805
UNLOCK_PFN (
APC_LEVEL);
00806 }
00807
00808 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
00809
00810
if (NeedToZero) {
00811
00812
MiZeroPhysicalPage (PageFrameIndex, PageColor);
00813
00814
00815
00816
00817
00818
MI_BARRIER_STAMP_ZEROED_PAGE (&BarrierStamp);
00819 }
00820
00821
00822
00823
00824
00825
00826
PERFINFO_SOFTFAULT(Pfn1, VirtualAddress, PERFINFO_LOG_TYPE_DEMANDZEROFAULT)
00827
00828
MI_MAKE_VALID_PTE (TempPte,
00829 PageFrameIndex,
00830 PointerPte->
u.Soft.Protection,
00831 PointerPte);
00832
00833
if (TempPte.
u.Hard.Write != 0) {
00834
MI_SET_PTE_DIRTY (TempPte);
00835 }
00836
00837
if (BarrierNeeded) {
00838
MI_BARRIER_SYNCHRONIZE (BarrierStamp);
00839 }
00840
00841
MI_WRITE_VALID_PTE (PointerPte, TempPte);
00842
00843
if (!
PrototypePte) {
00844
ASSERT (Pfn1->
u1.Event == 0);
00845
00846
CONSISTENCY_LOCK_PFN (OldIrql);
00847
00848 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
00849
00850
CONSISTENCY_UNLOCK_PFN (OldIrql);
00851
00852
MiAddValidPageToWorkingSet (VirtualAddress,
00853 PointerPte,
00854 Pfn1,
00855 0);
00856 }
00857
return STATUS_PAGE_FAULT_DEMAND_ZERO;
00858 }
00859 }
00860
if (!
PrototypePte) {
00861
UNLOCK_PFN (
APC_LEVEL);
00862 }
00863
return STATUS_REFAULT;
00864 }
00865
00866
00867
NTSTATUS
00868 MiResolveTransitionFault (
00869 IN PVOID FaultingAddress,
00870 IN
PMMPTE PointerPte,
00871 IN
PEPROCESS CurrentProcess,
00872 IN ULONG PfnLockHeld,
00873 OUT PLOGICAL ApcNeeded
00874 )
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
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 PFN_NUMBER PageFrameIndex;
00919
PMMPFN Pfn1;
00920
MMPTE TempPte;
00921
NTSTATUS status;
00922
NTSTATUS PfnStatus;
00923
PMMINPAGE_SUPPORT CapturedEvent;
00924 KIRQL OldIrql;
00925
PETHREAD CurrentThread;
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
if (!PfnLockHeld) {
00942
LOCK_PFN (OldIrql);
00943 }
00944
00945 TempPte = *PointerPte;
00946
00947
if ((TempPte.
u.Soft.Valid == 0) &&
00948 (TempPte.
u.Soft.Prototype == 0) &&
00949 (TempPte.
u.Soft.Transition == 1)) {
00950
00951
00952
00953
00954
00955
MmInfoCounters.
TransitionCount += 1;
00956
00957 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&TempPte);
00958 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
00959
00960
if (Pfn1->
u3.e1.InPageError) {
00961
00962
00963
00964
00965
00966
00967
00968
ASSERT (!
NT_SUCCESS(Pfn1->
u1.ReadStatus));
00969
if (!PfnLockHeld) {
00970
UNLOCK_PFN (
APC_LEVEL);
00971 }
00972
00973
return Pfn1->
u1.ReadStatus;
00974 }
00975
00976
if (Pfn1->
u3.e1.ReadInProgress) {
00977
00978
00979
00980
00981
00982
#if DBG
00983
if (MmDebug &
MM_DBG_COLLIDED_PAGE) {
00984
DbgPrint(
"MM:collided page fault\n");
00985 }
00986
#endif
00987
00988 CapturedEvent = (
PMMINPAGE_SUPPORT)Pfn1->
u1.Event;
00989
00990 CurrentThread =
PsGetCurrentThread();
00991
00992
if (CapturedEvent->
u.Thread == CurrentThread) {
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
ASSERT ((CurrentThread->
NestedFaultCount == 1) ||
01015 (CurrentThread->
NestedFaultCount == 2));
01016
01017 CurrentThread->
ApcNeeded = 1;
01018
01019
if (!PfnLockHeld) {
01020
UNLOCK_PFN (
APC_LEVEL);
01021 }
01022
return STATUS_MULTIPLE_FAULT_VIOLATION;
01023 }
01024
01025
01026
01027
01028
01029
01030
ASSERT (Pfn1->
u2.ShareCount == 0);
01031
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
01032
ASSERT (Pfn1->
u3.e1.LockCharged == 1);
01033
01034 Pfn1->
u3.e2.ReferenceCount += 1;
01035
01036 CapturedEvent->
WaitCount += 1;
01037
01038
UNLOCK_PFN (
APC_LEVEL);
01039
01040
if (CurrentProcess ==
HYDRA_PROCESS) {
01041 CurrentThread =
NULL;
01042
UNLOCK_SESSION_SPACE_WS (
APC_LEVEL);
01043 }
01044
else if (CurrentProcess !=
NULL) {
01045
01046
01047
01048
01049
01050
01051
01052
01053
ASSERT (CurrentThread->
NestedFaultCount <= 2);
01054 CurrentThread->
NestedFaultCount += 1;
01055
01056
KeEnterCriticalRegion();
01057
UNLOCK_WS (CurrentProcess);
01058 }
01059
else {
01060 CurrentThread =
NULL;
01061
UNLOCK_SYSTEM_WS (
APC_LEVEL);
01062 }
01063
01064 status =
MiWaitForInPageComplete (Pfn1,
01065 PointerPte,
01066 FaultingAddress,
01067 &TempPte,
01068 CapturedEvent,
01069 CurrentProcess);
01070
01071
01072
01073
01074
01075
if (CurrentThread !=
NULL) {
01076
KeLeaveCriticalRegion();
01077
01078
ASSERT (CurrentThread->
NestedFaultCount <= 3);
01079
ASSERT (CurrentThread->
NestedFaultCount != 0);
01080
01081 CurrentThread->
NestedFaultCount -= 1;
01082
01083
if ((CurrentThread->
ApcNeeded == 1) &&
01084 (CurrentThread->
NestedFaultCount == 0)) {
01085 *ApcNeeded =
TRUE;
01086 CurrentThread->
ApcNeeded = 0;
01087 }
01088 }
01089
01090
ASSERT (Pfn1->
u3.e1.ReadInProgress == 0);
01091
01092
if (status != STATUS_SUCCESS) {
01093 PfnStatus = Pfn1->
u1.ReadStatus;
01094
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 9);
01095
MiDecrementReferenceCount (PageFrameIndex);
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
if (Pfn1->
u3.e1.InPageError == 1) {
01107
ASSERT (!
NT_SUCCESS(PfnStatus));
01108 status = PfnStatus;
01109
if (Pfn1->
u3.e2.ReferenceCount == 0) {
01110
01111 Pfn1->
u3.e1.InPageError = 0;
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
if (Pfn1->
u3.e1.PageLocation !=
FreePageList) {
01122
ASSERT (Pfn1->
u3.e1.PageLocation ==
01123
StandbyPageList);
01124
MiUnlinkPageFromList (Pfn1);
01125
MiRestoreTransitionPte (PageFrameIndex);
01126
01127
MiInsertPageInList(
MmPageLocationList[
FreePageList],
01128 PageFrameIndex);
01129 }
01130 }
01131 }
01132
01133
#if DBG
01134
if (MmDebug &
MM_DBG_COLLIDED_PAGE) {
01135
DbgPrint(
"MM:decrement ref count - pte changed\n");
01136
MiFormatPfn(Pfn1);
01137 }
01138
#endif
01139
if (!PfnLockHeld) {
01140
UNLOCK_PFN (
APC_LEVEL);
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
return STATUS_REFAULT;
01155 }
01156
01157 }
else {
01158
01159
01160
01161
01162
01163
ASSERT (Pfn1->
u3.e1.InPageError == 0);
01164
if (Pfn1->
u3.e1.PageLocation ==
ActiveAndValid) {
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
ASSERT (((Pfn1->
PteAddress >=
MiGetPteAddress(
MmPagedPoolStart)) &&
01179 (Pfn1->
PteAddress <=
MiGetPteAddress(
MmPagedPoolEnd))) ||
01180 ((Pfn1->
PteAddress >=
MiGetPteAddress(
MmSpecialPoolStart)) &&
01181 (Pfn1->
PteAddress <=
MiGetPteAddress(
MmSpecialPoolEnd))));
01182
01183
01184
01185
01186
01187
01188
ASSERT (Pfn1->
u2.ShareCount != 0);
01189
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
01190
01191 }
else {
01192
01193
MiUnlinkPageFromList (Pfn1);
01194
01195
01196
01197
01198
01199
01200
ASSERT (Pfn1->
u2.ShareCount == 0);
01201
01202
01203
01204
01205
01206
01207
01208
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 8);
01209
01210 Pfn1->
u3.e2.ReferenceCount += 1;
01211 }
01212 }
01213
01214
01215
01216
01217
01218
01219
ASSERT (Pfn1->
u3.e1.InPageError == 0);
01220
01221
if (Pfn1->
u2.ShareCount == 0) {
01222
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9);
01223 }
01224
01225 Pfn1->
u2.ShareCount += 1;
01226 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
01227
01228
MI_MAKE_TRANSITION_PTE_VALID (TempPte, PointerPte);
01229
01230
01231
01232
01233
01234
01235
01236
01237
if (Pfn1->
u3.e1.Modified && TempPte.
u.Hard.Write &&
01238 (TempPte.
u.Hard.CopyOnWrite == 0)) {
01239
MI_SET_PTE_DIRTY (TempPte);
01240 }
else {
01241
MI_SET_PTE_CLEAN (TempPte);
01242 }
01243
01244
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01245
01246
if (!PfnLockHeld) {
01247
01248
if (Pfn1->
u1.Event == 0) {
01249 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
01250 }
01251
01252
UNLOCK_PFN (
APC_LEVEL);
01253
01254
PERFINFO_SOFTFAULT(Pfn1, FaultingAddress, PERFINFO_LOG_TYPE_TRANSITIONFAULT)
01255
01256
MiAddValidPageToWorkingSet (FaultingAddress,
01257 PointerPte,
01258 Pfn1,
01259 0);
01260 }
01261
return STATUS_PAGE_FAULT_TRANSITION;
01262 }
else {
01263
if (!PfnLockHeld) {
01264
UNLOCK_PFN (
APC_LEVEL);
01265 }
01266 }
01267
return STATUS_REFAULT;
01268 }
01269
01270
01271
NTSTATUS
01272 MiResolvePageFileFault (
01273 IN PVOID FaultingAddress,
01274 IN
PMMPTE PointerPte,
01275 OUT
PMMINPAGE_SUPPORT *ReadBlock,
01276 IN
PEPROCESS Process
01277 )
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 {
01311 LARGE_INTEGER StartingOffset;
01312 PFN_NUMBER PageFrameIndex;
01313 ULONG PageFileNumber;
01314 ULONG WorkingSetIndex;
01315 ULONG PageColor;
01316
MMPTE TempPte;
01317
PETHREAD CurrentThread;
01318
PMMINPAGE_SUPPORT ReadBlockLocal;
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 CurrentThread =
PsGetCurrentThread();
01329 TempPte = *PointerPte;
01330
01331
if (TempPte.
u.Hard.Valid == 1) {
01332
UNLOCK_PFN (
APC_LEVEL);
01333
return STATUS_REFAULT;
01334 }
01335
01336
ASSERT (TempPte.
u.Soft.Prototype == 0);
01337
ASSERT (TempPte.
u.Soft.Transition == 0);
01338
01339 PageFileNumber =
GET_PAGING_FILE_NUMBER (TempPte);
01340 StartingOffset.LowPart =
GET_PAGING_FILE_OFFSET (TempPte);
01341
01342
ASSERT (StartingOffset.LowPart <=
MmPagingFile[PageFileNumber]->
Size);
01343
01344 StartingOffset.HighPart = 0;
01345 StartingOffset.QuadPart = StartingOffset.QuadPart <<
PAGE_SHIFT;
01346
01347
MM_PFN_LOCK_ASSERT();
01348
if (
MiEnsureAvailablePageOrWait (Process,
01349 FaultingAddress)) {
01350
01351
01352
01353
01354
01355
01356
UNLOCK_PFN (
APC_LEVEL);
01357
return STATUS_REFAULT;
01358 }
01359
01360 ReadBlockLocal =
MiGetInPageSupportBlock ();
01361
if (ReadBlockLocal ==
NULL) {
01362
UNLOCK_PFN (
APC_LEVEL);
01363
return STATUS_REFAULT;
01364 }
01365
MmInfoCounters.
PageReadCount += 1;
01366
MmInfoCounters.
PageReadIoCount += 1;
01367
01368 *ReadBlock = ReadBlockLocal;
01369
01370
01371
01372 ReadBlockLocal->
FilePointer =
MmPagingFile[PageFileNumber]->
File;
01373
01374
#if DBG
01375
01376
if (((StartingOffset.QuadPart >>
PAGE_SHIFT) < 8192) && (PageFileNumber == 0)) {
01377
if ((
MmPagingFileDebug[StartingOffset.QuadPart >>
PAGE_SHIFT] & ~0x1f) !=
01378 ((ULONG_PTR)PointerPte << 3)) {
01379
if ((
MmPagingFileDebug[StartingOffset.QuadPart >>
PAGE_SHIFT] & ~0x1f) !=
01380 ((ULONG_PTR)(
MiGetPteAddress(FaultingAddress)) << 3)) {
01381
01382
DbgPrint(
"MMINPAGE: Mismatch PointerPte %p Offset %I64X info %p\n",
01383 PointerPte,
01384 StartingOffset.QuadPart >>
PAGE_SHIFT,
01385
MmPagingFileDebug[StartingOffset.QuadPart >>
PAGE_SHIFT]);
01386
01387 DbgBreakPoint();
01388 }
01389 }
01390 }
01391
01392
#endif //DBG
01393
01394 ReadBlockLocal->ReadOffset = StartingOffset;
01395
01396
01397
01398
01399
01400
01401
if (Process ==
HYDRA_PROCESS) {
01402 PageColor =
MI_GET_PAGE_COLOR_FROM_SESSION (
MmSessionSpace);
01403 }
01404
else if (Process ==
NULL) {
01405 PageColor =
MI_GET_PAGE_COLOR_FROM_VA(FaultingAddress);
01406 }
01407
else {
01408 PageColor =
MI_PAGE_COLOR_VA_PROCESS (FaultingAddress,
01409 &Process->NextPageColor);
01410 }
01411
01412 ReadBlockLocal->BasePte = PointerPte;
01413
01414
01415
01416
01417
01418
MmInitializeMdl(&ReadBlockLocal->Mdl,
PAGE_ALIGN(FaultingAddress),
PAGE_SIZE);
01419 ReadBlockLocal->Mdl.MdlFlags |= (
MDL_PAGES_LOCKED |
MDL_IO_PAGE_READ);
01420
01421
if (
MI_IS_PAGE_TABLE_ADDRESS(PointerPte)) {
01422 WorkingSetIndex = 1;
01423 }
else {
01424 WorkingSetIndex =
MI_PROTOTYPE_WSINDEX;
01425 }
01426
01427 PageFrameIndex =
MiRemoveAnyPage (PageColor);
01428
01429 ReadBlockLocal->Pfn =
MI_PFN_ELEMENT (PageFrameIndex);
01430 ReadBlockLocal->Page[0] = PageFrameIndex;
01431
01432
MiInitializeReadInProgressPfn (
01433 &ReadBlockLocal->Mdl,
01434 PointerPte,
01435 &ReadBlockLocal->Event,
01436 WorkingSetIndex);
01437
01438
MI_RETRIEVE_USED_PAGETABLE_ENTRIES_FROM_PTE (ReadBlockLocal, &TempPte);
01439
01440
UNLOCK_PFN (
APC_LEVEL);
01441
01442
return STATUS_ISSUE_PAGING_IO;
01443 }
01444
01445
NTSTATUS
01446 MiResolveProtoPteFault (
01447 IN BOOLEAN StoreInstruction,
01448 IN PVOID FaultingAddress,
01449 IN
PMMPTE PointerPte,
01450 IN
PMMPTE PointerProtoPte,
01451 OUT
PMMINPAGE_SUPPORT *ReadBlock,
01452 IN
PEPROCESS Process,
01453 OUT PLOGICAL ApcNeeded
01454 )
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495 {
01496
MMPTE TempPte;
01497 PFN_NUMBER PageFrameIndex;
01498
PMMPFN Pfn1;
01499
NTSTATUS status;
01500 ULONG CopyOnWrite;
01501 LOGICAL PfnHeld;
01502
01503 PfnHeld =
FALSE;
01504
01505
01506
01507
01508
01509
01510
MM_PFN_LOCK_ASSERT();
01511
01512
#if DBG
01513
if (MmDebug &
MM_DBG_PTE_UPDATE) {
01514
DbgPrint(
"MM:actual fault %p va %p\n",PointerPte, FaultingAddress);
01515
MiFormatPte(PointerPte);
01516 }
01517
#endif //DBG
01518
01519
ASSERT (PointerPte->u.Soft.Prototype == 1);
01520 TempPte = *PointerProtoPte;
01521
01522
01523
01524
01525
01526
01527
01528
01529
if (TempPte.
u.Hard.Valid) {
01530
01531
01532
01533
01534
01535 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
01536 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex);
01537 Pfn1->
u2.ShareCount += 1;
01538 status = STATUS_SUCCESS;
01539
01540
01541
01542
01543
01544
MmInfoCounters.
TransitionCount += 1;
01545 PfnHeld =
TRUE;
01546
01547
PERFINFO_SOFTFAULT(Pfn1, FaultingAddress, PERFINFO_LOG_TYPE_ADDVALIDPAGETOWS)
01548
01549 }
else {
01550
01551
01552
01553
01554
01555
if (TempPte.
u.Long == 0) {
01556
01557
#if DBG
01558
if (MmDebug &
MM_DBG_STOP_ON_ACCVIO) {
01559
DbgPrint(
"MM:access vio2 - %p\n",FaultingAddress);
01560
MiFormatPte(PointerPte);
01561 DbgBreakPoint();
01562 }
01563
#endif //DEBUG
01564
01565
UNLOCK_PFN (
APC_LEVEL);
01566
return STATUS_ACCESS_VIOLATION;
01567 }
01568
01569
01570
01571
01572
01573
01574 CopyOnWrite =
FALSE;
01575
01576
if (PointerPte->u.Soft.PageFileHigh !=
MI_PTE_LOOKUP_NEEDED) {
01577
if (PointerPte->u.Proto.ReadOnly == 0) {
01578
01579
01580
01581
01582
01583
01584
#if 0 // removed this assert since mapping drivers via MmMapViewInSystemSpace
01585
01586
01587 {
01588
PSUBSECTION Sub;
01589
if (PointerProtoPte->u.Soft.Prototype == 1) {
01590 Sub =
MiGetSubsectionAddress (PointerProtoPte);
01591
ASSERT (Sub->
u.SubsectionFlags.Protection ==
01592 PointerProtoPte->u.Soft.Protection);
01593 }
01594 }
01595
01596
#endif //DBG
01597
01598 status =
MiAccessCheck (PointerProtoPte,
01599 StoreInstruction,
01600
KernelMode,
01601
MI_GET_PROTECTION_FROM_SOFT_PTE (PointerProtoPte),
01602
TRUE);
01603
01604
if (status != STATUS_SUCCESS) {
01605
#if DBG
01606
if (MmDebug &
MM_DBG_STOP_ON_ACCVIO) {
01607
DbgPrint(
"MM:access vio3 - %p\n",FaultingAddress);
01608
MiFormatPte(PointerPte);
01609
MiFormatPte(PointerProtoPte);
01610 DbgBreakPoint();
01611 }
01612
#endif
01613
UNLOCK_PFN (
APC_LEVEL);
01614
return status;
01615 }
01616
if ((PointerProtoPte->u.Soft.Protection &
MM_COPY_ON_WRITE_MASK) ==
01617
MM_COPY_ON_WRITE_MASK) {
01618 CopyOnWrite =
TRUE;
01619 }
01620 }
01621 }
else {
01622
if ((PointerPte->u.Soft.Protection &
MM_COPY_ON_WRITE_MASK) ==
01623
MM_COPY_ON_WRITE_MASK) {
01624 CopyOnWrite =
TRUE;
01625 }
01626 }
01627
01628
if ((!
IS_PTE_NOT_DEMAND_ZERO(TempPte)) && (CopyOnWrite)) {
01629
01630
01631
01632
01633
01634
01635
ASSERT (Process !=
NULL);
01636
01637 PointerPte->u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
01638
01639
UNLOCK_PFN (
APC_LEVEL);
01640
01641 status =
MiResolveDemandZeroFault (FaultingAddress,
01642 PointerPte,
01643 Process,
01644
FALSE);
01645
return status;
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
if (TempPte.
u.Soft.Prototype == 1) {
01658
01659
01660
01661
01662
01663 status =
MiResolveMappedFileFault (FaultingAddress,
01664 PointerProtoPte,
01665 ReadBlock,
01666 Process);
01667
01668
01669
01670
01671
01672 PfnHeld =
TRUE;
01673
01674 }
else if (TempPte.
u.Soft.Transition == 1) {
01675
01676
01677
01678
01679
01680 status =
MiResolveTransitionFault (FaultingAddress,
01681 PointerProtoPte,
01682 Process,
01683
TRUE,
01684 ApcNeeded);
01685
01686
01687
01688
01689
01690 PfnHeld =
TRUE;
01691
01692 }
else if (TempPte.
u.Soft.PageFileHigh == 0) {
01693
01694
01695
01696
01697
01698 status =
MiResolveDemandZeroFault (FaultingAddress,
01699 PointerProtoPte,
01700 Process,
01701
TRUE);
01702
01703
01704
01705
01706
01707 PfnHeld =
TRUE;
01708
01709 }
else {
01710
01711
01712
01713
01714
01715 status =
MiResolvePageFileFault (FaultingAddress,
01716 PointerProtoPte,
01717 ReadBlock,
01718 Process);
01719
01720
01721
01722
01723
ASSERT (KeGetCurrentIrql() ==
APC_LEVEL);
01724 }
01725 }
01726
01727
if (
NT_SUCCESS(status)) {
01728
01729
ASSERT (PointerPte->u.Hard.Valid == 0);
01730
01731
MiCompleteProtoPteFault (StoreInstruction,
01732 FaultingAddress,
01733 PointerPte,
01734 PointerProtoPte);
01735
01736 }
else {
01737
01738
if (PfnHeld) {
01739
UNLOCK_PFN (
APC_LEVEL);
01740 }
01741
01742
ASSERT (KeGetCurrentIrql() ==
APC_LEVEL);
01743
01744
01745
01746
01747
01748
01749
01750
01751
if (
MmIsRetryIoStatus(status)) {
01752
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
01753 status =
STATUS_REFAULT;
01754 }
01755 }
01756
01757
return status;
01758 }
01759
01760
01761
NTSTATUS
01762 MiCompleteProtoPteFault (
01763 IN BOOLEAN StoreInstruction,
01764 IN PVOID FaultingAddress,
01765 IN
PMMPTE PointerPte,
01766 IN
PMMPTE PointerProtoPte
01767 )
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 {
01800
MMPTE TempPte;
01801
MMWSLE ProtoProtect;
01802 PFN_NUMBER PageFrameIndex;
01803
PMMPFN Pfn1;
01804
PMMPFN Pfn2;
01805
PMMPTE ContainingPageTablePointer;
01806
#if defined(_PREFETCH_)
01807
PFILE_OBJECT FileObject;
01808 LONGLONG FileOffset;
01809
PSUBSECTION Subsection;
01810
#endif
01811
01812
MM_PFN_LOCK_ASSERT();
01813
01814 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerProtoPte);
01815 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex);
01816 Pfn1->
u3.e1.PrototypePte = 1;
01817
01818
#if defined(_PREFETCH_)
01819
01820
01821
01822
01823
01824 FileObject =
NULL;
01825
01826
if (CCPF_IS_PREFETCHER_ACTIVE()) {
01827
01828
if (FaultingAddress < MM_HIGHEST_USER_ADDRESS) {
01829
01830 TempPte = Pfn1->
OriginalPte;
01831
01832
if (TempPte.
u.Soft.Prototype == 1) {
01833
01834 Subsection =
MiGetSubsectionAddress (&TempPte);
01835
01836
if (Subsection->
ControlArea->
u.Flags.Image) {
01837
01838 FileObject = Subsection->
ControlArea->
FilePointer;
01839
ASSERT (FileObject->
FileName.Length > 0);
01840
01841 FileOffset =
MI_STARTING_OFFSET (Subsection,
01842 PointerProtoPte);
01843 }
01844 }
01845 }
01846 }
01847
01848
#endif
01849
01850
01851
01852
01853
01854
ASSERT (PointerProtoPte->u.Hard.Valid == 1);
01855
01856
01857
01858
01859
01860
01861
01862
01863 ContainingPageTablePointer =
MiGetPteAddress(PointerPte);
01864 Pfn2 =
MI_PFN_ELEMENT(ContainingPageTablePointer->
u.Hard.PageFrameNumber);
01865 Pfn2->
u2.ShareCount += 1;
01866
01867 ProtoProtect.
u1.Long = 0;
01868
if (PointerPte->u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED) {
01869
01870
01871
01872
01873
01874
01875 ProtoProtect.
u1.e1.Protection =
MI_GET_PROTECTION_FROM_SOFT_PTE(PointerPte);
01876
01877 }
else {
01878
01879
01880
01881
01882
01883 ProtoProtect.
u1.e1.Protection =
MI_GET_PROTECTION_FROM_SOFT_PTE(&Pfn1->
OriginalPte);
01884 ProtoProtect.
u1.e1.SameProtectAsProto = 1;
01885
01886
if (StoreInstruction ==
TRUE && (ProtoProtect.
u1.e1.Protection &
MM_PROTECTION_WRITE_MASK) == 0) {
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
#if DBG
01900
DbgPrint(
"MM: user tried to write to a readonly subsection in the image! %p %p %p\n",
01901 FaultingAddress,
01902 PointerPte,
01903 PointerProtoPte);
01904
#endif
01905
StoreInstruction =
FALSE;
01906 }
01907 }
01908
01909
MI_MAKE_VALID_PTE (TempPte,
01910 PageFrameIndex,
01911 ProtoProtect.
u1.e1.Protection,
01912 PointerPte);
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
if ((StoreInstruction) && (TempPte.
u.Hard.CopyOnWrite == 0)) {
01923
01924
#if DBG
01925
if (
MiHydra ==
TRUE) {
01926
01927 PVOID Va;
01928
01929 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
01930
01931
01932
01933
01934
01935
ASSERT (!
MI_IS_SESSION_IMAGE_ADDRESS (Va));
01936 }
01937
#endif
01938
01939 Pfn1->
u3.e1.Modified = 1;
01940
MI_SET_PTE_DIRTY (TempPte);
01941
if ((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
01942 (Pfn1->
u3.e1.WriteInProgress == 0)) {
01943
MiReleasePageFileSpace (Pfn1->
OriginalPte);
01944 Pfn1->
OriginalPte.
u.Soft.PageFileHigh = 0;
01945 }
01946 }
01947
01948
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01949
01950
if (Pfn1->
u1.Event ==
NULL) {
01951 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
01952 }
01953
01954
UNLOCK_PFN (
APC_LEVEL);
01955
01956
PERFINFO_SOFTFAULT(Pfn1, FaultingAddress, PERFINFO_LOG_TYPE_PROTOPTEFAULT);
01957
01958
MiAddValidPageToWorkingSet (FaultingAddress,
01959 PointerPte,
01960 Pfn1,
01961 (ULONG) ProtoProtect.
u1.Long);
01962
01963
#if defined(_PREFETCH_)
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
if (FileObject !=
NULL) {
01977 CcPfLogPageFault (FileObject, FileOffset,
PsGetCurrentProcess());
01978 }
01979
01980
#endif
01981
01982
ASSERT (PointerPte ==
MiGetPteAddress(FaultingAddress));
01983
01984
return STATUS_SUCCESS;
01985 }
01986
01987
01988
NTSTATUS
01989 MiResolveMappedFileFault (
01990 IN PVOID FaultingAddress,
01991 IN
PMMPTE PointerPte,
01992 OUT
PMMINPAGE_SUPPORT *ReadBlock,
01993 IN
PEPROCESS Process
01994 )
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 {
02028 PFN_NUMBER PageFrameIndex;
02029
PMMPFN Pfn1;
02030
PSUBSECTION Subsection;
02031
PMDL Mdl;
02032 ULONG ReadSize;
02033
PETHREAD CurrentThread;
02034 PPFN_NUMBER Page;
02035 PPFN_NUMBER EndPage;
02036
PMMPTE BasePte;
02037
PMMPTE CheckPte;
02038 LARGE_INTEGER StartingOffset;
02039 LARGE_INTEGER TempOffset;
02040 PPFN_NUMBER FirstMdlPage;
02041
PMMINPAGE_SUPPORT ReadBlockLocal;
02042 ULONG PageColor;
02043 ULONG ClusterSize;
02044 ULONG Result;
02045
02046 ClusterSize = 0;
02047
02048
ASSERT (PointerPte->u.Soft.Prototype == 1);
02049
02050
02051
02052
02053
02054
if (Process ==
HYDRA_PROCESS) {
02055 Result =
MiEnsureAvailablePageOrWait (
NULL, FaultingAddress);
02056 }
02057
else {
02058 Result =
MiEnsureAvailablePageOrWait (Process, FaultingAddress);
02059 }
02060
02061
if (Result) {
02062
02063
02064
02065
02066
02067
02068
return STATUS_REFAULT;
02069 }
02070
02071
#if DBG
02072
if (MmDebug &
MM_DBG_PTE_UPDATE) {
02073
MiFormatPte (PointerPte);
02074 }
02075
#endif //DBG
02076
02077
02078
02079
02080
02081 Subsection =
MiGetSubsectionAddress (PointerPte);
02082
02083
#ifdef LARGE_PAGES
02084
02085
02086
02087
02088
02089
02090
if (Subsection->
u.SubsectionFlags.LargePages == 1) {
02091
KeFlushEntireTb (
TRUE,
TRUE);
02092 KeFillLargeEntryTb ((PHARDWARE_PTE)(Subsection + 1),
02093 FaultingAddress,
02094 Subsection->StartingSector);
02095
02096
return STATUS_REFAULT;
02097 }
02098
#endif //LARGE_PAGES
02099
02100
if (Subsection->
ControlArea->
u.Flags.FailAllIo) {
02101
return STATUS_IN_PAGE_ERROR;
02102 }
02103
02104
if (PointerPte >= &Subsection->
SubsectionBase[Subsection->
PtesInSubsection]) {
02105
02106
02107
02108
02109
02110
return STATUS_ACCESS_VIOLATION;
02111 }
02112
02113 CurrentThread =
PsGetCurrentThread();
02114
02115 ReadBlockLocal =
MiGetInPageSupportBlock ();
02116
if (ReadBlockLocal ==
NULL) {
02117
return STATUS_REFAULT;
02118 }
02119 *ReadBlock = ReadBlockLocal;
02120
02121
02122
02123
02124
02125 Mdl = &ReadBlockLocal->Mdl;
02126
02127 FirstMdlPage = &ReadBlockLocal->Page[0];
02128 Page = FirstMdlPage;
02129
02130
#if DBG
02131
RtlFillMemoryUlong( Page, (
MM_MAXIMUM_READ_CLUSTER_SIZE+1) *
sizeof(PFN_NUMBER), 0xf1f1f1f1);
02132
#endif //DBG
02133
02134 ReadSize =
PAGE_SIZE;
02135 BasePte = PointerPte;
02136
02137
02138
02139
02140
02141
if ((!CurrentThread->
DisablePageFaultClustering) &&
02142
PERFINFO_DO_PAGEFAULT_CLUSTERING() &&
02143 (Subsection->
ControlArea->
u.Flags.NoModifiedWriting == 0)) {
02144
02145
if ((
MmAvailablePages > (
MmFreeGoal * 2))
02146 ||
02147 (((Subsection->
ControlArea->
u.Flags.Image != 0) ||
02148 (CurrentThread->
ForwardClusterOnly)) &&
02149 (
MmAvailablePages > (
MM_MAXIMUM_READ_CLUSTER_SIZE + 16)))) {
02150
02151
02152
02153
02154
02155
if (Subsection->
ControlArea->
u.Flags.Image == 0) {
02156
ASSERT (CurrentThread->
ReadClusterSize <=
02157
MM_MAXIMUM_READ_CLUSTER_SIZE);
02158 ClusterSize = CurrentThread->
ReadClusterSize;
02159 }
else {
02160 ClusterSize =
MmDataClusterSize;
02161
if (Subsection->
u.SubsectionFlags.Protection &
02162
MM_PROTECTION_EXECUTE_MASK ) {
02163 ClusterSize =
MmCodeClusterSize;
02164 }
02165 }
02166 EndPage = Page + ClusterSize;
02167
02168 CheckPte = PointerPte + 1;
02169
02170
02171
02172
02173
02174
while ((
MiIsPteOnPdeBoundary(CheckPte) == 0) &&
02175 (Page < EndPage) &&
02176 (CheckPte <
02177 &Subsection->
SubsectionBase[Subsection->
PtesInSubsection])
02178 && (CheckPte->
u.Long == BasePte->
u.Long)) {
02179
02180 Subsection->
ControlArea->
NumberOfPfnReferences += 1;
02181 ReadSize +=
PAGE_SIZE;
02182 Page += 1;
02183 CheckPte += 1;
02184 }
02185
02186
if ((Page < EndPage) && (!CurrentThread->
ForwardClusterOnly)) {
02187
02188
02189
02190
02191
02192 CheckPte = PointerPte - 1;
02193
02194
while ((((ULONG_PTR)CheckPte & (
PAGE_SIZE - 1)) !=
02195 (
PAGE_SIZE -
sizeof(
MMPTE))) &&
02196 (Page < EndPage) &&
02197 (CheckPte >= Subsection->
SubsectionBase) &&
02198 (CheckPte->
u.Long == BasePte->
u.Long)) {
02199
02200 Subsection->
ControlArea->
NumberOfPfnReferences += 1;
02201 ReadSize +=
PAGE_SIZE;
02202 Page += 1;
02203 CheckPte -= 1;
02204 }
02205 BasePte = CheckPte + 1;
02206 }
02207 }
02208 }
02209
02210
02211
02212
02213
02214
02215
02216 StartingOffset.QuadPart =
MiStartingOffset (Subsection, BasePte);
02217
02218 TempOffset =
MiEndingOffset(Subsection);
02219
02220
ASSERT (StartingOffset.QuadPart < TempOffset.QuadPart);
02221
02222
02223
02224
02225
02226
02227
02228 EndPage = FirstMdlPage;
02229 CheckPte = BasePte;
02230
02231
while (EndPage < Page) {
02232
if (Process ==
HYDRA_PROCESS) {
02233 PageColor =
MI_GET_PAGE_COLOR_FROM_SESSION (
MmSessionSpace);
02234 }
02235
else if (Process ==
NULL) {
02236 PageColor =
MI_GET_PAGE_COLOR_FROM_PTE (CheckPte);
02237 }
02238
else {
02239 PageColor =
MI_PAGE_COLOR_PTE_PROCESS (CheckPte,
02240 &Process->NextPageColor);
02241 }
02242 *EndPage =
MiRemoveAnyPage (PageColor);
02243
02244 EndPage += 1;
02245 CheckPte += 1;
02246 }
02247
02248
if (Process ==
HYDRA_PROCESS) {
02249 PageColor =
MI_GET_PAGE_COLOR_FROM_SESSION (
MmSessionSpace);
02250 }
02251
else if (Process ==
NULL) {
02252 PageColor =
MI_GET_PAGE_COLOR_FROM_PTE (CheckPte);
02253 }
02254
else {
02255 PageColor =
MI_PAGE_COLOR_PTE_PROCESS (CheckPte,
02256 &Process->NextPageColor);
02257 }
02258
02259
02260
02261
02262
02263
02264
MmInfoCounters.
PageReadIoCount += 1;
02265
MmInfoCounters.
PageReadCount += ReadSize >>
PAGE_SHIFT;
02266
02267
if ((Subsection->
ControlArea->
u.Flags.Image) &&
02268 (((UINT64)StartingOffset.QuadPart + ReadSize) > (UINT64)TempOffset.QuadPart)) {
02269
02270
ASSERT ((ULONG)(TempOffset.QuadPart - StartingOffset.QuadPart)
02271 > (ReadSize -
PAGE_SIZE));
02272
02273 ReadSize = (ULONG)(TempOffset.QuadPart - StartingOffset.QuadPart);
02274
02275 PageFrameIndex =
MiRemoveZeroPage (PageColor);
02276
02277 }
else {
02278
02279
02280
02281
02282
02283 PageFrameIndex =
MiRemoveAnyPage (PageColor);
02284 }
02285
02286
02287
02288
02289
02290
02291 Subsection->
ControlArea->
NumberOfPfnReferences += 1;
02292 *Page = PageFrameIndex;
02293
02294 PageFrameIndex = *(FirstMdlPage + (PointerPte - BasePte));
02295
02296
02297
02298
02299
02300
02301 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02302
02303
02304
02305
02306
02307
MmInitializeMdl(Mdl,
02308
MiGetVirtualAddressMappedByPte (BasePte),
02309 ReadSize);
02310 Mdl->
MdlFlags |= (
MDL_PAGES_LOCKED |
MDL_IO_PAGE_READ);
02311
02312
#if DBG
02313
if (ReadSize > ((ClusterSize + 1) <<
PAGE_SHIFT)) {
02314
KeBugCheckEx (MEMORY_MANAGEMENT, 0x777,(ULONG_PTR)Mdl, (ULONG_PTR)Subsection,
02315 (ULONG)TempOffset.LowPart);
02316 }
02317
#endif //DBG
02318
02319
MiInitializeReadInProgressPfn (Mdl,
02320 BasePte,
02321 &ReadBlockLocal->Event,
02322
MI_PROTOTYPE_WSINDEX);
02323
02324
MI_ZERO_USED_PAGETABLE_ENTRIES_IN_INPAGE_SUPPORT(ReadBlockLocal);
02325
02326 ReadBlockLocal->ReadOffset = StartingOffset;
02327 ReadBlockLocal->FilePointer = Subsection->
ControlArea->
FilePointer;
02328 ReadBlockLocal->BasePte = BasePte;
02329 ReadBlockLocal->Pfn = Pfn1;
02330
02331
return STATUS_ISSUE_PAGING_IO;
02332 }
02333
02334
NTSTATUS
02335 MiWaitForInPageComplete (
02336 IN
PMMPFN Pfn2,
02337 IN
PMMPTE PointerPte,
02338 IN PVOID FaultingAddress,
02339 IN
PMMPTE PointerPteContents,
02340 IN
PMMINPAGE_SUPPORT InPageSupport,
02341 IN
PEPROCESS CurrentProcess
02342 )
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378 {
02379
PMMPTE NewPointerPte;
02380
PMMPTE ProtoPte;
02381
PMMPFN Pfn1;
02382
PMMPFN Pfn;
02383 PULONG Va;
02384 PPFN_NUMBER Page;
02385 PPFN_NUMBER LastPage;
02386 ULONG
Offset;
02387 ULONG Protection;
02388
PMDL Mdl;
02389 KIRQL OldIrql;
02390
NTSTATUS status;
02391
NTSTATUS status2;
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
KeWaitForSingleObject( &InPageSupport->Event,
02402
WrPageIn,
02403
KernelMode,
02404
FALSE,
02405 (PLARGE_INTEGER)
NULL);
02406
02407
if (CurrentProcess ==
HYDRA_PROCESS) {
02408
LOCK_SESSION_SPACE_WS (OldIrql);
02409 }
02410
else if (CurrentProcess !=
NULL) {
02411
LOCK_WS (CurrentProcess);
02412 }
02413
else {
02414
LOCK_SYSTEM_WS (OldIrql);
02415 }
02416
02417
LOCK_PFN (OldIrql);
02418
02419
ASSERT (Pfn2->u3.e2.ReferenceCount != 0);
02420
02421
02422
02423
02424
02425
02426 Pfn = InPageSupport->Pfn;
02427
if (Pfn2 != Pfn) {
02428
ASSERT (Pfn2->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
02429 Pfn2->u3.e1.ReadInProgress = 0;
02430 }
02431
02432
02433
02434
02435
02436
02437
02438
if (Pfn2->u3.e1.InPageError == 1) {
02439
ASSERT (!
NT_SUCCESS(Pfn2->u1.ReadStatus));
02440
MiFreeInPageSupportBlock (InPageSupport);
02441
02442
if (
MmIsRetryIoStatus(Pfn2->u1.ReadStatus)) {
02443
return STATUS_REFAULT;
02444 }
02445
return Pfn2->u1.ReadStatus;
02446 }
02447
02448
if (InPageSupport->Completed ==
FALSE) {
02449
02450
#if defined(_PREFETCH_)
02451
02452
02453
02454
02455
02456
02457
02458
ASSERT ((Pfn->
u3.e1.ReadInProgress == 1) ||
02459 (Pfn->
PteAddress == MI_PF_DUMMY_PAGE_PTE));
02460
#else
02461
ASSERT (Pfn->
u3.e1.ReadInProgress == 1);
02462
#endif
02463
02464 InPageSupport->Completed =
TRUE;
02465
02466 Mdl = &InPageSupport->Mdl;
02467
02468
#if defined(_PREFETCH_)
02469
02470
if (InPageSupport->PrefetchMdl !=
NULL) {
02471
02472
02473
02474
02475
02476 Mdl = InPageSupport->PrefetchMdl;
02477 }
02478
02479
#endif
02480
02481
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
02482
#if DBG
02483
Mdl->
MdlFlags |=
MDL_LOCK_HELD;
02484
#endif //DBG
02485
02486
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
02487
02488
#if DBG
02489
Mdl->
MdlFlags &= ~
MDL_LOCK_HELD;
02490
#endif //DBG
02491
}
02492
02493
ASSERT (Pfn->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
02494
02495 Pfn->
u3.e1.ReadInProgress = 0;
02496 Pfn->
u1.Event = (
PKEVENT)
NULL;
02497
02498
#if defined (_WIN64)
02499
02500
02501
02502
02503
02504
02505
if (InPageSupport->UsedPageTableEntries) {
02506 Page = (PPFN_NUMBER)(Mdl + 1);
02507 LastPage = Page + ((Mdl->
ByteCount - 1) >>
PAGE_SHIFT);
02508
ASSERT (Page == LastPage);
02509 }
02510
02511
#if DBGXX
02512
MiCheckPageTableInPage (Pfn, InPageSupport);
02513
#endif
02514
#endif
02515
02516
MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN(Pfn, InPageSupport);
02517
02518
02519
02520
02521
02522
if (!
NT_SUCCESS(InPageSupport->IoStatus.Status)) {
02523
02524
if (InPageSupport->IoStatus.Status == STATUS_END_OF_FILE) {
02525
02526
02527
02528
02529
02530
02531 Page = (PPFN_NUMBER)(Mdl + 1);
02532 LastPage = Page + ((Mdl->
ByteCount - 1) >>
PAGE_SHIFT);
02533
02534
while (Page <= LastPage) {
02535
MiZeroPhysicalPage (*Page, 0);
02536
02537
MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN(
MI_PFN_ELEMENT(*Page));
02538
02539 Page += 1;
02540 }
02541
02542 }
else {
02543
02544
02545
02546
02547
02548 status = InPageSupport->IoStatus.Status;
02549 status2 = InPageSupport->IoStatus.Status;
02550
02551
if (status != STATUS_VERIFY_REQUIRED) {
02552
02553 LOGICAL Retry;
02554
02555 Retry =
FALSE;
02556
#if DBG
02557
DbgPrint (
"MM: inpage I/O error %X\n",
02558 InPageSupport->IoStatus.Status);
02559
#endif
02560
02561
02562
02563
02564
02565
02566
if ((FaultingAddress > MM_HIGHEST_USER_ADDRESS) &&
02567 (!
MI_IS_SYSTEM_CACHE_ADDRESS(FaultingAddress))) {
02568
02569
if (
MmIsRetryIoStatus(status)) {
02570
02571
MiFaultRetries -= 1;
02572
if (
MiFaultRetries != 0) {
02573 Retry =
TRUE;
02574 }
else {
02575
MiFaultRetries =
MiIoRetryLevel;
02576 }
02577 }
02578
02579
if (Retry ==
FALSE) {
02580
02581 ULONG_PTR PteContents;
02582
02583
02584
02585
02586
02587
02588
if (
MmIsAddressValid (PointerPte) ==
TRUE) {
02589 PteContents = *(PULONG_PTR)PointerPte;
02590 }
02591
else {
02592 PteContents = (ULONG_PTR)-1;
02593 }
02594
02595
KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR,
02596 (ULONG_PTR)PointerPte,
02597 status,
02598 (ULONG_PTR)FaultingAddress,
02599 PteContents);
02600 }
02601 status2 =
STATUS_REFAULT;
02602 }
02603
else {
02604
02605
if (
MmIsRetryIoStatus(status)) {
02606
02607
MiUserFaultRetries -= 1;
02608
if (
MiUserFaultRetries != 0) {
02609 Retry =
TRUE;
02610 }
else {
02611
MiUserFaultRetries =
MiUserIoRetryLevel;
02612 }
02613 }
02614
02615
if (Retry ==
TRUE) {
02616 status2 =
STATUS_REFAULT;
02617 }
02618 }
02619 }
02620
02621 Page = (PPFN_NUMBER)(Mdl + 1);
02622 LastPage = Page + ((Mdl->
ByteCount - 1) >>
PAGE_SHIFT);
02623
02624
while (Page <= LastPage) {
02625 Pfn1 =
MI_PFN_ELEMENT (*Page);
02626
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
02627 Pfn1->
u3.e1.InPageError = 1;
02628 Pfn1->
u1.ReadStatus = status;
02629
02630
#if DBG
02631
{
02632 KIRQL Old;
02633 Va = (PULONG)
MiMapPageInHyperSpace (*Page,&Old);
02634 RtlFillMemoryUlong (Va,
PAGE_SIZE, 0x50444142);
02635
MiUnmapPageInHyperSpace (Old);
02636 }
02637
#endif //DBG
02638
Page += 1;
02639 }
02640
02641
MiFreeInPageSupportBlock (InPageSupport);
02642
return status2;
02643 }
02644 }
else {
02645
02646
MiFaultRetries =
MiIoRetryLevel;
02647
MiUserFaultRetries =
MiUserIoRetryLevel;
02648
02649
if (InPageSupport->IoStatus.Information != Mdl->
ByteCount) {
02650
02651
ASSERT (InPageSupport->IoStatus.Information != 0);
02652
02653
02654
02655
02656
02657
02658 Page = (PPFN_NUMBER)(Mdl + 1);
02659 LastPage = Page + ((Mdl->
ByteCount - 1) >>
PAGE_SHIFT);
02660 Page += ((InPageSupport->IoStatus.Information - 1) >>
PAGE_SHIFT);
02661
02662
Offset =
BYTE_OFFSET (InPageSupport->IoStatus.Information);
02663
02664
if (
Offset != 0) {
02665 KIRQL Old;
02666 Va = (PULONG)((PCHAR)
MiMapPageInHyperSpace (*Page, &Old)
02667 +
Offset);
02668
02669 RtlZeroMemory (Va,
PAGE_SIZE -
Offset);
02670
MiUnmapPageInHyperSpace (Old);
02671 }
02672
02673
02674
02675
02676
02677 Page += 1;
02678
02679
while (Page <= LastPage) {
02680
MiZeroPhysicalPage (*Page, 0);
02681 Page += 1;
02682 }
02683 }
02684 }
02685 }
02686
02687
MiFreeInPageSupportBlock (InPageSupport);
02688
02689
02690
02691
02692
02693 NewPointerPte =
MiFindActualFaultingPte (FaultingAddress);
02694
02695
02696
02697
02698
02699
02700
if (NewPointerPte == (
PMMPTE)
NULL) {
02701
return STATUS_PTE_CHANGED;
02702 }
02703
02704
if (NewPointerPte != PointerPte) {
02705
02706
02707
02708
02709
02710
02711
if (NewPointerPte->
u.Soft.Prototype == 1) {
02712
if (NewPointerPte->
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED) {
02713
02714 ProtoPte =
MiCheckVirtualAddress (FaultingAddress,
02715 &Protection);
02716
02717 }
else {
02718 ProtoPte =
MiPteToProto (NewPointerPte);
02719 }
02720
02721
02722
02723
02724
02725
if (ProtoPte != PointerPte) {
02726
return STATUS_PTE_CHANGED;
02727 }
02728
02729
02730
02731
02732
02733
if (ProtoPte->
u.Long != PointerPteContents->u.Long) {
02734
return STATUS_PTE_CHANGED;
02735 }
02736 }
else {
02737
return STATUS_PTE_CHANGED;
02738 }
02739 }
else {
02740
02741
if (NewPointerPte->
u.Long != PointerPteContents->u.Long) {
02742
return STATUS_PTE_CHANGED;
02743 }
02744 }
02745
return STATUS_SUCCESS;
02746 }
02747
02748
PMMPTE
02749 MiFindActualFaultingPte (
02750 IN PVOID FaultingAddress
02751 )
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779 {
02780
PMMPTE ProtoPteAddress;
02781
PMMPTE PointerPte;
02782
PMMPTE PointerFaultingPte;
02783 ULONG Protection;
02784
02785
if (
MI_IS_PHYSICAL_ADDRESS(FaultingAddress)) {
02786
return NULL;
02787 }
02788
02789
#if defined (_WIN64)
02790
02791 PointerPte =
MiGetPpeAddress (FaultingAddress);
02792
02793
if (PointerPte->
u.Hard.Valid == 0) {
02794
02795
02796
02797
02798
02799
return PointerPte;
02800 }
02801
02802
#endif
02803
02804 PointerPte =
MiGetPdeAddress (FaultingAddress);
02805
02806
if (PointerPte->
u.Hard.Valid == 0) {
02807
02808
02809
02810
02811
02812
return PointerPte;
02813 }
02814
02815 PointerPte =
MiGetPteAddress (FaultingAddress);
02816
02817
if (PointerPte->
u.Hard.Valid == 1) {
02818
02819
02820
02821
02822
02823
return (
PMMPTE)
NULL;
02824 }
02825
02826
if (PointerPte->
u.Soft.Prototype == 0) {
02827
02828
02829
02830
02831
02832
return PointerPte;
02833 }
02834
02835
02836
02837
02838
02839
if (PointerPte->
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED) {
02840
02841
02842
02843
02844
02845 ProtoPteAddress =
MiCheckVirtualAddress (FaultingAddress,
02846 &Protection);
02847
02848
if (ProtoPteAddress ==
NULL) {
02849
02850
02851
02852
02853
02854
02855
02856
02857
return (
PMMPTE)
NULL;
02858 }
02859
02860 }
else {
02861
02862
02863
02864
02865
02866 ProtoPteAddress =
MiPteToProto (PointerPte);
02867 }
02868
02869 PointerFaultingPte =
MiFindActualFaultingPte (ProtoPteAddress);
02870
02871
if (PointerFaultingPte == (
PMMPTE)
NULL) {
02872
return PointerPte;
02873 }
else {
02874
return PointerFaultingPte;
02875 }
02876
02877 }
02878
02879
PMMPTE
02880 MiCheckVirtualAddress (
02881 IN PVOID VirtualAddress,
02882 OUT PULONG ProtectCode
02883 )
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912 {
02913
PMMVAD Vad;
02914
PMMPTE PointerPte;
02915 PLIST_ENTRY NextEntry;
02916
PIMAGE_ENTRY_IN_SESSION Image;
02917
02918
if (VirtualAddress <= MM_HIGHEST_USER_ADDRESS) {
02919
02920
#if defined(MM_SHARED_USER_DATA_VA)
02921
02922
if (
PAGE_ALIGN(VirtualAddress) == (PVOID) MM_SHARED_USER_DATA_VA) {
02923
02924
02925
02926
02927
02928
02929
02930 *ProtectCode =
MM_READONLY;
02931
return &
MmSharedUserDataPte;
02932 }
02933
02934
#endif
02935
02936 Vad =
MiLocateAddress (VirtualAddress);
02937
if (Vad == (
PMMVAD)
NULL) {
02938
02939 *ProtectCode =
MM_NOACCESS;
02940
return NULL;
02941 }
02942
02943
02944
02945
02946
02947
02948
02949
#ifdef LARGE_PAGES
02950
02951
if (Vad->
u.VadFlags.LargePages == 1) {
02952
02953 KIRQL OldIrql;
02954
PSUBSECTION Subsection;
02955
02956
02957
02958
02959
02960 Subsection = (
PSUBSECTION)Vad->
FirstPrototypePte;
02961
02962
ASSERT (Subsection->
u.SubsectionFlags.LargePages == 1);
02963
02964
KeRaiseIrql (
DISPATCH_LEVEL, &OldIrql);
02965
KeFlushEntireTb (
TRUE,
TRUE);
02966 KeFillLargeEntryTb ((PHARDWARE_PTE)(Subsection + 1),
02967 VirtualAddress,
02968 Subsection->StartingSector);
02969
02970
KeLowerIrql (OldIrql);
02971 *ProtectCode =
MM_LARGE_PAGES;
02972
return NULL;
02973 }
02974
#endif //LARGE_PAGES
02975
02976
if (Vad->
u.VadFlags.PhysicalMapping == 1) {
02977
02978
02979
02980
02981
02982
MiHandleBankedSection (VirtualAddress, Vad);
02983 *ProtectCode =
MM_NOACCESS;
02984
return NULL;
02985 }
02986
02987
if (Vad->
u.VadFlags.PrivateMemory == 1) {
02988
02989
02990
02991
02992
02993
02994
02995
if (Vad->
u.VadFlags.UserPhysicalPages == 1) {
02996
02997
02998
02999
03000
03001
ASSERT (
MiGetPteAddress(VirtualAddress)->u.Long ==
ZeroPte.
u.Long);
03002 *ProtectCode =
MM_NOACCESS;
03003
return NULL;
03004 }
03005
03006
if (Vad->
u.VadFlags.MemCommit == 1) {
03007 *ProtectCode =
MI_GET_PROTECTION_FROM_VAD(Vad);
03008
return NULL;
03009 }
03010
03011
03012
03013
03014
03015 *ProtectCode =
MM_NOACCESS;
03016
return NULL;
03017
03018 }
else {
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
if (Vad->
u.VadFlags.ImageMap == 1) {
03037
03038
03039
03040
03041
03042 *ProtectCode =
MM_UNKNOWN_PROTECTION;
03043 }
else {
03044 *ProtectCode =
MI_GET_PROTECTION_FROM_VAD(Vad);
03045 }
03046 PointerPte = (
PMMPTE)
MiGetProtoPteAddress(Vad,
03047
MI_VA_TO_VPN (VirtualAddress));
03048
if (PointerPte ==
NULL) {
03049 *ProtectCode =
MM_NOACCESS;
03050 }
03051
if (Vad->
u2.VadFlags2.ExtendableFile) {
03052
03053
03054
03055
03056
03057
if ((
MI_VA_TO_VPN (VirtualAddress) - Vad->
StartingVpn) >
03058 (ULONG_PTR)((Vad->
u4.ExtendedInfo->CommittedSize - 1)
03059 >>
PAGE_SHIFT)) {
03060 *ProtectCode =
MM_NOACCESS;
03061 }
03062 }
03063
return PointerPte;
03064 }
03065
03066 }
else if (
MI_IS_PAGE_TABLE_ADDRESS(VirtualAddress)) {
03067
03068
03069
03070
03071
03072
03073
if (((
PMMPTE)VirtualAddress >=
MiGetPteAddress (
MM_PAGED_POOL_START)) &&
03074 ((
PMMPTE)VirtualAddress <=
MmPagedPoolInfo.LastPteForPagedPool)) {
03075
03076 *ProtectCode =
MM_NOACCESS;
03077
return NULL;
03078 }
03079
03080 *ProtectCode =
MM_READWRITE;
03081
return NULL;
03082 }
03083
else if (
MI_IS_SESSION_ADDRESS (VirtualAddress) ==
TRUE) {
03084
03085
03086
03087
03088
03089
MM_SESSION_SPACE_WS_LOCK_ASSERT ();
03090
03091 PointerPte =
NULL;
03092 *ProtectCode =
MM_NOACCESS;
03093
03094 NextEntry =
MmSessionSpace->
ImageList.Flink;
03095
03096
while (NextEntry != &
MmSessionSpace->
ImageList) {
03097
03098 Image = CONTAINING_RECORD(NextEntry,
IMAGE_ENTRY_IN_SESSION, Link);
03099
03100
if ((VirtualAddress >= Image->
Address) && (VirtualAddress <= Image->
LastAddress)) {
03101 PointerPte = Image->
PrototypePtes +
03102 (((PCHAR)VirtualAddress - (PCHAR)Image->
Address) >>
PAGE_SHIFT);
03103 *ProtectCode =
MM_EXECUTE_WRITECOPY;
03104
break;
03105 }
03106
03107 NextEntry = NextEntry->Flink;
03108 }
03109
03110
return PointerPte;
03111 }
03112
03113
03114
03115
03116
03117 *ProtectCode =
MM_NOACCESS;
03118
return NULL;
03119 }
03120
03121
#if !defined (_WIN64)
03122
03123
NTSTATUS
03124
FASTCALL
03125 MiCheckPdeForPagedPool (
03126 IN PVOID VirtualAddress
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
PMMPTE PointerPde;
03154
PMMPTE PointerPte;
03155
NTSTATUS status;
03156
03157
if (
MiHydra ==
TRUE) {
03158
03159
if (
MI_IS_SESSION_ADDRESS (VirtualAddress) ==
TRUE) {
03160
03161
03162
03163
03164
03165
return MiCheckPdeForSessionSpace (VirtualAddress);
03166 }
03167
03168
if (
MI_IS_SESSION_PTE (VirtualAddress) ==
TRUE) {
03169
03170
03171
03172
03173
03174
return MiCheckPdeForSessionSpace (VirtualAddress);
03175 }
03176 }
03177
03178 status = STATUS_SUCCESS;
03179
03180
if (
MI_IS_KERNEL_PAGE_TABLE_ADDRESS(VirtualAddress)) {
03181
03182
03183
03184
03185
03186 PointerPde =
MiGetPteAddress (VirtualAddress);
03187 status = STATUS_WAIT_1;
03188 }
else if (VirtualAddress <
MmSystemRangeStart) {
03189
03190
return STATUS_ACCESS_VIOLATION;
03191
03192 }
else {
03193
03194
03195
03196
03197
03198 PointerPde =
MiGetPdeAddress (VirtualAddress);
03199 }
03200
03201
03202
03203
03204
03205
if (PointerPde->
u.Hard.Valid == 0) {
03206 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
03207
#if !defined (_X86PAE_)
03208
MI_WRITE_VALID_PTE (PointerPde,
03209
MmSystemPagePtes [((ULONG_PTR)PointerPde &
03210 ((
sizeof(
MMPTE) *
PDE_PER_PAGE) - 1)) /
sizeof(
MMPTE)]);
03211
#else
03212
MI_WRITE_VALID_PTE (PointerPde,
03213
MmSystemPagePtes [((ULONG_PTR)PointerPde &
03214 (PD_PER_SYSTEM * (
sizeof(
MMPTE) *
PDE_PER_PAGE) - 1)) /
sizeof(
MMPTE)]);
03215
#endif
03216
KeFillEntryTb ((PHARDWARE_PTE)PointerPde, PointerPte,
FALSE);
03217 }
03218
return status;
03219 }
03220
03221
03222
NTSTATUS
03223
FASTCALL
03224 MiCheckPdeForSessionSpace(
03225 IN PVOID VirtualAddress
03226 )
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256 {
03257
PMMPTE PointerPde;
03258 PVOID SessionVirtualAddress;
03259 ULONG
Index;
03260
03261
03262
03263
03264
03265
ASSERT (
MiHydra ==
TRUE);
03266
03267
03268
03269
03270
03271
03272
03273
if (
MI_IS_SESSION_PTE (VirtualAddress) ==
TRUE) {
03274
03275
03276
03277
03278
03279 PointerPde =
MiGetPdeAddress (
MmSessionSpace);
03280
03281
if (PointerPde->
u.Hard.Valid == 0) {
03282
03283
#if DBG
03284
DbgPrint(
"MiCheckPdeForSessionSpace: No current session for PTE %p\n",
03285 VirtualAddress);
03286
03287 DbgBreakPoint();
03288
#endif
03289
return STATUS_ACCESS_VIOLATION;
03290 }
03291
03292 SessionVirtualAddress =
MiGetVirtualAddressMappedByPte ((
PMMPTE) VirtualAddress);
03293
03294 PointerPde =
MiGetPteAddress (VirtualAddress);
03295
03296
if (PointerPde->
u.Hard.Valid == 1) {
03297
03298
03299
03300
03301
03302
03303
return STATUS_WAIT_1;
03304 }
03305
03306
03307
03308
03309
03310
03311
Index =
MiGetPdeSessionIndex (SessionVirtualAddress);
03312
03313 PointerPde->
u.Long =
MmSessionSpace->
PageTables[
Index].
u.Long;
03314
03315
if (PointerPde->
u.Hard.Valid == 1) {
03316 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, VirtualAddress,
FALSE);
03317
return STATUS_WAIT_1;
03318 }
03319
03320
#if DBG
03321
DbgPrint(
"MiCheckPdeForSessionSpace: No Session PDE for PTE %p, %p\n",
03322 PointerPde->
u.Long, SessionVirtualAddress);
03323
03324 DbgBreakPoint();
03325
#endif
03326
return STATUS_ACCESS_VIOLATION;
03327 }
03328
03329
if (
MI_IS_SESSION_ADDRESS (VirtualAddress) ==
FALSE) {
03330
03331
03332
03333
03334
03335
return STATUS_SUCCESS;
03336 }
03337
03338
03339
03340
03341
03342
03343 PointerPde =
MiGetPdeAddress (
MmSessionSpace);
03344
03345
if (PointerPde->
u.Hard.Valid == 0) {
03346
03347
#if DBG
03348
DbgPrint(
"MiCheckPdeForSessionSpace: No current session for VA %p\n",
03349 VirtualAddress);
03350
03351 DbgBreakPoint();
03352
#endif
03353
return STATUS_ACCESS_VIOLATION;
03354 }
03355
03356 PointerPde =
MiGetPdeAddress (VirtualAddress);
03357
03358
if (PointerPde->
u.Hard.Valid == 0) {
03359
03360
03361
03362
03363
03364
03365
Index =
MiGetPdeSessionIndex (VirtualAddress);
03366
03367 PointerPde->
u.Long =
MmSessionSpace->
PageTables[
Index].
u.Long;
03368
03369
if (PointerPde->
u.Hard.Valid == 1) {
03370
03371 KeFillEntryTb ((PHARDWARE_PTE)PointerPde,
03372
MiGetPteAddress(VirtualAddress),
03373
FALSE);
03374
03375
return STATUS_WAIT_1;
03376 }
03377
03378
#if DBG
03379
DbgPrint(
"MiCheckPdeForSessionSpace: No Session PDE for VA %p, %p\n",
03380 PointerPde->
u.Long, VirtualAddress);
03381
03382 DbgBreakPoint();
03383
#endif
03384
03385
return STATUS_ACCESS_VIOLATION;
03386 }
03387
03388
03389
03390
03391
03392
return STATUS_SUCCESS;
03393 }
03394
#endif
03395
03396
03397
VOID
03398 MiInitializePfn (
03399 IN PFN_NUMBER PageFrameIndex,
03400 IN
PMMPTE PointerPte,
03401 IN ULONG ModifiedState
03402 )
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431 {
03432
PMMPFN Pfn1;
03433
PMMPFN Pfn2;
03434
PMMPTE PteFramePointer;
03435 PFN_NUMBER PteFramePage;
03436
03437
MM_PFN_LOCK_ASSERT();
03438
03439 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03440 Pfn1->
PteAddress = PointerPte;
03441
03442
03443
03444
03445
03446
03447
if (PointerPte->u.Hard.Valid == 1) {
03448 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
03449
03450
#if defined(_IA64_)
03451
if (PointerPte->u.Hard.Execute == 1) {
03452 Pfn1->
OriginalPte.
u.Soft.Protection =
MM_EXECUTE_READWRITE;
03453 }
03454
#endif
03455
03456
if (
MI_IS_CACHING_DISABLED (PointerPte)) {
03457 Pfn1->
OriginalPte.
u.Soft.Protection =
MM_READWRITE |
MM_NOCACHE;
03458 }
03459
03460 }
else {
03461 Pfn1->
OriginalPte = *PointerPte;
03462
ASSERT (!((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
03463 (Pfn1->
OriginalPte.
u.Soft.Transition == 1)));
03464 }
03465
03466 Pfn1->
u3.e2.ReferenceCount += 1;
03467
03468
#if DBG
03469
if (Pfn1->
u3.e2.ReferenceCount > 1) {
03470
DbgPrint(
"MM:incrementing ref count > 1 \n");
03471
MiFormatPfn(Pfn1);
03472
MiFormatPte(PointerPte);
03473 }
03474
#endif
03475
03476 Pfn1->
u2.ShareCount += 1;
03477 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
03478 Pfn1->
u3.e1.Modified = ModifiedState;
03479
03480
#if defined (_WIN64)
03481
Pfn1->UsedPageTableEntries = 0;
03482
#endif
03483
03484
#if PFN_CONSISTENCY
03485
Pfn1->
u3.e1.PageTablePage = 0;
03486
#endif
03487
03488
03489
03490
03491
03492 PteFramePointer =
MiGetPteAddress(PointerPte);
03493
if (PteFramePointer->
u.Hard.Valid == 0) {
03494
#if !defined (_WIN64)
03495
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (PointerPte))) {
03496
#endif
03497
KeBugCheckEx (MEMORY_MANAGEMENT,
03498 0x61940,
03499 (ULONG_PTR)PointerPte,
03500 (ULONG_PTR)PteFramePointer->
u.Long,
03501 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte));
03502
#if !defined (_WIN64)
03503
}
03504
#endif
03505
}
03506 PteFramePage =
MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer);
03507
ASSERT (PteFramePage != 0);
03508 Pfn1->
PteFrame = PteFramePage;
03509
03510
03511
03512
03513
03514
03515 Pfn2 =
MI_PFN_ELEMENT (PteFramePage);
03516
03517 Pfn2->
u2.ShareCount += 1;
03518
03519
return;
03520 }
03521
03522
VOID
03523 MiInitializeReadInProgressPfn (
03524 IN
PMDL Mdl,
03525 IN
PMMPTE BasePte,
03526 IN
PKEVENT Event,
03527 IN WSLE_NUMBER WorkingSetIndex
03528 )
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562 {
03563
PMMPFN Pfn1;
03564
PMMPFN Pfn2;
03565
PMMPTE PteFramePointer;
03566 PFN_NUMBER PteFramePage;
03567
MMPTE TempPte;
03568 LONG NumberOfBytes;
03569 PPFN_NUMBER Page;
03570
03571
MM_PFN_LOCK_ASSERT();
03572
03573 Page = (PPFN_NUMBER)(Mdl + 1);
03574
03575 NumberOfBytes = Mdl->ByteCount;
03576
03577
while (NumberOfBytes > 0) {
03578
03579 Pfn1 =
MI_PFN_ELEMENT (*Page);
03580 Pfn1->
u1.Event =
Event;
03581 Pfn1->
PteAddress = BasePte;
03582 Pfn1->
OriginalPte = *BasePte;
03583
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
03584
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 10);
03585 Pfn1->
u3.e2.ReferenceCount += 1;
03586
03587 Pfn1->
u2.ShareCount = 0;
03588 Pfn1->
u3.e1.ReadInProgress = 1;
03589 Pfn1->
u3.e1.InPageError = 0;
03590
03591
#if PFN_CONSISTENCY
03592
Pfn1->
u3.e1.PageTablePage = 0;
03593
#endif
03594
if (WorkingSetIndex ==
MI_PROTOTYPE_WSINDEX) {
03595 Pfn1->
u3.e1.PrototypePte = 1;
03596 }
03597
03598
03599
03600
03601
03602
03603 PteFramePointer =
MiGetPteAddress(BasePte);
03604
if (PteFramePointer->
u.Hard.Valid == 0) {
03605
#if !defined (_WIN64)
03606
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (BasePte))) {
03607
#endif
03608
KeBugCheckEx (MEMORY_MANAGEMENT,
03609 0x61940,
03610 (ULONG_PTR)BasePte,
03611 (ULONG_PTR)PteFramePointer->
u.Long,
03612 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(BasePte));
03613
#if !defined (_WIN64)
03614
}
03615
#endif
03616
}
03617
03618 PteFramePage =
MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer);
03619 Pfn1->
PteFrame = PteFramePage;
03620
03621
03622
03623
03624
03625
03626
MI_MAKE_TRANSITION_PTE (TempPte,
03627 *Page,
03628 BasePte->
u.Soft.Protection,
03629 BasePte);
03630
MI_WRITE_INVALID_PTE (BasePte, TempPte);
03631
03632
03633
03634
03635
03636
03637
ASSERT (PteFramePage != 0);
03638 Pfn2 =
MI_PFN_ELEMENT (PteFramePage);
03639 Pfn2->
u2.ShareCount += 1;
03640
03641 NumberOfBytes -=
PAGE_SIZE;
03642 Page += 1;
03643 BasePte += 1;
03644 }
03645
03646
return;
03647 }
03648
03649
VOID
03650 MiInitializeTransitionPfn (
03651 IN PFN_NUMBER PageFrameIndex,
03652 IN
PMMPTE PointerPte,
03653 IN WSLE_NUMBER WorkingSetIndex
03654 )
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685 {
03686
PMMPFN Pfn1;
03687
PMMPFN Pfn2;
03688
PMMPTE PteFramePointer;
03689 PFN_NUMBER PteFramePage;
03690
MMPTE TempPte;
03691
03692
MM_PFN_LOCK_ASSERT();
03693 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03694 Pfn1->
u1.Event =
NULL;
03695 Pfn1->
PteAddress = PointerPte;
03696 Pfn1->
OriginalPte = *PointerPte;
03697
ASSERT (!((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
03698 (Pfn1->
OriginalPte.
u.Soft.Transition == 1)));
03699
03700
03701
03702
03703
03704 Pfn1->
u2.ShareCount = 0;
03705
03706
if (WorkingSetIndex ==
MI_PROTOTYPE_WSINDEX) {
03707 Pfn1->
u3.e1.PrototypePte = 1;
03708 }
03709
03710 Pfn1->
u3.e1.PageLocation =
TransitionPage;
03711
03712
03713
03714
03715
03716
03717 PteFramePointer =
MiGetPteAddress(PointerPte);
03718
if (PteFramePointer->
u.Hard.Valid == 0) {
03719
#if !defined (_WIN64)
03720
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (PointerPte))) {
03721
#endif
03722
KeBugCheckEx (MEMORY_MANAGEMENT,
03723 0x61940,
03724 (ULONG_PTR)PointerPte,
03725 (ULONG_PTR)PteFramePointer->
u.Long,
03726 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte));
03727
#if !defined (_WIN64)
03728
}
03729
#endif
03730
}
03731
03732 PteFramePage =
MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer);
03733 Pfn1->
PteFrame = PteFramePage;
03734
03735
#if PFN_CONSISTENCY
03736
Pfn1->
u3.e1.PageTablePage = 0;
03737
#endif
03738
03739
03740
03741
03742
03743
03744
MI_MAKE_TRANSITION_PTE (TempPte,
03745 PageFrameIndex,
03746 PointerPte->
u.Soft.Protection,
03747 PointerPte);
03748
03749
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
03750
03751
03752
03753
03754
03755
03756 Pfn2 =
MI_PFN_ELEMENT (PteFramePage);
03757
ASSERT (PteFramePage != 0);
03758 Pfn2->
u2.ShareCount += 1;
03759
03760
return;
03761 }
03762
03763
VOID
03764 MiInitializeCopyOnWritePfn (
03765 IN PFN_NUMBER PageFrameIndex,
03766 IN
PMMPTE PointerPte,
03767 IN WSLE_NUMBER WorkingSetIndex,
03768 IN PVOID SessionPointer
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
03803
03804
03805 {
03806
PMMPFN Pfn1;
03807
PMMPTE PteFramePointer;
03808 PFN_NUMBER PteFramePage;
03809 PVOID VirtualAddress;
03810
PMM_SESSION_SPACE SessionSpace;
03811
03812 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03813 Pfn1->
PteAddress = PointerPte;
03814
03815
03816
03817
03818
03819 VirtualAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
03820
03821 Pfn1->
OriginalPte.
u.Long = 0;
03822
03823
if (SessionPointer) {
03824 Pfn1->
OriginalPte.
u.Soft.Protection =
MM_EXECUTE_READWRITE;
03825 SessionSpace = (
PMM_SESSION_SPACE) SessionPointer;
03826 SessionSpace->
Wsle[WorkingSetIndex].
u1.e1.Protection =
03827
MM_EXECUTE_READWRITE;
03828 }
03829
else {
03830 Pfn1->
OriginalPte.
u.Soft.Protection =
03831
MI_MAKE_PROTECT_NOT_WRITE_COPY (
03832
MmWsle[WorkingSetIndex].u1.
e1.
Protection);
03833 }
03834
03835
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
03836 Pfn1->
u3.e2.ReferenceCount += 1;
03837 Pfn1->
u2.ShareCount += 1;
03838 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
03839 Pfn1->
u1.WsIndex = WorkingSetIndex;
03840
03841
03842
03843
03844
03845
03846 PteFramePointer =
MiGetPteAddress(PointerPte);
03847
if (PteFramePointer->
u.Hard.Valid == 0) {
03848
#if !defined (_WIN64)
03849
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (PointerPte))) {
03850
#endif
03851
KeBugCheckEx (MEMORY_MANAGEMENT,
03852 0x61940,
03853 (ULONG_PTR)PointerPte,
03854 (ULONG_PTR)PteFramePointer->
u.Long,
03855 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte));
03856
#if !defined (_WIN64)
03857
}
03858
#endif
03859
}
03860
03861 PteFramePage =
MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer);
03862
ASSERT (PteFramePage != 0);
03863
03864 Pfn1->
PteFrame = PteFramePage;
03865
03866
#if PFN_CONSISTENCY
03867
MM_PFN_LOCK_ASSERT();
03868
03869 Pfn1->
u3.e1.PageTablePage = 0;
03870
#endif
03871
03872
03873
03874
03875
03876
03877 Pfn1->
u3.e1.Modified = 1;
03878
03879
return;
03880 }
03881
03882 BOOLEAN
03883 MmIsAddressValid (
03884 IN PVOID VirtualAddress
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
PMMPTE PointerPte;
03914
03915
#if defined(_ALPHA_) || defined(_IA64_)
03916
03917
03918
03919
03920
03921
if (
MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) {
03922
return TRUE;
03923 }
03924
03925
#endif // _ALPHA_ || _IA64_
03926
03927
#if defined (_WIN64)
03928
PointerPte =
MiGetPpeAddress (VirtualAddress);
03929
if (PointerPte->
u.Hard.Valid == 0) {
03930
return FALSE;
03931 }
03932
#endif
03933
03934 PointerPte =
MiGetPdeAddress (VirtualAddress);
03935
if (PointerPte->
u.Hard.Valid == 0) {
03936
return FALSE;
03937 }
03938
#ifdef _X86_
03939
if (PointerPte->
u.Hard.LargePage == 1) {
03940
return TRUE;
03941 }
03942
#endif //_X86_
03943
03944 PointerPte =
MiGetPteAddress (VirtualAddress);
03945
if (PointerPte->
u.Hard.Valid == 0) {
03946
return FALSE;
03947 }
03948
03949
#ifdef _X86_
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
if (PointerPte->
u.Hard.LargePage == 1) {
03960 PVOID Va;
03961
03962 Va =
MiGetVirtualAddressMappedByPde (PointerPte);
03963
if (
MI_IS_PHYSICAL_ADDRESS(Va)) {
03964
return FALSE;
03965 }
03966 }
03967
#endif
03968
03969
return TRUE;
03970 }
03971
03972
VOID
03973 MiInitializePfnForOtherProcess (
03974 IN PFN_NUMBER PageFrameIndex,
03975 IN
PMMPTE PointerPte,
03976 IN PFN_NUMBER ContainingPageFrame
03977 )
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014 {
04015
PMMPFN Pfn1;
04016
PMMPFN Pfn2;
04017
04018 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
04019 Pfn1->
PteAddress = PointerPte;
04020 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
04021
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
04022 Pfn1->
u3.e2.ReferenceCount += 1;
04023
04024
#if DBG
04025
if (Pfn1->
u3.e2.ReferenceCount > 1) {
04026
DbgPrint(
"MM:incrementing ref count > 1 \n");
04027
MiFormatPfn(Pfn1);
04028
MiFormatPte(PointerPte);
04029 }
04030
#endif
04031
04032 Pfn1->
u2.ShareCount += 1;
04033 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
04034 Pfn1->
u3.e1.Modified = 1;
04035
04036
#if PFN_CONSISTENCY
04037
MM_PFN_LOCK_ASSERT();
04038
04039 Pfn1->
u3.e1.PageTablePage = 0;
04040
#endif
04041
04042
04043
04044
04045
04046
04047
if (ContainingPageFrame != 0) {
04048 Pfn1->
PteFrame = ContainingPageFrame;
04049 Pfn2 =
MI_PFN_ELEMENT (ContainingPageFrame);
04050 Pfn2->
u2.ShareCount += 1;
04051 }
04052
return;
04053 }
04054
04055
VOID
04056 MiAddValidPageToWorkingSet (
04057 IN PVOID VirtualAddress,
04058 IN
PMMPTE PointerPte,
04059 IN
PMMPFN Pfn1,
04060 IN ULONG WsleMask
04061 )
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092 {
04093
WSLE_NUMBER WorkingSetIndex;
04094
PEPROCESS Process;
04095
PMMSUPPORT WsInfo;
04096
PMMWSLE Wsle;
04097
04098
ASSERT (
MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
04099
ASSERT (PointerPte->u.Hard.Valid == 1);
04100
04101
if (
MI_IS_SESSION_ADDRESS (VirtualAddress) ||
MI_IS_SESSION_PTE (VirtualAddress)) {
04102
04103
04104
04105
04106 WsInfo = &
MmSessionSpace->
Vm;
04107 Wsle =
MmSessionSpace->
Wsle;
04108 }
04109
else if (
MI_IS_PROCESS_SPACE_ADDRESS(VirtualAddress)) {
04110
04111
04112
04113
04114
04115 Process =
PsGetCurrentProcess();
04116 WsInfo = &Process->
Vm;
04117 Wsle =
MmWsle;
04118
04119
PERFINFO_ADDTOWS(Pfn1, VirtualAddress, Process->
UniqueProcessId)
04120 }
else {
04121
04122
04123
04124
04125
04126 WsInfo = &
MmSystemCacheWs;
04127 Wsle =
MmSystemCacheWsle;
04128
04129
PERFINFO_ADDTOWS(Pfn1, VirtualAddress, (HANDLE) -1);
04130 }
04131
04132 WorkingSetIndex =
MiLocateAndReserveWsle (WsInfo);
04133
MiUpdateWsle (&WorkingSetIndex,
04134 VirtualAddress,
04135 WsInfo->
VmWorkingSetList,
04136 Pfn1);
04137 Wsle[WorkingSetIndex].
u1.Long |= WsleMask;
04138
04139
#if DBG
04140
if (
MI_IS_SYSTEM_CACHE_ADDRESS(VirtualAddress)) {
04141
ASSERT (
MmSystemCacheWsle[WorkingSetIndex].u1.
e1.
SameProtectAsProto);
04142 }
04143
#endif //DBG
04144
04145
MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex);
04146
04147 KeFillEntryTb ((PHARDWARE_PTE)PointerPte, VirtualAddress,
FALSE);
04148
return;
04149 }
04150
04151
PMMINPAGE_SUPPORT
04152 MiGetInPageSupportBlock (
04153 VOID
04154 )
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184 {
04185 KIRQL OldIrql;
04186
PMMINPAGE_SUPPORT Support;
04187 PLIST_ENTRY NextEntry;
04188
04189
MM_PFN_LOCK_ASSERT();
04190
04191
if (
MmInPageSupportList.
Count == 0) {
04192
ASSERT (IsListEmpty(&
MmInPageSupportList.
ListHead));
04193
UNLOCK_PFN (
APC_LEVEL);
04194 Support =
ExAllocatePoolWithTag (
NonPagedPool,
04195
sizeof(
MMINPAGE_SUPPORT),
04196 'nImM');
04197
if (Support ==
NULL) {
04198
LOCK_PFN (OldIrql);
04199
return NULL;
04200 }
04201
04202
KeInitializeEvent (&Support->
Event, NotificationEvent,
FALSE);
04203
LOCK_PFN (OldIrql);
04204
04205
MmInPageSupportList.
Count += 1;
04206 Support->
u.Thread =
NULL;
04207
#if defined(_PREFETCH_)
04208
Support->PrefetchMdl =
NULL;
04209
#endif
04210
InsertTailList (&
MmInPageSupportList.
ListHead,
04211 &Support->
ListEntry);
04212
return NULL;
04213 }
04214
04215
ASSERT (!IsListEmpty(&
MmInPageSupportList.
ListHead));
04216
MmInPageSupportList.
Count -= 1;
04217 NextEntry = RemoveHeadList (&
MmInPageSupportList.
ListHead);
04218 Support = CONTAINING_RECORD (NextEntry,
04219
MMINPAGE_SUPPORT,
04220 ListEntry );
04221
04222
#if defined(_PREFETCH_)
04223
if ((Support->PrefetchMdl !=
NULL) &&
04224 (Support->PrefetchMdl != &Support->
Mdl)) {
04225
04226
UNLOCK_PFN (
APC_LEVEL);
04227
04228
ExFreePool (Support->PrefetchMdl);
04229
ExFreePool (Support);
04230
04231
LOCK_PFN (OldIrql);
04232
return NULL;
04233 }
04234
#endif
04235
04236 Support->
Completed =
FALSE;
04237 Support->
WaitCount = 1;
04238 Support->
u.Thread =
PsGetCurrentThread();
04239 Support->
ListEntry.Flink =
NULL;
04240
#if defined(_PREFETCH_)
04241
Support->PrefetchMdl =
NULL;
04242
#endif
04243
#if defined (_WIN64)
04244
Support->UsedPageTableEntries = 0;
04245
#endif
04246
KeClearEvent (&Support->
Event);
04247
return Support;
04248 }
04249
04250
04251
VOID
04252 MiFreeInPageSupportBlock (
04253 IN
PMMINPAGE_SUPPORT Support
04254 )
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277 {
04278
04279
MM_PFN_LOCK_ASSERT();
04280
04281
ASSERT (Support->u.Thread !=
NULL);
04282
ASSERT (Support->WaitCount != 0);
04283
#if defined (_PREFETCH_)
04284
ASSERT ((Support->ListEntry.Flink ==
NULL) ||
04285 (Support->PrefetchMdl !=
NULL));
04286
#else
04287
ASSERT (Support->ListEntry.Flink ==
NULL);
04288
#endif
04289
Support->WaitCount -= 1;
04290
if (Support->WaitCount == 0) {
04291 Support->u.Thread =
NULL;
04292 InsertTailList (&
MmInPageSupportList.
ListHead,
04293 &Support->ListEntry);
04294
MmInPageSupportList.
Count += 1;
04295 }
04296
return;
04297 }
04298
04299
04300
VOID
04301 MiFlushInPageSupportBlock (
04302 )
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329 #define
MMMAX_INPAGE_SUPPORT 4
04330
04331 {
04332 KIRQL OldIrql;
04333
PMMINPAGE_SUPPORT Support[10];
04334 ULONG i = 0;
04335 PLIST_ENTRY NextEntry;
04336
04337
MM_PFN_LOCK_ASSERT();
04338
04339
while ((
MmInPageSupportList.
Count >
MMMAX_INPAGE_SUPPORT) && (i < 10)) {
04340 NextEntry = RemoveHeadList (&
MmInPageSupportList.
ListHead);
04341 Support[i] = CONTAINING_RECORD (NextEntry,
04342
MMINPAGE_SUPPORT,
04343 ListEntry );
04344 Support[i]->
ListEntry.Flink =
NULL;
04345 i += 1;
04346
MmInPageSupportList.
Count -= 1;
04347 }
04348
04349
if (i == 0) {
04350
return;
04351 }
04352
04353
UNLOCK_PFN (
APC_LEVEL);
04354
04355
do {
04356 i -= 1;
04357
04358
#if defined (_PREFETCH_)
04359
if ((Support[i]->PrefetchMdl !=
NULL) &&
04360 (Support[i]->PrefetchMdl != &Support[i]->
Mdl)) {
04361
ExFreePool (Support[i]->PrefetchMdl);
04362 }
04363
#endif
04364
04365
ExFreePool(Support[i]);
04366 }
while (i > 0);
04367
04368
LOCK_PFN (OldIrql);
04369
04370
return;
04371 }
04372
04373
VOID
04374 MiHandleBankedSection (
04375 IN PVOID VirtualAddress,
04376 IN
PMMVAD Vad
04377 )
04378
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401
04402 {
04403
PMMBANKED_SECTION Bank;
04404
PMMPTE PointerPte;
04405 ULONG BankNumber;
04406 ULONG size;
04407
04408 Bank = Vad->u4.Banked;
04409 size = Bank->
BankSize;
04410
04411 RtlFillMemory (Bank->
CurrentMappedPte,
04412 size >> (
PAGE_SHIFT -
PTE_SHIFT),
04413 (UCHAR)
ZeroPte.
u.Long);
04414
04415
04416
04417
04418
04419
KeFlushEntireTb (
TRUE,
FALSE);
04420
04421
04422
04423
04424
04425 PointerPte =
MiGetPteAddress (
04426 (PVOID)((ULONG_PTR)VirtualAddress & ~((LONG)size - 1)));
04427 Bank->
CurrentMappedPte = PointerPte;
04428
04429 BankNumber = (ULONG)(((PCHAR)PointerPte - (PCHAR)Bank->
BasedPte) >> Bank->
BankShift);
04430
04431 (Bank->
BankedRoutine)(BankNumber, BankNumber, Bank->
Context);
04432
04433
04434
04435
04436
04437 RtlMoveMemory (PointerPte,
04438 &Bank->
BankTemplate[0],
04439 size >> (
PAGE_SHIFT -
PTE_SHIFT));
04440
04441
return;
04442 }
04443
04444
04445
NTSTATUS
04446 MiSessionCopyOnWrite (
04447 IN
PMM_SESSION_SPACE SessionSpace,
04448 IN PVOID FaultingAddress,
04449 IN
PMMPTE PointerPte
04450 )
04451
04452
04453
04454
04455
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476 {
04477
MMPTE TempPte;
04478
MMPTE PreviousPte;
04479 PFN_NUMBER PageFrameIndex;
04480 PFN_NUMBER NewPageIndex;
04481 PULONG CopyTo;
04482 KIRQL OldIrql;
04483
PMMPFN Pfn1;
04484 PVOID VirtualAddress;
04485
WSLE_NUMBER WorkingSetIndex;
04486
04487
#if defined(_IA64_)
04488
UNREFERENCED_PARAMETER (FaultingAddress);
04489
#endif
04490
04491 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
04492 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
04493
04494
ASSERT (Pfn1->
u3.e1.PrototypePte == 1);
04495
04496
04497
04498
04499
04500 VirtualAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
04501
04502 WorkingSetIndex =
MiLocateWsle (VirtualAddress,
04503 SessionSpace->Vm.VmWorkingSetList,
04504 Pfn1->
u1.WsIndex);
04505
04506
LOCK_PFN (OldIrql);
04507
04508
04509
04510
04511
04512
if (
MiEnsureAvailablePageOrWait(
HYDRA_PROCESS,
NULL)) {
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
UNLOCK_PFN (OldIrql);
04524
return STATUS_SUCCESS;
04525 }
04526
04527
04528
04529
04530
04531
04532 TempPte = *(
volatile MMPTE *)PointerPte;
04533
04534
if (!(TempPte.
u.Hard.Valid && TempPte.
u.Hard.Write == 0)) {
04535
UNLOCK_PFN (OldIrql);
04536
return STATUS_SUCCESS;
04537 }
04538
04539
04540
04541
04542
04543
MmInfoCounters.
CopyOnWriteCount += 1;
04544
04545
MmSessionSpace->
CopyOnWriteCount += 1;
04546
04547
04548
04549
04550
04551
04552
04553
04554
ASSERT (Pfn1->
u3.e1.Modified == 0);
04555
ASSERT (!
MI_IS_PTE_DIRTY(*PointerPte));
04556
04557
04558
04559
04560
04561 NewPageIndex =
MiRemoveAnyPage (
MI_GET_SECONDARY_COLOR (PageFrameIndex,
04562 Pfn1));
04563
04564
MiInitializeCopyOnWritePfn (NewPageIndex,
04565 PointerPte,
04566 WorkingSetIndex,
04567 SessionSpace);
04568
04569
UNLOCK_PFN (OldIrql);
04570
04571
04572
04573
04574
04575 CopyTo = (PULONG)
MiMapPageInHyperSpace (NewPageIndex, &OldIrql);
04576
04577 RtlCopyMemory (CopyTo, VirtualAddress,
PAGE_SIZE);
04578
04579
MiUnmapPageInHyperSpace (OldIrql);
04580
04581
04582
04583
04584
04585
04586
04587
MI_SET_PTE_DIRTY (TempPte);
04588 TempPte.
u.Hard.Write = 1;
04589
MI_SET_ACCESSED_IN_PTE (&TempPte, 1);
04590 TempPte.
u.Hard.CopyOnWrite = 0;
04591 TempPte.
u.Hard.PageFrameNumber = NewPageIndex;
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
ASSERT (TempPte.
u.Hard.Valid == 1);
04602
04603
LOCK_PFN (OldIrql);
04604
04605
04606
04607
04608
04609
MI_FLUSH_SINGLE_SESSION_TB (FaultingAddress,
04610
TRUE,
04611
TRUE,
04612 (PHARDWARE_PTE)PointerPte,
04613 TempPte.
u.Flush,
04614 PreviousPte);
04615
04616
ASSERT (Pfn1->
u3.e1.PrototypePte == 1);
04617
04618
04619
04620
04621
04622
04623
MiDecrementShareCount (PageFrameIndex);
04624
04625
UNLOCK_PFN (OldIrql);
04626
return STATUS_SUCCESS;
04627 }
04628
04629
#if DBG
04630
VOID
04631 MiCheckFileState (
04632 IN
PMMPFN Pfn
04633 )
04634
04635 {
04636
PSUBSECTION Subsection;
04637 LARGE_INTEGER StartingOffset;
04638
04639
if (Pfn->u3.e1.PrototypePte == 0) {
04640
return;
04641 }
04642
if (Pfn->OriginalPte.u.Soft.Prototype == 0) {
04643
return;
04644 }
04645
04646 Subsection =
MiGetSubsectionAddress (&(Pfn->OriginalPte));
04647
if (Subsection->
ControlArea->
u.Flags.NoModifiedWriting) {
04648
return;
04649 }
04650 StartingOffset.QuadPart =
MiStartingOffset (Subsection,
04651 Pfn->PteAddress);
04652
DbgPrint(
"file: %lx offset: %I64X\n",
04653 Subsection->
ControlArea->
FilePointer,
04654 StartingOffset.QuadPart);
04655
return;
04656 }
04657
#endif //DBG