00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "mi.h"
00025
00026
#ifdef ALLOC_PRAGMA
00027
#pragma alloc_text(INIT,MiInitializeSystemCache )
00028
#endif
00029
00030 extern ULONG
MmFrontOfList;
00031
00032
VOID
00033
MiFreeInPageSupportBlock (
00034 IN
PMMINPAGE_SUPPORT Support
00035 );
00036
00037
VOID
00038
MiRemoveMappedPtes (
00039 IN PVOID BaseAddress,
00040 IN ULONG NumberOfPtes,
00041 IN
PCONTROL_AREA ControlArea,
00042 IN
PMMSUPPORT WorkingSetInfo
00043 );
00044
00045 #define X256K 0x40000
00046
00047 PMMPTE MmFirstFreeSystemCache;
00048
00049 PMMPTE MmLastFreeSystemCache;
00050
00051 PMMPTE MmFlushSystemCache;
00052
00053 PMMPTE MmSystemCachePteBase;
00054
00055
00056 LONG
00057
MiMapCacheExceptionFilter (
00058 IN PNTSTATUS Status,
00059 IN PEXCEPTION_POINTERS ExceptionPointer
00060 );
00061
00062
NTSTATUS
00063 MmMapViewInSystemCache (
00064 IN PVOID SectionToMap,
00065 OUT PVOID *CapturedBase,
00066 IN OUT PLARGE_INTEGER SectionOffset,
00067 IN OUT PULONG CapturedViewSize
00068 )
00069
00070
00071
00072
00073
00074
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
PSECTION Section;
00124 ULONG PteOffset;
00125 KIRQL OldIrql;
00126
PMMPTE PointerPte;
00127
PMMPTE LastPte;
00128
PMMPTE ProtoPte;
00129
PMMPTE LastProto;
00130
PSUBSECTION Subsection;
00131 PVOID EndingVa;
00132
PCONTROL_AREA ControlArea;
00133
00134 Section = SectionToMap;
00135
00136
00137
00138
00139
00140
00141
ASSERT (*CapturedViewSize <= 256
L*1024
L);
00142
ASSERT ((SectionOffset->LowPart & (256
L*1024
L - 1)) == 0);
00143
00144
00145
00146
00147
00148
00149
if (Section->u.Flags.Image) {
00150
return STATUS_NOT_MAPPED_DATA;
00151 }
00152
00153 ControlArea = Section->
Segment->
ControlArea;
00154
00155
ASSERT (*CapturedViewSize != 0);
00156
00157
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
00158
00159 Subsection = (
PSUBSECTION)(ControlArea + 1);
00160
00161
LOCK_PFN (OldIrql);
00162
00163
ASSERT (ControlArea->
u.Flags.BeingCreated == 0);
00164
ASSERT (ControlArea->
u.Flags.BeingDeleted == 0);
00165
ASSERT (ControlArea->
u.Flags.BeingPurged == 0);
00166
00167
00168
00169
00170
00171
if (
MmFirstFreeSystemCache == (
PMMPTE)
MM_EMPTY_LIST) {
00172
UNLOCK_PFN (OldIrql);
00173
return STATUS_NO_MEMORY;
00174 }
00175
00176
if (
MmFirstFreeSystemCache ==
MmFlushSystemCache) {
00177
00178
00179
00180
00181
00182
00183
KeFlushEntireTb (
TRUE,
TRUE);
00184
MmFlushSystemCache =
NULL;
00185 }
00186
00187 PointerPte =
MmFirstFreeSystemCache;
00188
00189
00190
00191
00192
00193
ASSERT (PointerPte->
u.Hard.Valid == 0);
00194
00195
if (PointerPte->
u.List.NextEntry ==
MM_EMPTY_PTE_LIST) {
00196
KeBugCheckEx (MEMORY_MANAGEMENT,
00197 0x778,
00198 (ULONG_PTR)PointerPte,
00199 0,
00200 0);
00201
MmFirstFreeSystemCache = (
PMMPTE)
MM_EMPTY_LIST;
00202 }
00203
else {
00204
MmFirstFreeSystemCache =
MmSystemCachePteBase + PointerPte->
u.List.NextEntry;
00205
ASSERT (
MmFirstFreeSystemCache <=
MiGetPteAddress (
MmSystemCacheEnd));
00206 }
00207
00208
00209
00210
00211
00212
00213 ControlArea->
NumberOfMappedViews += 1;
00214 ControlArea->
NumberOfSystemCacheViews += 1;
00215
ASSERT (ControlArea->
NumberOfSectionReferences != 0);
00216
00217
UNLOCK_PFN (OldIrql);
00218
00219 *CapturedBase =
MiGetVirtualAddressMappedByPte (PointerPte);
00220
00221 EndingVa = (PVOID)(((ULONG_PTR)*CapturedBase +
00222 *CapturedViewSize - 1
L) | (
PAGE_SIZE - 1
L));
00223
00224
00225
00226
00227
00228
00229
#if DBG
00230
00231
00232
00233
00234
00235 PointerPte->
u.List.NextEntry = 0;
00236
#endif //DBG
00237
00238 LastPte =
MiGetPteAddress (EndingVa);
00239
00240
00241
00242
00243
00244 PteOffset = (ULONG)(SectionOffset->QuadPart >>
PAGE_SHIFT);
00245
00246
00247
00248
00249
00250
00251
while (PteOffset >= Subsection->
PtesInSubsection) {
00252 PteOffset -= Subsection->
PtesInSubsection;
00253 Subsection = Subsection->
NextSubsection;
00254 }
00255
00256 ProtoPte = &Subsection->
SubsectionBase[PteOffset];
00257
00258 LastProto = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00259
00260
while (PointerPte <= LastPte) {
00261
00262
if (ProtoPte >= LastProto) {
00263
00264
00265
00266
00267
00268 Subsection = Subsection->
NextSubsection;
00269 ProtoPte = Subsection->
SubsectionBase;
00270 LastProto = &Subsection->
SubsectionBase[
00271 Subsection->
PtesInSubsection];
00272 }
00273
ASSERT (PointerPte->
u.Long ==
ZeroKernelPte.
u.Long);
00274 PointerPte->
u.Long =
MiProtoAddressForKernelPte (ProtoPte);
00275
00276
ASSERT (((ULONG_PTR)PointerPte & (
MM_COLOR_MASK <<
PTE_SHIFT)) ==
00277 (((ULONG_PTR)ProtoPte & (
MM_COLOR_MASK <<
PTE_SHIFT))));
00278
00279 PointerPte += 1;
00280 ProtoPte += 1;
00281 }
00282
00283
return STATUS_SUCCESS;
00284 }
00285
00286
VOID
00287 MiAddMappedPtes (
00288 IN
PMMPTE FirstPte,
00289 IN ULONG NumberOfPtes,
00290 IN
PCONTROL_AREA ControlArea
00291 )
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 {
00324
PMMPTE PointerPte;
00325
PMMPTE ProtoPte;
00326
PMMPTE LastProto;
00327
PMMPTE LastPte;
00328
PSUBSECTION Subsection;
00329
00330
if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
00331 Subsection = (
PSUBSECTION)(ControlArea + 1);
00332 }
00333
else {
00334 Subsection = (
PSUBSECTION)((
PLARGE_CONTROL_AREA)ControlArea + 1);
00335 }
00336
00337 PointerPte = FirstPte;
00338
ASSERT (NumberOfPtes != 0);
00339 LastPte = FirstPte + NumberOfPtes;
00340
00341
ASSERT (ControlArea->NumberOfMappedViews >= 1);
00342
ASSERT (ControlArea->NumberOfUserReferences >= 1);
00343
ASSERT (ControlArea->u.Flags.HadUserReference == 1);
00344
ASSERT (ControlArea->NumberOfSectionReferences != 0);
00345
00346
ASSERT (ControlArea->u.Flags.BeingCreated == 0);
00347
ASSERT (ControlArea->u.Flags.BeingDeleted == 0);
00348
ASSERT (ControlArea->u.Flags.BeingPurged == 0);
00349
00350 ProtoPte = Subsection->
SubsectionBase;
00351
00352 LastProto = &Subsection->
SubsectionBase[Subsection->
PtesInSubsection];
00353
00354
while (PointerPte < LastPte) {
00355
00356
if (ProtoPte >= LastProto) {
00357
00358
00359
00360
00361
00362 Subsection = Subsection->
NextSubsection;
00363 ProtoPte = Subsection->
SubsectionBase;
00364 LastProto = &Subsection->
SubsectionBase[
00365 Subsection->
PtesInSubsection];
00366 }
00367
ASSERT (PointerPte->
u.Long ==
ZeroKernelPte.
u.Long);
00368 PointerPte->
u.Long =
MiProtoAddressForKernelPte (ProtoPte);
00369
00370
ASSERT (((ULONG_PTR)PointerPte & (
MM_COLOR_MASK <<
PTE_SHIFT)) ==
00371 (((ULONG_PTR)ProtoPte & (
MM_COLOR_MASK <<
PTE_SHIFT))));
00372
00373 PointerPte += 1;
00374 ProtoPte += 1;
00375 }
00376
00377
return;
00378 }
00379
00380
VOID
00381 MmUnmapViewInSystemCache (
00382 IN PVOID BaseAddress,
00383 IN PVOID SectionToUnmap,
00384 IN ULONG AddToFront
00385 )
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 {
00419
PMMPTE PointerPte;
00420
PMMPFN Pfn1;
00421
PMMPTE FirstPte;
00422
MMPTE PteContents;
00423 KIRQL OldIrql;
00424 KIRQL OldIrqlWs;
00425 PFN_NUMBER i;
00426
WSLE_NUMBER WorkingSetIndex;
00427
PCONTROL_AREA ControlArea;
00428 ULONG WsHeld;
00429 PFN_NUMBER PdeFrameNumber;
00430
00431 WsHeld =
FALSE;
00432
00433
ASSERT (KeGetCurrentIrql() <=
APC_LEVEL);
00434
00435 PointerPte =
MiGetPteAddress (BaseAddress);
00436 FirstPte = PointerPte;
00437 ControlArea = ((
PSECTION)SectionToUnmap)->
Segment->
ControlArea;
00438 PdeFrameNumber =
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress (PointerPte));
00439
00440
00441
00442
00443
00444 i = 0;
00445
00446
do {
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 PteContents = *(
volatile MMPTE *)PointerPte;
00461
if (PteContents.
u.Hard.Valid == 1) {
00462
00463
if (!WsHeld) {
00464 WsHeld =
TRUE;
00465
LOCK_SYSTEM_WS (OldIrqlWs);
00466
continue;
00467 }
00468
00469 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
00470
00471 WorkingSetIndex =
MiLocateWsle (BaseAddress,
00472
MmSystemCacheWorkingSetList,
00473 Pfn1->
u1.WsIndex );
00474
MiRemoveWsle (WorkingSetIndex,
00475
MmSystemCacheWorkingSetList );
00476
MiReleaseWsle (WorkingSetIndex, &
MmSystemCacheWs);
00477
00478
MI_SET_PTE_IN_WORKING_SET (PointerPte, 0);
00479
00480
00481
00482
00483
00484
LOCK_PFN (OldIrql);
00485
00486
00487
00488
00489
00490
MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
00491
00492
00493
00494
00495
00496
00497
MiDecrementShareAndValidCount (PdeFrameNumber);
00498
00499
00500
00501
00502
00503
#if DBG
00504
if (ControlArea->
NumberOfMappedViews == 1) {
00505
PMMPFN Pfn;
00506 Pfn =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
00507
ASSERT (Pfn->
u2.ShareCount == 1);
00508 }
00509
#endif //DBG
00510
00511
00512
MmFrontOfList = AddToFront;
00513
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents));
00514
MmFrontOfList =
FALSE;
00515
UNLOCK_PFN (OldIrql);
00516 }
else {
00517
if (WsHeld) {
00518
UNLOCK_SYSTEM_WS (OldIrqlWs);
00519 WsHeld =
FALSE;
00520 }
00521
00522
ASSERT ((PteContents.
u.Long ==
ZeroKernelPte.
u.Long) ||
00523 (PteContents.
u.Soft.Prototype == 1));
00524 NOTHING;
00525 }
00526
MI_WRITE_INVALID_PTE (PointerPte,
ZeroKernelPte);
00527
00528 PointerPte += 1;
00529 BaseAddress = (PVOID)((PCHAR)BaseAddress +
PAGE_SIZE);
00530 i += 1;
00531 }
while (i < (
X256K /
PAGE_SIZE));
00532
00533
if (WsHeld) {
00534
UNLOCK_SYSTEM_WS (OldIrqlWs);
00535 }
00536
00537 FirstPte->
u.List.NextEntry =
MM_EMPTY_PTE_LIST;
00538
00539
LOCK_PFN (OldIrql);
00540
00541
00542
00543
00544
00545
if (
MmFlushSystemCache ==
NULL) {
00546
00547
00548
00549
00550
00551
00552
00553
MmFlushSystemCache = FirstPte;
00554 }
00555
00556
MmLastFreeSystemCache->
u.List.NextEntry = FirstPte -
MmSystemCachePteBase;
00557
MmLastFreeSystemCache = FirstPte;
00558
00559
00560
00561
00562
00563
00564 ControlArea->
NumberOfMappedViews -= 1;
00565 ControlArea->
NumberOfSystemCacheViews -= 1;
00566
00567
00568
00569
00570
00571
00572
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00573
00574
return;
00575 }
00576
00577
00578
VOID
00579 MiRemoveMappedPtes (
00580 IN PVOID BaseAddress,
00581 IN ULONG NumberOfPtes,
00582 IN
PCONTROL_AREA ControlArea,
00583 IN
PMMSUPPORT WorkingSetInfo
00584 )
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 {
00617
PMMPTE PointerPte;
00618
PMMPTE PointerPde;
00619
PMMPFN Pfn1;
00620
PMMPTE FirstPte;
00621
MMPTE PteContents;
00622 KIRQL OldIrql;
00623 KIRQL OldIrqlWs;
00624 ULONG WorkingSetIndex;
00625 ULONG DereferenceSegment;
00626
MMPTE_FLUSH_LIST PteFlushList;
00627 ULONG WsHeld;
00628
00629 DereferenceSegment =
FALSE;
00630 WsHeld =
FALSE;
00631
00632 PteFlushList.
Count = 0;
00633 PointerPte =
MiGetPteAddress (BaseAddress);
00634 FirstPte = PointerPte;
00635
00636
00637
00638
00639
00640
while (NumberOfPtes) {
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 PteContents = *PointerPte;
00657
if (PteContents.
u.Hard.Valid == 1) {
00658
00659
00660
00661
00662
00663
00664
if (WorkingSetInfo == &
MmSystemCacheWs) {
00665
if (!WsHeld) {
00666 WsHeld =
TRUE;
00667
LOCK_SYSTEM_WS (OldIrqlWs);
00668
continue;
00669 }
00670 }
00671
00672 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
00673
00674 WorkingSetIndex =
MiLocateWsle (BaseAddress,
00675 WorkingSetInfo->VmWorkingSetList,
00676 Pfn1->
u1.WsIndex );
00677
ASSERT (WorkingSetIndex !=
WSLE_NULL_INDEX);
00678
00679
MiRemoveWsle (WorkingSetIndex,
00680 WorkingSetInfo->VmWorkingSetList );
00681
MiReleaseWsle (WorkingSetIndex, WorkingSetInfo);
00682
00683
MI_SET_PTE_IN_WORKING_SET (PointerPte, 0);
00684
00685
LOCK_PFN (OldIrql);
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
00696
00697
00698
00699
00700
00701
if (PteFlushList.
Count !=
MM_MAXIMUM_FLUSH_COUNT) {
00702 PteFlushList.
FlushPte[PteFlushList.
Count] = PointerPte;
00703 PteFlushList.
FlushVa[PteFlushList.
Count] = BaseAddress;
00704 PteFlushList.
Count += 1;
00705 }
00706
00707 PointerPde =
MiGetPteAddress (PointerPte);
00708
00709
#if !defined (_WIN64)
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
if (PointerPde->
u.Long == 0) {
00723
00724
PMMPTE MasterPde;
00725
00726
ASSERT (
MiHydra ==
FALSE);
00727
00728
#if !defined (_X86PAE_)
00729
MasterPde = &
MmSystemPagePtes [((ULONG_PTR)PointerPde &
00730 ((
sizeof(
MMPTE) *
PDE_PER_PAGE) - 1)) /
sizeof(
MMPTE)];
00731
#else
00732
MasterPde = &
MmSystemPagePtes [((ULONG_PTR)PointerPde &
00733 (PD_PER_SYSTEM * (
sizeof(
MMPTE) *
PDE_PER_PAGE) - 1)) /
sizeof(
MMPTE)];
00734
#endif
00735
ASSERT (MasterPde->
u.Hard.Valid == 1);
00736
MI_WRITE_VALID_PTE (PointerPde, *MasterPde);
00737 }
00738
#endif
00739
00740
00741
00742
00743
00744
00745
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
00746
00747
00748
00749
00750
00751
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents));
00752
UNLOCK_PFN (OldIrql);
00753
00754 }
else {
00755
if (WorkingSetInfo == &
MmSystemCacheWs) {
00756
if (WsHeld) {
00757
UNLOCK_SYSTEM_WS (OldIrqlWs);
00758 WsHeld =
FALSE;
00759 }
00760 }
00761
00762
ASSERT ((PteContents.
u.Long ==
ZeroKernelPte.
u.Long) ||
00763 (PteContents.
u.Soft.Prototype == 1));
00764 NOTHING;
00765 }
00766
MI_WRITE_INVALID_PTE (PointerPte,
ZeroKernelPte);
00767
00768 PointerPte += 1;
00769 BaseAddress = (PVOID)((PCHAR)BaseAddress +
PAGE_SIZE);
00770 NumberOfPtes -= 1;
00771 }
00772
00773
if (WorkingSetInfo == &
MmSystemCacheWs) {
00774
if (WsHeld) {
00775
UNLOCK_SYSTEM_WS (OldIrqlWs);
00776 }
00777 }
00778
LOCK_PFN (OldIrql);
00779
00780
MiFlushPteList (&PteFlushList,
TRUE,
ZeroKernelPte);
00781
00782
if (WorkingSetInfo != &
MmSystemCacheWs) {
00783
00784
00785
00786
00787
00788
MI_FLUSH_ENTIRE_SESSION_TB (
TRUE,
TRUE);
00789 }
00790
00791
00792
00793
00794
00795
00796 ControlArea->NumberOfUserReferences -= 1;
00797
00798
00799
00800
00801
00802
00803 ControlArea->NumberOfMappedViews -= 1;
00804
00805
00806
00807
00808
00809
00810
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00811 }
00812
00813
VOID
00814 MiInitializeSystemCache (
00815 IN ULONG MinimumWorkingSet,
00816 IN ULONG MaximumWorkingSet
00817 )
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 ULONG SizeOfSystemCacheInPages;
00846 ULONG HunksOf256KInCache;
00847
PMMWSLE WslEntry;
00848 ULONG NumberOfEntriesMapped;
00849 PFN_NUMBER i;
00850
MMPTE PteContents;
00851
PMMPTE PointerPte;
00852 KIRQL OldIrql;
00853
00854 PointerPte =
MiGetPteAddress (
MmSystemCacheWorkingSetList);
00855
00856 PteContents =
ValidKernelPte;
00857
00858
LOCK_PFN (OldIrql);
00859
00860 i =
MiRemoveZeroPage(
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
00861
00862 PteContents.
u.Hard.PageFrameNumber = i;
00863
00864
MI_WRITE_VALID_PTE (PointerPte, PteContents);
00865
00866
MiInitializePfn (i, PointerPte, 1
L);
00867
00868
UNLOCK_PFN (OldIrql);
00869
00870
#if defined (_WIN64)
00871
MmSystemCacheWsle = (
PMMWSLE)(
MmSystemCacheWorkingSetList + 1);
00872
#else
00873
MmSystemCacheWsle =
00874 (
PMMWSLE)(&
MmSystemCacheWorkingSetList->
UsedPageTableEntries[0]);
00875
#endif
00876
00877
MmSystemCacheWs.
VmWorkingSetList =
MmSystemCacheWorkingSetList;
00878
MmSystemCacheWs.
WorkingSetSize = 0;
00879
MmSystemCacheWs.
MinimumWorkingSetSize = MinimumWorkingSet;
00880
MmSystemCacheWs.
MaximumWorkingSetSize = MaximumWorkingSet;
00881 InsertTailList (&
MmWorkingSetExpansionHead.
ListHead,
00882 &
MmSystemCacheWs.
WorkingSetExpansionLinks);
00883
00884
MmSystemCacheWs.
AllowWorkingSetAdjustment =
TRUE;
00885
00886
00887
00888
00889
00890
00891
00892
MmSystemCacheWorkingSetList->
FirstFree = 1;
00893
MmSystemCacheWorkingSetList->
FirstDynamic = 1;
00894
MmSystemCacheWorkingSetList->
NextSlot = 1;
00895
MmSystemCacheWorkingSetList->
LastEntry = (ULONG)
MmSystemCacheWsMinimum;
00896
MmSystemCacheWorkingSetList->
Quota =
MmSystemCacheWorkingSetList->
LastEntry;
00897
MmSystemCacheWorkingSetList->
HashTable =
NULL;
00898
MmSystemCacheWorkingSetList->
HashTableSize = 0;
00899
MmSystemCacheWorkingSetList->
Wsle =
MmSystemCacheWsle;
00900
00901
MmSystemCacheWorkingSetList->
HashTableStart =
00902 (PVOID)((PCHAR)
PAGE_ALIGN (&
MmSystemCacheWorkingSetList->
Wsle[
MM_MAXIMUM_WORKING_SET]) +
PAGE_SIZE);
00903
00904
MmSystemCacheWorkingSetList->
HighestPermittedHashAddress = (PVOID)(
MM_SYSTEM_CACHE_START);
00905
00906 NumberOfEntriesMapped = (ULONG)(((
PMMWSLE)((PCHAR)
MmSystemCacheWorkingSetList +
00907
PAGE_SIZE)) -
MmSystemCacheWsle);
00908
00909
LOCK_PFN (OldIrql);
00910
00911
while (NumberOfEntriesMapped <
MmSystemCacheWsMaximum) {
00912
00913 PointerPte += 1;
00914 i =
MiRemoveZeroPage(
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
00915 PteContents.
u.Hard.PageFrameNumber = i;
00916
MI_WRITE_VALID_PTE (PointerPte, PteContents);
00917
MiInitializePfn (i, PointerPte, 1
L);
00918 NumberOfEntriesMapped +=
PAGE_SIZE /
sizeof(
MMWSLE);
00919 }
00920
00921
UNLOCK_PFN (OldIrql);
00922
00923
00924
00925
00926
00927 WslEntry =
MmSystemCacheWsle + 1;
00928
00929
for (i = 1; i < NumberOfEntriesMapped; i++) {
00930
00931
00932
00933
00934
00935
00936
00937
00938 WslEntry->
u1.Long = (i + 1) <<
MM_FREE_WSLE_SHIFT;
00939 WslEntry += 1;
00940 }
00941
00942 WslEntry -= 1;
00943 WslEntry->
u1.Long =
WSLE_NULL_INDEX <<
MM_FREE_WSLE_SHIFT;
00944
00945
MmSystemCacheWorkingSetList->
LastInitializedWsle = NumberOfEntriesMapped - 1;
00946
00947
00948
00949
00950
00951
MmSystemCachePteBase =
MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS;
00952
00953 SizeOfSystemCacheInPages =
COMPUTE_PAGES_SPANNED (
MmSystemCacheStart,
00954 (PCHAR)
MmSystemCacheEnd - (PCHAR)
MmSystemCacheStart + 1);
00955
00956 HunksOf256KInCache = SizeOfSystemCacheInPages / (
X256K /
PAGE_SIZE);
00957
00958 PointerPte =
MiGetPteAddress (
MmSystemCacheStart);
00959
00960
MmFirstFreeSystemCache = PointerPte;
00961
00962
for (i = 0; i < HunksOf256KInCache; i += 1) {
00963 PointerPte->
u.List.NextEntry = (PointerPte + (
X256K /
PAGE_SIZE)) -
MmSystemCachePteBase;
00964 PointerPte +=
X256K /
PAGE_SIZE;
00965 }
00966
00967 PointerPte -=
X256K /
PAGE_SIZE;
00968
00969
#if defined(_X86_)
00970
00971
00972
00973
00974
00975
if (
MiSystemCacheEndExtra !=
MmSystemCacheEnd) {
00976
00977 SizeOfSystemCacheInPages =
COMPUTE_PAGES_SPANNED (
MiSystemCacheStartExtra,
00978 (PCHAR)
MiSystemCacheEndExtra - (PCHAR)
MiSystemCacheStartExtra + 1);
00979
00980 HunksOf256KInCache = SizeOfSystemCacheInPages / (
X256K /
PAGE_SIZE);
00981
00982
if (HunksOf256KInCache) {
00983
00984
PMMPTE PointerPteExtended;
00985
00986 PointerPteExtended =
MiGetPteAddress (
MiSystemCacheStartExtra);
00987 PointerPte->u.List.NextEntry = PointerPteExtended -
MmSystemCachePteBase;
00988 PointerPte = PointerPteExtended;
00989
00990
for (i = 0; i < HunksOf256KInCache; i += 1) {
00991 PointerPte->
u.List.NextEntry = (PointerPte + (
X256K /
PAGE_SIZE)) -
MmSystemCachePteBase;
00992 PointerPte +=
X256K /
PAGE_SIZE;
00993 }
00994
00995 PointerPte -=
X256K /
PAGE_SIZE;
00996 }
00997 }
00998
#endif
00999
01000 PointerPte->u.List.NextEntry =
MM_EMPTY_PTE_LIST;
01001
MmLastFreeSystemCache = PointerPte;
01002
01003
if (MaximumWorkingSet > ((1536*1024) >>
PAGE_SHIFT)) {
01004
01005
01006
01007
01008
01009
LOCK_SYSTEM_WS (OldIrql);
01010
MiGrowWsleHash (&
MmSystemCacheWs);
01011
UNLOCK_SYSTEM_WS (OldIrql);
01012 }
01013 }
01014
01015 BOOLEAN
01016 MmCheckCachedPageState (
01017 IN PVOID Address,
01018 IN BOOLEAN SetToZero
01019 )
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 {
01058
PMMPTE PointerPte;
01059
PMMPTE PointerPde;
01060
PMMPTE ProtoPte;
01061 PFN_NUMBER PageFrameIndex;
01062
WSLE_NUMBER WorkingSetIndex;
01063
MMPTE TempPte;
01064
MMPTE ProtoPteContents;
01065
PMMPFN Pfn1;
01066
PMMPFN Pfn2;
01067 KIRQL OldIrql;
01068 LOGICAL BarrierNeeded;
01069 ULONG BarrierStamp;
01070
01071 BarrierNeeded =
FALSE;
01072
01073 PointerPte =
MiGetPteAddress (Address);
01074
01075
01076
01077
01078
01079
if (PointerPte->
u.Hard.Valid == 1) {
01080
return TRUE;
01081 }
01082
01083
LOCK_PFN (OldIrql);
01084
01085
if (PointerPte->
u.Hard.Valid == 1) {
01086
goto UnlockAndReturnTrue;
01087 }
01088
01089
ASSERT (PointerPte->
u.Soft.Prototype == 1);
01090
01091 ProtoPte =
MiPteToProto (PointerPte);
01092
01093
01094
01095
01096
01097
if (
MiMakeSystemAddressValidPfn (ProtoPte)) {
01098
01099
01100
01101
01102
01103
if (PointerPte->
u.Hard.Valid == 1) {
01104
goto UnlockAndReturnTrue;
01105 }
01106 }
01107
01108 ProtoPteContents = *ProtoPte;
01109
01110
if (ProtoPteContents.
u.Hard.Valid == 1) {
01111
01112 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&ProtoPteContents);
01113 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01114
01115
01116
01117
01118
01119
01120 TempPte = ProtoPteContents;
01121
01122 }
else if ((ProtoPteContents.
u.Soft.Transition == 1) &&
01123 (ProtoPteContents.
u.Soft.Prototype == 0)) {
01124
01125
01126
01127
01128
01129
01130 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&ProtoPteContents);
01131 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01132
if ((Pfn1->
u3.e1.ReadInProgress) ||
01133 (Pfn1->
u3.e1.InPageError)) {
01134
01135
01136
01137
01138
01139
goto UnlockAndReturnTrue;
01140 }
01141
01142
MiUnlinkPageFromList (Pfn1);
01143
01144 Pfn1->
u3.e2.ReferenceCount += 1;
01145 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
01146
01147
MI_MAKE_VALID_PTE (TempPte,
01148 PageFrameIndex,
01149 Pfn1->
OriginalPte.
u.Soft.Protection,
01150
NULL );
01151
01152
MI_WRITE_VALID_PTE (ProtoPte, TempPte);
01153
01154
01155
01156
01157
01158
01159 Pfn2 =
MI_PFN_ELEMENT (Pfn1->
PteFrame);
01160
01161 }
else {
01162
01163
01164
01165
01166
01167
01168
if ((SetToZero ==
FALSE) || (
MmAvailablePages < 8)) {
01169
UNLOCK_PFN (OldIrql);
01170
01171
01172
01173
01174
01175
MmAccessFault (
FALSE, Address,
KernelMode, (PVOID)0);
01176
return FALSE;
01177 }
01178
01179
01180
01181
01182
01183
01184
MiGetSubsectionAddress (
01185 ProtoPte)->ControlArea->NumberOfPfnReferences += 1;
01186
01187 PageFrameIndex =
MiRemoveZeroPage(
MI_GET_PAGE_COLOR_FROM_PTE (ProtoPte));
01188
01189 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01190
01191
01192
01193
01194
01195
01196
01197 BarrierNeeded =
TRUE;
01198 BarrierStamp = (ULONG)Pfn1->
PteFrame;
01199
01200
MiInitializePfn (PageFrameIndex, ProtoPte, 1);
01201 Pfn1->
u2.ShareCount = 0;
01202 Pfn1->
u3.e1.PrototypePte = 1;
01203
01204
MI_MAKE_VALID_PTE (TempPte,
01205 PageFrameIndex,
01206 Pfn1->
OriginalPte.
u.Soft.Protection,
01207
NULL );
01208
01209
MI_WRITE_VALID_PTE (ProtoPte, TempPte);
01210 }
01211
01212
01213
01214
01215
01216
01217 Pfn1->
u2.ShareCount += 1;
01218
01219
if (Pfn1->
u1.Event ==
NULL) {
01220 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
01221 }
01222
01223
01224
01225
01226
01227
01228 PointerPde =
MiGetPteAddress (PointerPte);
01229 Pfn2 =
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
01230
01231 Pfn2->
u2.ShareCount += 1;
01232
01233
MI_SET_GLOBAL_STATE (TempPte, 1);
01234
01235
#if defined (_WIN64)
01236
if (
MI_DETERMINE_OWNER (PointerPte) == 0) {
01237 TempPte.
u.Long &= ~
MM_PTE_OWNER_MASK;
01238 }
01239
#else
01240
TempPte.
u.Hard.Owner =
MI_DETERMINE_OWNER (PointerPte);
01241
#endif
01242
01243
if (BarrierNeeded) {
01244
MI_BARRIER_SYNCHRONIZE (BarrierStamp);
01245 }
01246
01247
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01248
01249
UNLOCK_PFN (OldIrql);
01250
01251
LOCK_SYSTEM_WS (OldIrql);
01252
01253 WorkingSetIndex =
MiLocateAndReserveWsle (&
MmSystemCacheWs);
01254
01255
MiUpdateWsle (&WorkingSetIndex,
01256
MiGetVirtualAddressMappedByPte (PointerPte),
01257
MmSystemCacheWorkingSetList,
01258 Pfn1);
01259
01260
MmSystemCacheWsle[WorkingSetIndex].
u1.e1.SameProtectAsProto = 1;
01261
01262
MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex);
01263
01264
UNLOCK_SYSTEM_WS (OldIrql);
01265
01266
return TRUE;
01267
01268 UnlockAndReturnTrue:
01269
UNLOCK_PFN (OldIrql);
01270
return TRUE;
01271 }
01272
01273
NTSTATUS
01274 MmCopyToCachedPage (
01275 IN PVOID Address,
01276 IN PVOID UserBuffer,
01277 IN ULONG Offset,
01278 IN SIZE_T CountInBytes,
01279 IN BOOLEAN DontZero
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
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 {
01324
PMMPTE PointerPte;
01325
PMMPTE PointerPde;
01326
PMMPTE ProtoPte;
01327 PFN_NUMBER PageFrameIndex;
01328
WSLE_NUMBER WorkingSetIndex;
01329
MMPTE TempPte;
01330
MMPTE ProtoPteContents;
01331
PMMPFN Pfn1;
01332
PMMPFN Pfn2;
01333 KIRQL OldIrql;
01334 ULONG TransitionState;
01335 ULONG AddToWorkingSet;
01336 LOGICAL ShareCountUpped;
01337 SIZE_T EndFill;
01338 PVOID
Buffer;
01339
NTSTATUS status;
01340
PMMINPAGE_SUPPORT Event;
01341
PCONTROL_AREA ControlArea;
01342
PETHREAD Thread;
01343 ULONG SavedState;
01344 LOGICAL ApcsExplicitlyBlocked;
01345 LOGICAL ApcNeeded;
01346
01347 TransitionState =
FALSE;
01348 AddToWorkingSet =
FALSE;
01349 ApcsExplicitlyBlocked =
FALSE;
01350 ApcNeeded =
FALSE;
01351
01352
ASSERT (((ULONG_PTR)Address & (
PAGE_SIZE - 1)) == 0);
01353
ASSERT ((CountInBytes +
Offset) <=
PAGE_SIZE);
01354
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
01355
01356 PointerPte =
MiGetPteAddress (Address);
01357
01358
if (PointerPte->
u.Hard.Valid == 1) {
01359
goto Copy;
01360 }
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
try {
01374
01375 *(
volatile CHAR *)UserBuffer;
01376
01377 } except (
EXCEPTION_EXECUTE_HANDLER) {
01378
return GetExceptionCode();
01379 }
01380
01381
01382
01383
01384
01385
LOCK_PFN (OldIrql);
01386
01387 Recheck:
01388
01389
if (PointerPte->
u.Hard.Valid == 1) {
01390
goto UnlockAndCopy;
01391 }
01392
01393
ASSERT (PointerPte->
u.Soft.Prototype == 1);
01394
01395 ProtoPte =
MiPteToProto (PointerPte);
01396
01397
01398
01399
01400
01401
if (
MiMakeSystemAddressValidPfn (ProtoPte)) {
01402
01403
01404
01405
01406
01407
if (PointerPte->
u.Hard.Valid == 1) {
01408
goto UnlockAndCopy;
01409 }
01410 }
01411
01412 ShareCountUpped =
FALSE;
01413 ProtoPteContents = *ProtoPte;
01414
01415
if (ProtoPteContents.
u.Hard.Valid == 1) {
01416
01417 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&ProtoPteContents);
01418 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01419
01420
01421
01422
01423
01424
01425 Pfn1->
u2.ShareCount += 1;
01426 ShareCountUpped =
TRUE;
01427
01428
01429
01430
01431
01432
01433 TempPte = ProtoPteContents;
01434
01435 }
else if ((ProtoPteContents.
u.Soft.Transition == 1) &&
01436 (ProtoPteContents.
u.Soft.Prototype == 0)) {
01437
01438
01439
01440
01441
01442
01443 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&ProtoPteContents);
01444 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01445
if ((Pfn1->
u3.e1.ReadInProgress) ||
01446 (Pfn1->
u3.e1.InPageError)) {
01447
01448
01449
01450
01451
01452
01453
goto UnlockAndCopy;
01454 }
01455
01456
MiUnlinkPageFromList (Pfn1);
01457
01458 Pfn1->
u3.e2.ReferenceCount += 1;
01459 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
01460 Pfn1->
u3.e1.Modified = 1;
01461
ASSERT (Pfn1->
u2.ShareCount == 0);
01462 Pfn1->
u2.ShareCount += 1;
01463 ShareCountUpped =
TRUE;
01464
01465
MI_MAKE_VALID_PTE (TempPte,
01466 PageFrameIndex,
01467 Pfn1->
OriginalPte.
u.Soft.Protection,
01468
NULL );
01469
MI_SET_PTE_DIRTY (TempPte);
01470
01471
MI_WRITE_VALID_PTE (ProtoPte, TempPte);
01472
01473
01474
01475
01476
01477
01478 }
else {
01479
01480
01481
01482
01483
01484
01485
if (
MiEnsureAvailablePageOrWait (
NULL,
NULL)) {
01486
01487
01488
01489
01490
01491
01492
goto Recheck;
01493 }
01494
01495
Event =
MiGetInPageSupportBlock ();
01496
if (
Event ==
NULL) {
01497
UNLOCK_PFN (OldIrql);
01498
KeDelayExecutionThread (
KernelMode,
FALSE, (PLARGE_INTEGER)&
MmShortTime);
01499
LOCK_PFN (OldIrql);
01500
goto Recheck;
01501 }
01502
01503
01504
01505
01506
01507
01508 ControlArea =
MiGetSubsectionAddress (ProtoPte)->ControlArea;
01509 ControlArea->
NumberOfPfnReferences += 1;
01510
if (ControlArea->
NumberOfUserReferences > 0) {
01511
01512
01513
01514
01515
01516 DontZero =
FALSE;
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526 PageFrameIndex =
MiRemoveAnyPage(
MI_GET_PAGE_COLOR_FROM_PTE (ProtoPte));
01527
01528 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01529
01530
01531
01532
01533
01534
01535
MiInitializeTransitionPfn (PageFrameIndex, ProtoPte, 0xFFFFFFFF);
01536
01537 Pfn1->
u2.ShareCount = 0;
01538
01539 Pfn1->
u3.e2.ReferenceCount = 0;
01540
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 24);
01541
01542 Pfn1->
u3.e2.ReferenceCount = 1;
01543 Pfn1->
u3.e1.PrototypePte = 1;
01544 Pfn1->
u3.e1.Modified = 1;
01545 Pfn1->
u3.e1.ReadInProgress = 1;
01546 Pfn1->
u1.Event = &
Event->Event;
01547
Event->Pfn = Pfn1;
01548
01549
01550
01551
01552
01553
01554
01555 Thread =
PsGetCurrentThread ();
01556
ASSERT (Thread->
NestedFaultCount <= 1);
01557 Thread->
NestedFaultCount += 1;
01558
01559 TransitionState =
TRUE;
01560
01561
MI_MAKE_VALID_PTE (TempPte,
01562 PageFrameIndex,
01563 Pfn1->
OriginalPte.
u.Soft.Protection,
01564
NULL);
01565
MI_SET_PTE_DIRTY (TempPte);
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
KeEnterCriticalRegion();
01576 ApcsExplicitlyBlocked =
TRUE;
01577 }
01578
01579
01580
01581
01582
01583 PointerPde =
MiGetPteAddress (PointerPte);
01584 Pfn2 =
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
01585
01586 Pfn2->
u2.ShareCount += 1;
01587
01588
MI_SET_GLOBAL_STATE (TempPte, 1);
01589
#if defined (_WIN64)
01590
if (
MI_DETERMINE_OWNER (PointerPte) == 0) {
01591 TempPte.
u.Long &= ~
MM_PTE_OWNER_MASK;
01592 }
01593
#else
01594
TempPte.
u.Hard.Owner =
MI_DETERMINE_OWNER (PointerPte);
01595
#endif
01596
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01597
01598 AddToWorkingSet =
TRUE;
01599
01600 UnlockAndCopy:
01601
01602
01603
01604
01605
01606
UNLOCK_PFN (OldIrql);
01607
01608
Copy:
01609
01610 Thread =
PsGetCurrentThread ();
01611
MmSavePageFaultReadAhead( Thread, &SavedState );
01612
MmSetPageFaultReadAhead( Thread, 0 );
01613 status = STATUS_SUCCESS;
01614
01615
01616
01617
01618
01619
try {
01620
01621
Buffer = (PVOID)((PCHAR)Address +
Offset);
01622 RtlCopyBytes (
Buffer, UserBuffer, CountInBytes);
01623
01624
if (TransitionState) {
01625
01626
01627
01628
01629
01630
01631
if (
Offset != 0) {
01632 RtlZeroMemory (Address,
Offset);
01633 }
01634
01635
if (DontZero ==
FALSE) {
01636 EndFill =
PAGE_SIZE - (
Offset + CountInBytes);
01637
01638
if (EndFill != 0) {
01639
Buffer = (PVOID)((PCHAR)
Buffer + CountInBytes);
01640 RtlZeroMemory (
Buffer, EndFill);
01641 }
01642 }
01643 }
01644 } except (
MiMapCacheExceptionFilter (&status, GetExceptionInformation())) {
01645
01646
if (status == STATUS_MULTIPLE_FAULT_VIOLATION) {
01647
ASSERT (TransitionState ==
TRUE);
01648 }
01649
01650
01651
01652
01653
01654
if (TransitionState) {
01655 RtlZeroMemory (Address,
PAGE_SIZE);
01656 }
01657 }
01658
01659
MmResetPageFaultReadAhead(Thread, SavedState);
01660
01661
if (AddToWorkingSet) {
01662
01663
LOCK_PFN (OldIrql);
01664
01665
if (ApcsExplicitlyBlocked ==
TRUE) {
01666
KeLeaveCriticalRegion();
01667 }
01668
01669
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
01670
ASSERT (Pfn1->
PteAddress == ProtoPte);
01671
01672
if (TransitionState) {
01673
01674
01675
01676
01677
01678
ASSERT (ShareCountUpped ==
FALSE);
01679
ASSERT (Pfn1->
u2.ShareCount <= 1);
01680
ASSERT (Pfn1->
u1.Event == &
Event->Event);
01681
01682
MiMakeSystemAddressValidPfn (ProtoPte);
01683
MI_SET_GLOBAL_STATE (TempPte, 0);
01684
MI_WRITE_VALID_PTE (ProtoPte, TempPte);
01685 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
01686
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
01687
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01688
01689
ASSERT (
Event->Completed ==
FALSE);
01690
Event->Completed =
TRUE;
01691
01692
ASSERT (Pfn1->
u2.ShareCount == 0);
01693
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 41);
01694 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
01695
01696
ASSERT (Pfn1->
u3.e1.ReadInProgress == 1);
01697 Pfn1->
u3.e1.ReadInProgress = 0;
01698
01699
01700
01701
01702
01703
01704 Pfn1->
u2.ShareCount += 1;
01705
01706
if (
Event->WaitCount != 1) {
01707
Event->IoStatus.Status = STATUS_SUCCESS;
01708
Event->IoStatus.Information = 0;
01709
KeSetEvent (&
Event->Event, 0,
FALSE);
01710 }
01711
01712
MiFreeInPageSupportBlock (
Event);
01713
if (DontZero !=
FALSE) {
01714
MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 40);
01715 Pfn1->
u3.e2.ReferenceCount += 1;
01716 status = STATUS_CACHE_PAGE_LOCKED;
01717 }
01718
01719
ASSERT (Thread->
NestedFaultCount <= 3);
01720
ASSERT (Thread->
NestedFaultCount != 0);
01721
01722 Thread->
NestedFaultCount -= 1;
01723
01724
if ((Thread->
ApcNeeded == 1) && (Thread->
NestedFaultCount == 0)) {
01725 ApcNeeded =
TRUE;
01726 Thread->
ApcNeeded = 0;
01727 }
01728
01729 }
else {
01730
01731
01732
01733
01734
01735
01736
01737
01738
ASSERT (ShareCountUpped ==
TRUE);
01739
01740
if (Pfn1->
u1.Event ==
NULL) {
01741 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread();
01742 }
01743 }
01744
01745
UNLOCK_PFN (OldIrql);
01746
01747
LOCK_SYSTEM_WS (OldIrql);
01748
01749 WorkingSetIndex =
MiLocateAndReserveWsle (&
MmSystemCacheWs);
01750
01751
MiUpdateWsle (&WorkingSetIndex,
01752
MiGetVirtualAddressMappedByPte (PointerPte),
01753
MmSystemCacheWorkingSetList,
01754 Pfn1);
01755
01756
MmSystemCacheWsle[WorkingSetIndex].
u1.e1.SameProtectAsProto = 1;
01757
01758
MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex);
01759
01760
UNLOCK_SYSTEM_WS (OldIrql);
01761
01762
if (ApcNeeded ==
TRUE) {
01763
ASSERT (OldIrql <
APC_LEVEL);
01764
ASSERT (Thread->
NestedFaultCount == 0);
01765
ASSERT (Thread->
ApcNeeded == 0);
01766
KeRaiseIrql (
APC_LEVEL, &OldIrql);
01767
IoRetryIrpCompletions ();
01768
KeLowerIrql (OldIrql);
01769 }
01770 }
01771
else {
01772
ASSERT (ApcsExplicitlyBlocked ==
FALSE);
01773 }
01774
01775
return status;
01776 }
01777
01778 LONG
01779 MiMapCacheExceptionFilter (
01780 IN PNTSTATUS Status,
01781 IN PEXCEPTION_POINTERS ExceptionPointer
01782 )
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807 {
01808
NTSTATUS local;
01809
01810 local = ExceptionPointer->ExceptionRecord->ExceptionCode;
01811
01812
01813
01814
01815
01816
01817
if (local == STATUS_IN_PAGE_ERROR) {
01818
if (ExceptionPointer->ExceptionRecord->NumberParameters >= 3) {
01819 local = (
NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
01820 }
01821 }
01822
01823
if (local == STATUS_ACCESS_VIOLATION) {
01824 local = STATUS_INVALID_USER_BUFFER;
01825 }
01826
01827 *
Status = local;
01828
return EXCEPTION_EXECUTE_HANDLER;
01829 }
01830
01831
01832
VOID
01833 MmUnlockCachedPage (
01834 IN PVOID AddressInCache
01835 )
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855 {
01856
PMMPTE PointerPte;
01857
PMMPFN Pfn1;
01858 KIRQL OldIrql;
01859
01860 PointerPte =
MiGetPteAddress (AddressInCache);
01861
01862
ASSERT (PointerPte->
u.Hard.Valid == 1);
01863 Pfn1 =
MI_PFN_ELEMENT (PointerPte->
u.Hard.PageFrameNumber);
01864
01865
LOCK_PFN (OldIrql);
01866
01867
if (Pfn1->
u3.e2.ReferenceCount <= 1) {
01868
KeBugCheckEx (MEMORY_MANAGEMENT,
01869 0x777,
01870 (ULONG_PTR)PointerPte->
u.Hard.PageFrameNumber,
01871 Pfn1->
u3.e2.ReferenceCount,
01872 (ULONG_PTR)AddressInCache);
01873
return;
01874 }
01875
01876
MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 25);
01877 Pfn1->
u3.e2.ReferenceCount -= 1;
01878
01879
UNLOCK_PFN (OldIrql);
01880
return;
01881 }