00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025
#if defined (_WIN64)
00026
00027
#include "wow64t.h"
00028
00029
#if !defined(_IA64_)
00030
#define MM_PROCESS_COMMIT_CHARGE 4
00031
00032
#define MM_PROCESS_CREATE_CHARGE 6
00033
#else
00034
#define MM_PROCESS_COMMIT_CHARGE 5
00035
00036
#define MM_PROCESS_CREATE_CHARGE 7
00037
#endif
00038
00039
#else
00040
00041
#if !defined (_X86PAE_)
00042 #define MM_PROCESS_COMMIT_CHARGE 3
00043 #define MM_PROCESS_CREATE_CHARGE 5
00044
#else
00045
#define MM_PROCESS_COMMIT_CHARGE 7
00046
#define MM_PROCESS_CREATE_CHARGE 9
00047
#define MM_HIGHEST_PAE_PAGE 0xFFFFF
00048
00049
#define PAES_PER_PAGE (PAGE_SIZE / sizeof(PAE_ENTRY))
00050
00051
#define MINIMUM_PAE_THRESHOLD (PAES_PER_PAGE * 4)
00052
#define EXCESS_PAE_THRESHOLD (PAES_PER_PAGE * 8)
00053
00054 PAE_ENTRY MiFirstFreePae;
00055 ULONG MiFreePaes;
00056
00057
00058
00059
00060
00061
#define MM_PAE_PDPTE_MASK 0x1e6
00062
00063 ULONG
00064 MiPaeAllocate (
00065 PPAE_ENTRY *
00066 );
00067
00068 PVOID
00069 MiPaeFree (
00070 PPAE_ENTRY Pae
00071 );
00072
00073
VOID
00074 MiPaeFreeEntirePage (
00075 PVOID VirtualAddress
00076 );
00077
00078
extern POOL_DESCRIPTOR NonPagedPoolDescriptor;
00079
00080
#endif
00081
00082
#endif
00083
00084 #define HEADER_FILE
00085
00086 extern ULONG
MmProductType;
00087
00088 extern ULONG
MmWorkingSetReductionMax;
00089
00090 extern MM_SYSTEMSIZE MmSystemSize;
00091
00092 extern PVOID
BBTBuffer;
00093
00094 SIZE_T
MmProcessCommit;
00095
00096 ULONG
MmKernelStackPages;
00097 PFN_NUMBER
MmKernelStackResident;
00098 ULONG
MmLargeStacks;
00099 ULONG
MmSmallStacks;
00100
00101 MMPTE KernelDemandZeroPte = {
MM_KERNEL_DEMAND_ZERO_PTE};
00102
00103 CCHAR
MmRotatingUniprocessorNumber;
00104
00105 extern ULONG
MiFaultRetries;
00106
00107 ULONG
00108
MiGetSystemPteListCount (
00109 IN ULONG ListSize
00110 );
00111
00112 PFN_NUMBER
00113
MiMakeOutswappedPageResident (
00114 IN
PMMPTE ActualPteAddress,
00115 IN
PMMPTE PointerTempPte,
00116 IN ULONG Global,
00117 IN PFN_NUMBER ContainingPage
00118 );
00119
00120 PVOID
00121
MiCreatePebOrTeb (
00122 IN
PEPROCESS TargetProcess,
00123 IN ULONG Size
00124 );
00125
00126
VOID
00127
MiDeleteAddressesInWorkingSet (
00128 IN
PEPROCESS Process
00129 );
00130
00131
VOID
00132
MiDeleteValidAddress (
00133 IN PVOID Va,
00134 IN
PEPROCESS CurrentProcess
00135 );
00136
00137
VOID
00138
MiDeleteFreeVm (
00139 IN PVOID StartingAddress,
00140 IN PVOID EndingAddress
00141 );
00142
00143
VOID
00144
VadTreeWalk (
00145 IN
PMMVAD Start
00146 );
00147
00148
PMMVAD
00149
MiAllocateVad(
00150 IN ULONG_PTR StartingVirtualAddress,
00151 IN ULONG_PTR EndingVirtualAddress,
00152 IN LOGICAL Deletable
00153 );
00154
00155 PVOID
00156
MiPaeReplenishList (
00157 VOID
00158 );
00159
00160 extern LOGICAL
MiNoLowMemory;
00161
00162 PVOID
00163
MiAllocateLowMemory (
00164 IN SIZE_T NumberOfBytes,
00165 IN PFN_NUMBER LowestAcceptablePfn,
00166 IN PFN_NUMBER HighestAcceptablePfn,
00167 IN PFN_NUMBER BoundaryPfn,
00168 IN PVOID CallingAddress,
00169 IN ULONG Tag
00170 );
00171
00172 LOGICAL
00173
MiFreeLowMemory (
00174 IN PVOID BaseAddress,
00175 IN ULONG Tag
00176 );
00177
00178
#ifdef ALLOC_PRAGMA
00179
#if defined (_X86PAE_)
00180
#pragma alloc_text(INIT,MiPaeInitialize)
00181
#endif
00182
#pragma alloc_text(PAGE,MmCreateTeb)
00183
#pragma alloc_text(PAGE,MmCreatePeb)
00184
#pragma alloc_text(PAGE,MiCreatePebOrTeb)
00185
#pragma alloc_text(PAGE,MmDeleteTeb)
00186
#endif
00187
00188
00189 BOOLEAN
00190 MmCreateProcessAddressSpace (
00191 IN ULONG MinimumWorkingSetSize,
00192 IN
PEPROCESS NewProcess,
00193 OUT PULONG_PTR DirectoryTableBase
00194 )
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 {
00228 PFN_NUMBER HyperDirectoryIndex;
00229 PFN_NUMBER PageDirectoryIndex;
00230
PMMPTE PointerPte;
00231
PMMPTE PointerPde;
00232
PMMPTE PointerPpe;
00233 PFN_NUMBER HyperSpaceIndex;
00234 PFN_NUMBER PageContainingWorkingSet;
00235
MMPTE TempPte;
00236
PMMPTE LastPte;
00237
PMMPTE PointerFillPte;
00238
PMMPTE CurrentAddressSpacePde;
00239
PEPROCESS CurrentProcess;
00240 KIRQL OldIrql;
00241
PMMPFN Pfn1;
00242 ULONG Color;
00243
#if defined (_X86PAE_)
00244
ULONG TopQuad;
00245
MMPTE TopPte;
00246 PPAE_ENTRY PaeVa;
00247 PFN_NUMBER PageDirectoryIndex2;
00248 KIRQL OldIrql2;
00249 ULONG i;
00250 PFN_NUMBER HyperSpaceIndex2;
00251 PVOID PoolBlock;
00252
#endif
00253
#if defined(_IA64_)
00254
PFN_NUMBER SessionParentIndex;
00255
#endif
00256
00257
00258
00259
00260
00261
00262 CurrentProcess =
PsGetCurrentProcess ();
00263
00264
00265
00266
00267
00268
00269
if (
MiChargeCommitment (
MM_PROCESS_COMMIT_CHARGE,
NULL) ==
FALSE) {
00270
return FALSE;
00271 }
00272
00273
MM_TRACK_COMMIT (
MM_DBG_COMMIT_PROCESS_CREATE,
MM_PROCESS_COMMIT_CHARGE);
00274
00275 NewProcess->NextPageColor = (
USHORT)(
RtlRandom(&
MmProcessColorSeed));
00276
KeInitializeSpinLock (&NewProcess->HyperSpaceLock);
00277
00278
#if defined (_X86PAE_)
00279
TopQuad = MiPaeAllocate (&PaeVa);
00280
if (TopQuad == 0) {
00281
MiReturnCommitment (
MM_PROCESS_COMMIT_CHARGE);
00282
return FALSE;
00283 }
00284
00285
00286
00287
00288
00289
ASSERT ((TopQuad >>
PAGE_SHIFT) <= MM_HIGHEST_PAE_PAGE);
00290
#endif
00291
00292
LOCK_WS (CurrentProcess);
00293
00294
LOCK_PFN (OldIrql);
00295
00296
00297
00298
00299
00300
if (
MmResidentAvailablePages <= (SPFN_NUMBER)MinimumWorkingSetSize) {
00301
00302
#if defined (_X86PAE_)
00303
PoolBlock = MiPaeFree (PaeVa);
00304
#endif
00305
00306
UNLOCK_PFN (OldIrql);
00307
UNLOCK_WS (CurrentProcess);
00308
MiReturnCommitment (
MM_PROCESS_COMMIT_CHARGE);
00309
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PROCESS_CREATE_FAILURE1,
MM_PROCESS_COMMIT_CHARGE);
00310
00311
#if defined (_X86PAE_)
00312
if (PoolBlock !=
NULL) {
00313 MiPaeFreeEntirePage (PoolBlock);
00314 }
00315
#endif
00316
00317
00318
00319
00320
return FALSE;
00321 }
00322
00323
MmResidentAvailablePages -= MinimumWorkingSetSize;
00324
MM_BUMP_COUNTER(6, MinimumWorkingSetSize);
00325
MmProcessCommit +=
MM_PROCESS_COMMIT_CHARGE;
00326
00327 NewProcess->AddressSpaceInitialized = 1;
00328 NewProcess->Vm.MinimumWorkingSetSize = MinimumWorkingSetSize;
00329
00330
00331
00332
00333
00334
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00335
00336 Color =
MI_PAGE_COLOR_PTE_PROCESS (PDE_BASE,
00337 &CurrentProcess->
NextPageColor);
00338
00339 PageDirectoryIndex =
MiRemoveZeroPageIfAny (Color);
00340
if (PageDirectoryIndex == 0) {
00341 PageDirectoryIndex =
MiRemoveAnyPage (Color);
00342
UNLOCK_PFN (OldIrql);
00343
MiZeroPhysicalPage (PageDirectoryIndex, Color);
00344
LOCK_PFN (OldIrql);
00345 }
00346
00347
#if defined (_X86PAE_)
00348
TempPte =
ValidPdePde;
00349
MI_SET_GLOBAL_STATE (TempPte, 0);
00350
00351
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
00352
00353
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00354
00355 Color =
MI_PAGE_COLOR_PTE_PROCESS (PDE_BASE,
00356 &CurrentProcess->
NextPageColor);
00357
00358 PageDirectoryIndex2 =
MiRemoveZeroPageIfAny (Color);
00359
if (PageDirectoryIndex2 == 0) {
00360 PageDirectoryIndex2 =
MiRemoveAnyPage (Color);
00361
UNLOCK_PFN (OldIrql);
00362
MiZeroPhysicalPage (PageDirectoryIndex2, Color);
00363
LOCK_PFN (OldIrql);
00364 }
00365
00366
00367
00368
00369
00370 TempPte.
u.Hard.PageFrameNumber = PageDirectoryIndex2;
00371 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageDirectoryIndex,
00372 &OldIrql2);
00373 PointerPte[i] = TempPte;
00374
MiUnmapPageInHyperSpace (OldIrql2);
00375 TopPte.
u.Long = TempPte.u.Long & ~MM_PAE_PDPTE_MASK;
00376 PaeVa->PteEntry[i].u.Long = TopPte.
u.Long;
00377 }
00378
00379
00380
00381
00382
00383 TempPte.
u.Hard.PageFrameNumber = PageDirectoryIndex;
00384 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageDirectoryIndex, &OldIrql2);
00385 PointerPte[PD_PER_SYSTEM - 1] = TempPte;
00386
MiUnmapPageInHyperSpace (OldIrql2);
00387 TopPte.
u.Long = TempPte.u.Long & ~MM_PAE_PDPTE_MASK;
00388 PaeVa->PteEntry[PD_PER_SYSTEM - 1].u.Long = TopPte.
u.Long;
00389 NewProcess->PaePageDirectoryPage = PageDirectoryIndex;
00390 NewProcess->PaeTop = (PVOID)PaeVa;
00391 DirectoryTableBase[0] = TopQuad;
00392
#else
00393
INITIALIZE_DIRECTORY_TABLE_BASE(&DirectoryTableBase[0], PageDirectoryIndex);
00394
#endif
00395
00396
#if defined (_WIN64)
00397
00398 PointerPpe = KSEG_ADDRESS (PageDirectoryIndex);
00399 TempPte =
ValidPdePde;
00400
00401
00402
00403
00404
00405 TempPte.
u.Hard.PageFrameNumber = PageDirectoryIndex;
00406
00407
#if defined (_AXP64_)
00408
ASSERT (TempPte.u.Hard.Global == 0);
00409 PointerPpe[
MiGetPpeOffset(PDE_TBASE)] = TempPte;
00410
#endif
00411
00412
#if defined(_IA64_)
00413
00414
00415
00416
00417
00418
00419 PointerPpe[(PDE_SELFMAP &
00420 ((
sizeof(
MMPTE)*
PTE_PER_PAGE) - 1))/
sizeof(
MMPTE)] = TempPte;
00421
00422
#endif
00423
00424
00425
00426
00427
00428
00429
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00430
00431 Color =
MI_PAGE_COLOR_PTE_PROCESS (
MiGetPpeAddress(
HYPER_SPACE),
00432 &CurrentProcess->
NextPageColor);
00433
00434 HyperDirectoryIndex =
MiRemoveZeroPageIfAny (Color);
00435
if (HyperDirectoryIndex == 0) {
00436 HyperDirectoryIndex =
MiRemoveAnyPage (Color);
00437
UNLOCK_PFN (OldIrql);
00438
MiZeroPhysicalPage (HyperDirectoryIndex, Color);
00439
LOCK_PFN (OldIrql);
00440 }
00441
00442 TempPte.u.Hard.PageFrameNumber = HyperDirectoryIndex;
00443 PointerPpe[
MiGetPpeOffset(
HYPER_SPACE)] = TempPte;
00444
00445
#if defined (_IA64_)
00446
00447
00448
00449
00450
00451
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00452
00453 Color =
MI_PAGE_COLOR_PTE_PROCESS (
MiGetPpeAddress(SESSION_SPACE_DEFAULT),
00454 &CurrentProcess->
NextPageColor);
00455
00456 SessionParentIndex =
MiRemoveZeroPageIfAny (Color);
00457
if (SessionParentIndex == 0) {
00458 SessionParentIndex =
MiRemoveAnyPage (Color);
00459
UNLOCK_PFN (OldIrql);
00460
MiZeroPhysicalPage (SessionParentIndex, Color);
00461
LOCK_PFN (OldIrql);
00462 }
00463
00464
INITIALIZE_DIRECTORY_TABLE_BASE(&NewProcess->Pcb.SessionParentBase, SessionParentIndex);
00465
00466 PointerPpe = KSEG_ADDRESS (SessionParentIndex);
00467
00468 TempPte.u.Hard.PageFrameNumber = SessionParentIndex;
00469
00470 PointerPpe[(PDE_SSELFMAP &
00471 ((
sizeof(
MMPTE)*
PTE_PER_PAGE) - 1))/
sizeof(
MMPTE)] = TempPte;
00472
00473
#endif // _IA64_
00474
00475
#endif
00476
00477
00478
00479
00480
00481
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00482
00483 Color =
MI_PAGE_COLOR_PTE_PROCESS (
MiGetPdeAddress(
HYPER_SPACE),
00484 &CurrentProcess->
NextPageColor);
00485
00486 HyperSpaceIndex =
MiRemoveZeroPageIfAny (Color);
00487
if (HyperSpaceIndex == 0) {
00488 HyperSpaceIndex =
MiRemoveAnyPage (Color);
00489
UNLOCK_PFN (OldIrql);
00490
MiZeroPhysicalPage (HyperSpaceIndex, Color);
00491
LOCK_PFN (OldIrql);
00492 }
00493
00494
#if defined (_WIN64)
00495
PointerPde = KSEG_ADDRESS (HyperDirectoryIndex);
00496 TempPte.u.Hard.PageFrameNumber = HyperSpaceIndex;
00497 PointerPde[
MiGetPdeOffset(
HYPER_SPACE)] = TempPte;
00498
#endif
00499
00500
#if defined (_X86PAE_)
00501
00502
00503
00504
00505
00506
00507
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00508
00509 Color =
MI_PAGE_COLOR_PTE_PROCESS (
MiGetPdeAddress(HYPER_SPACE2),
00510 &CurrentProcess->
NextPageColor);
00511
00512 HyperSpaceIndex2 =
MiRemoveZeroPageIfAny (Color);
00513
if (HyperSpaceIndex2 == 0) {
00514 HyperSpaceIndex2 =
MiRemoveAnyPage (Color);
00515
UNLOCK_PFN (OldIrql);
00516
MiZeroPhysicalPage (HyperSpaceIndex2, Color);
00517
LOCK_PFN (OldIrql);
00518 }
00519
00520
00521
00522
00523
00524
00525 DirectoryTableBase[1] = HyperSpaceIndex;
00526
#else
00527
INITIALIZE_DIRECTORY_TABLE_BASE(&DirectoryTableBase[1], HyperSpaceIndex);
00528
#endif
00529
00530
00531
00532
00533
00534
MiEnsureAvailablePageOrWait (CurrentProcess,
NULL);
00535
00536 Color =
MI_PAGE_COLOR_VA_PROCESS (
MmWorkingSetList,
00537 &CurrentProcess->
NextPageColor);
00538
00539 PageContainingWorkingSet =
MiRemoveZeroPageIfAny (Color);
00540
if (PageContainingWorkingSet == 0) {
00541 PageContainingWorkingSet =
MiRemoveAnyPage (Color);
00542
UNLOCK_PFN (OldIrql);
00543
MiZeroPhysicalPage (PageContainingWorkingSet, Color);
00544
LOCK_PFN (OldIrql);
00545 }
00546
00547
00548
00549
00550
00551
UNLOCK_PFN (OldIrql);
00552
00553 NewProcess->WorkingSetPage = PageContainingWorkingSet;
00554
00555
00556
00557
00558
00559
MI_INITIALIZE_HYPERSPACE_MAP (HyperSpaceIndex);
00560
00561
00562
00563
00564
00565
#if defined (_WIN64)
00566
00567 Pfn1 =
MI_PFN_ELEMENT (PageDirectoryIndex);
00568
00569
ASSERT (Pfn1->
u3.e1.PageColor == 0);
00570
00571
CONSISTENCY_LOCK_PFN (OldIrql);
00572
00573 Pfn1->
PteAddress =
MiGetPteAddress(PDE_TBASE);
00574
00575
CONSISTENCY_UNLOCK_PFN (OldIrql);
00576
00577
00578
00579
00580
00581 Pfn1 =
MI_PFN_ELEMENT (HyperDirectoryIndex);
00582
00583
ASSERT (Pfn1->
u3.e1.PageColor == 0);
00584
00585
CONSISTENCY_LOCK_PFN (OldIrql);
00586
00587 Pfn1->
PteAddress =
MiGetPpeAddress(
HYPER_SPACE);
00588
00589
CONSISTENCY_UNLOCK_PFN (OldIrql);
00590
00591
#if defined (_AXP64_)
00592
00593
00594
00595
00596
00597
MI_SET_GLOBAL_STATE (TempPte, 1);
00598
00599 PointerFillPte = &PointerPpe[
MiGetPpeOffset(
MM_SYSTEM_SPACE_START)];
00600 CurrentAddressSpacePde =
MiGetPpeAddress(
MM_SYSTEM_SPACE_START);
00601 RtlCopyMemory (PointerFillPte,
00602 CurrentAddressSpacePde,
00603 ((1 + (
MiGetPpeAddress(
MM_SYSTEM_SPACE_END) -
00604
MiGetPpeAddress(
MM_SYSTEM_SPACE_START))) *
sizeof(
MMPTE)));
00605
00606
00607
00608
00609
00610
if (
MiHydra ==
TRUE) {
00611
MI_SET_GLOBAL_STATE (TempPte, 0);
00612 }
00613
00614 PointerFillPte = &PointerPpe[
MiGetPpeOffset(
MM_SESSION_SPACE_DEFAULT)];
00615 CurrentAddressSpacePde =
MiGetPpeAddress(
MM_SESSION_SPACE_DEFAULT);
00616
MI_WRITE_VALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00617
00618
#endif
00619
00620
#if defined(_IA64_)
00621
if ((
MiHydra ==
TRUE) && (CurrentProcess->
Vm.
u.Flags.ProcessInSession != 0)) {
00622 PointerPpe = KSEG_ADDRESS(SessionParentIndex);
00623 PointerFillPte = &PointerPpe[
MiGetPpeOffset(
MM_SESSION_SPACE_DEFAULT)];
00624 CurrentAddressSpacePde =
MiGetPpeAddress(
MM_SESSION_SPACE_DEFAULT);
00625
MI_WRITE_VALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00626 }
00627
#endif
00628
00629
#else // the following is for !WIN64 only
00630
00631
#if defined (_X86PAE_)
00632
00633
00634
00635
00636
00637
00638 TempPte =
ValidPdePde;
00639 TempPte.
u.Hard.PageFrameNumber = HyperSpaceIndex2;
00640
MI_SET_GLOBAL_STATE (TempPte, 0);
00641
00642 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (HyperSpaceIndex, &OldIrql2);
00643 PointerPte[0] = TempPte;
00644
MiUnmapPageInHyperSpace (OldIrql2);
00645
00646
#endif
00647
00648
00649
00650
00651
00652 Pfn1 =
MI_PFN_ELEMENT (PageDirectoryIndex);
00653
00654
ASSERT (Pfn1->
u3.e1.PageColor == 0);
00655
00656
CONSISTENCY_LOCK_PFN (OldIrql);
00657
00658 Pfn1->
PteAddress = (
PMMPTE)PDE_BASE;
00659
00660
CONSISTENCY_UNLOCK_PFN (OldIrql);
00661
00662 TempPte =
ValidPdePde;
00663 TempPte.
u.Hard.PageFrameNumber = HyperSpaceIndex;
00664
MI_SET_GLOBAL_STATE (TempPte, 0);
00665
00666
00667
00668
00669
00670
00671 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageDirectoryIndex, &OldIrql);
00672 PointerPte[
MiGetPdeOffset(
HYPER_SPACE)] = TempPte;
00673
00674
#if defined (_X86PAE_)
00675
00676
00677
00678
00679
00680
00681 TempPte.
u.Hard.PageFrameNumber = HyperSpaceIndex2;
00682 PointerPte[
MiGetPdeOffset(HYPER_SPACE2)] = TempPte;
00683
00684
#else
00685
00686
00687
00688
00689
00690 TempPte.
u.Hard.PageFrameNumber = PageDirectoryIndex;
00691 PointerPte[
MiGetPdeOffset(PTE_BASE)] = TempPte;
00692
00693
#endif
00694
00695
00696
00697
00698
00699
#if defined(_ALPHA_)
00700
00701 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MM_SYSTEM_SPACE_START)];
00702 CurrentAddressSpacePde =
MiGetPdeAddress(
MM_SYSTEM_SPACE_START);
00703 RtlCopyMemory (PointerFillPte,
00704 CurrentAddressSpacePde,
00705 ((1 + (
MiGetPdeAddress(
MM_SYSTEM_SPACE_END) -
00706
MiGetPdeAddress(
MM_SYSTEM_SPACE_START))) *
sizeof(
MMPTE)));
00707
00708
00709
00710
00711
00712 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MM_KSEG0_BASE)];
00713 CurrentAddressSpacePde =
MiGetPdeAddress(
MM_KSEG0_BASE);
00714 RtlCopyMemory (PointerFillPte,
00715 CurrentAddressSpacePde,
00716
MiGetPdeOffset(
KSEG2_BASE-
KSEG0_BASE) *
sizeof(
MMPTE));
00717
00718
#else // the following is for x86 only
00719
00720
00721
00722
00723
00724
00725
#if defined (_X86PAE_)
00726
00727
00728
00729
00730
00731
00732
00733
if (
MmVirtualBias != 0) {
00734 PointerFillPte = &PointerPte[
MiGetPdeOffset(
CODE_START +
MmVirtualBias)];
00735 CurrentAddressSpacePde =
MiGetPdeAddress(
CODE_START +
MmVirtualBias);
00736
00737 RtlCopyMemory (PointerFillPte,
00738 CurrentAddressSpacePde,
00739 (((1 +
CODE_END) -
CODE_START) /
MM_VA_MAPPED_BY_PDE) *
sizeof(
MMPTE));
00740 }
00741
#else
00742
PointerFillPte = &PointerPte[
MiGetPdeOffset(
CODE_START +
MmVirtualBias)];
00743 CurrentAddressSpacePde =
MiGetPdeAddress(
CODE_START +
MmVirtualBias);
00744
00745 RtlCopyMemory (PointerFillPte,
00746 CurrentAddressSpacePde,
00747 (((1 +
CODE_END) -
CODE_START) /
MM_VA_MAPPED_BY_PDE) *
sizeof(
MMPTE));
00748
#endif
00749
00750 LastPte = &PointerPte[
MiGetPdeOffset(
NON_PAGED_SYSTEM_END)];
00751 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MmNonPagedSystemStart)];
00752 CurrentAddressSpacePde =
MiGetPdeAddress(
MmNonPagedSystemStart);
00753
00754 RtlCopyMemory (PointerFillPte,
00755 CurrentAddressSpacePde,
00756 ((1 + (
MiGetPdeAddress(
NON_PAGED_SYSTEM_END) -
00757 CurrentAddressSpacePde))) *
sizeof(
MMPTE));
00758
00759
00760
00761
00762
00763 LastPte = &PointerPte[
MiGetPdeOffset(
MmSystemCacheEnd)];
00764 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MM_SYSTEM_CACHE_WORKING_SET)];
00765 CurrentAddressSpacePde =
MiGetPdeAddress(
MM_SYSTEM_CACHE_WORKING_SET);
00766
00767 RtlCopyMemory (PointerFillPte,
00768 CurrentAddressSpacePde,
00769 ((1 + (
MiGetPdeAddress(
MmSystemCacheEnd) -
00770 CurrentAddressSpacePde))) *
sizeof(
MMPTE));
00771
00772
#if !defined (_X86PAE_)
00773
00774
00775
00776
00777
if (
MiSystemCacheEndExtra !=
MmSystemCacheEnd) {
00778 LastPte = &PointerPte[
MiGetPdeOffset(
MiSystemCacheEndExtra)];
00779 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MiSystemCacheStartExtra)];
00780 CurrentAddressSpacePde =
MiGetPdeAddress(
MiSystemCacheStartExtra);
00781
00782 RtlCopyMemory (PointerFillPte,
00783 CurrentAddressSpacePde,
00784 ((1 + (
MiGetPdeAddress(
MiSystemCacheEndExtra) -
00785 CurrentAddressSpacePde))) *
sizeof(
MMPTE));
00786 }
00787
#endif
00788
00789
#endif // end of x86 specific else
00790
00791
#if !defined (_X86PAE_)
00792
if (
MiHydra ==
TRUE) {
00793
00794
00795
00796
00797
00798
00799 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MmSessionSpace)];
00800 CurrentAddressSpacePde =
MiGetPdeAddress(
MmSessionSpace);
00801
if (CurrentAddressSpacePde->u.Hard.Valid == 1) {
00802
MI_WRITE_VALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00803 }
00804
else {
00805
MI_WRITE_INVALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00806 }
00807 }
00808
#endif
00809
00810
#if defined(_X86_)
00811
00812
00813
00814
00815
00816
#if !defined (_X86PAE_)
00817
if (
MiNumberOfExtraSystemPdes) {
00818
00819 PointerFillPte = &PointerPte[
MiGetPdeOffset(
KSTACK_POOL_START)];
00820 CurrentAddressSpacePde =
MiGetPdeAddress(
KSTACK_POOL_START);
00821
00822 RtlCopyMemory (PointerFillPte,
00823 CurrentAddressSpacePde,
00824
MiNumberOfExtraSystemPdes *
sizeof(
MMPTE));
00825 }
00826
#endif
00827
#endif
00828
00829
MiUnmapPageInHyperSpace (OldIrql);
00830
00831
#if defined (_X86PAE_)
00832
00833
00834
00835
00836
00837
if (
MmVirtualBias == 0) {
00838
00839 PageDirectoryIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PaeVa->PteEntry[PD_PER_SYSTEM - 2]);
00840
00841 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageDirectoryIndex, &OldIrql);
00842
00843 PointerFillPte = &PointerPte[
MiGetPdeOffset(
CODE_START)];
00844 CurrentAddressSpacePde =
MiGetPdeAddress(
CODE_START);
00845
00846 RtlCopyMemory (PointerFillPte,
00847 CurrentAddressSpacePde,
00848 (((1 +
CODE_END) -
CODE_START) /
MM_VA_MAPPED_BY_PDE) *
sizeof(
MMPTE));
00849
00850
if (
MiSystemCacheEndExtra !=
MmSystemCacheEnd) {
00851 LastPte = &PointerPte[
MiGetPdeOffset(
MiSystemCacheEndExtra)];
00852 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MiSystemCacheStartExtra)];
00853 CurrentAddressSpacePde =
MiGetPdeAddress(
MiSystemCacheStartExtra);
00854
00855 RtlCopyMemory (PointerFillPte,
00856 CurrentAddressSpacePde,
00857 ((1 + (
MiGetPdeAddress(
MiSystemCacheEndExtra) -
00858 CurrentAddressSpacePde))) *
sizeof(
MMPTE));
00859 }
00860
00861
if (
MiHydra ==
TRUE) {
00862
00863
00864
00865
00866
00867
00868 PointerFillPte = &PointerPte[
MiGetPdeOffset(
MmSessionSpace)];
00869 CurrentAddressSpacePde =
MiGetPdeAddress(
MmSessionSpace);
00870
if (CurrentAddressSpacePde->u.Hard.Valid == 1) {
00871
MI_WRITE_VALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00872 }
00873
else {
00874
MI_WRITE_INVALID_PTE (PointerFillPte, *CurrentAddressSpacePde);
00875 }
00876 }
00877
00878
if (
MiNumberOfExtraSystemPdes) {
00879
00880 PointerFillPte = &PointerPte[
MiGetPdeOffset(
KSTACK_POOL_START)];
00881 CurrentAddressSpacePde =
MiGetPdeAddress(
KSTACK_POOL_START);
00882
00883 RtlCopyMemory (PointerFillPte,
00884 CurrentAddressSpacePde,
00885
MiNumberOfExtraSystemPdes *
sizeof(
MMPTE));
00886 }
00887
MiUnmapPageInHyperSpace (OldIrql);
00888 }
00889
#endif
00890
00891
#endif // end of !WIN64 specific else
00892
00893
00894
00895
00896
00897
if (
MiHydra ==
TRUE) {
00898
MiSessionAddProcess (NewProcess);
00899 }
00900
00901
00902
00903
00904
00905
UNLOCK_WS (CurrentProcess);
00906
00907
return TRUE;
00908 }
00909
00910
NTSTATUS
00911 MmInitializeProcessAddressSpace (
00912 IN
PEPROCESS ProcessToInitialize,
00913 IN
PEPROCESS ProcessToClone OPTIONAL,
00914 IN PVOID SectionToMap OPTIONAL,
00915 OUT PUNICODE_STRING * AuditName OPTIONAL
00916 )
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 {
00955
PMMPTE PointerPte;
00956
MMPTE TempPte;
00957 PVOID BaseAddress;
00958 SIZE_T ViewSize;
00959 KIRQL OldIrql;
00960
NTSTATUS Status;
00961 PFN_NUMBER PpePhysicalPage;
00962 PFN_NUMBER PdePhysicalPage;
00963 PFN_NUMBER PageContainingWorkingSet;
00964 LARGE_INTEGER SectionOffset;
00965 PSECTION_IMAGE_INFORMATION ImageInfo;
00966
PMMVAD VadShare;
00967
PMMVAD VadReserve;
00968
PLOCK_HEADER LockedPagesHeader;
00969
#if defined (_X86PAE_)
00970
ULONG i;
00971 PFN_NUMBER PdePhysicalPage2;
00972
#endif
00973
#if defined (_WIN64)
00974
PWOW64_PROCESS Wow64Process;
00975
#endif
00976
00977
00978
00979
00980
00981
KeAttachProcess (&ProcessToInitialize->Pcb);
00982 ProcessToInitialize->AddressSpaceInitialized = 2;
00983
00984
ExInitializeFastMutex(&ProcessToInitialize->AddressCreationLock);
00985
00986
ExInitializeFastMutex(&ProcessToInitialize->WorkingSetLock);
00987
00988
00989
00990
00991
00992
00993
ASSERT (ProcessToInitialize->VadRoot ==
NULL);
00994
00995
KeQuerySystemTime(&ProcessToInitialize->Vm.LastTrimTime);
00996 ProcessToInitialize->Vm.VmWorkingSetList =
MmWorkingSetList;
00997
00998
00999
01000
01001
01002
01003
LOCK_PFN (OldIrql);
01004
01005
01006
01007
01008
01009
01010
#if defined (_WIN64)
01011
01012 PointerPte =
MiGetPteAddress (PDE_TBASE);
01013 PpePhysicalPage =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
01014
01015
MiInitializePfn (PpePhysicalPage, PointerPte, 1);
01016
01017 PointerPte =
MiGetPpeAddress (
HYPER_SPACE);
01018
MiInitializePfn (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte), PointerPte, 1);
01019
01020
#if defined(_IA64_)
01021
PointerPte =
MiGetPteAddress (PDE_STBASE);
01022
MiInitializePfn (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte), PointerPte, 1);
01023
#endif
01024
01025
#else
01026
01027
#if defined (_X86PAE_)
01028
PointerPte =
MiGetPdeAddress (PDE_BASE);
01029
#else
01030
PointerPte =
MiGetPteAddress (PDE_BASE);
01031
#endif
01032
PdePhysicalPage =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
01033
01034
MiInitializePfn (PdePhysicalPage, PointerPte, 1);
01035
01036
#endif
01037
01038 PointerPte =
MiGetPdeAddress (
HYPER_SPACE);
01039
MiInitializePfn (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte), PointerPte, 1);
01040
01041
#if defined (_X86PAE_)
01042
01043
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
01044 PointerPte =
MiGetPteAddress (PDE_BASE + (i <<
PAGE_SHIFT));
01045 PdePhysicalPage2 =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
01046
MiInitializePfn (PdePhysicalPage2, PointerPte, 1);
01047 }
01048
01049 PointerPte =
MiGetPdeAddress (HYPER_SPACE2);
01050
MiInitializePfn (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte), PointerPte, 1);
01051
#endif
01052
01053 PageContainingWorkingSet = ProcessToInitialize->WorkingSetPage;
01054
01055 PointerPte =
MiGetPteAddress (
MmWorkingSetList);
01056 PointerPte->u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
01057
01058
MiInitializePfn (PageContainingWorkingSet, PointerPte, 1);
01059
01060
UNLOCK_PFN (OldIrql);
01061
01062
MI_MAKE_VALID_PTE (TempPte,
01063 PageContainingWorkingSet,
01064
MM_READWRITE,
01065 PointerPte );
01066
01067
MI_SET_PTE_DIRTY (TempPte);
01068
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01069
01070
ASSERT (ProcessToInitialize->LockedPagesList ==
NULL);
01071
01072
if (
MmTrackLockedPages ==
TRUE) {
01073 LockedPagesHeader =
ExAllocatePoolWithTag (
NonPagedPool,
01074
sizeof(
LOCK_HEADER),
01075 'xTmM');
01076
01077
if (LockedPagesHeader) {
01078 RtlZeroMemory (LockedPagesHeader,
sizeof(
LOCK_HEADER));
01079 ProcessToInitialize->LockedPagesList = (PVOID)LockedPagesHeader;
01080 InitializeListHead (&LockedPagesHeader->
ListHead);
01081 }
01082 }
01083
01084
MiInitializeWorkingSetList (ProcessToInitialize);
01085
01086
KeInitializeSpinLock (&ProcessToInitialize->AweLock);
01087 InitializeListHead (&ProcessToInitialize->PhysicalVadList);
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
#if defined(_X86_) && defined(MM_SHARED_USER_DATA_VA)
01098
01099
if ((
MmVirtualBias != 0) && (ProcessToClone ==
NULL)) {
01100
01101
01102
01103
01104
01105
01106
01107 VadShare =
MiAllocateVad (MM_SHARED_USER_DATA_VA,
01108 MM_SHARED_USER_DATA_VA,
01109
FALSE);
01110
01111
if (VadShare ==
NULL) {
01112
KeDetachProcess ();
01113
return STATUS_NO_MEMORY;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
if (SectionToMap !=
NULL) {
01123
if (!((
PSECTION)SectionToMap)->u.Flags.Image) {
01124
KeDetachProcess ();
01125
ExFreePool (VadShare);
01126
return STATUS_SECTION_NOT_IMAGE;
01127 }
01128 ImageInfo = ((
PSECTION)SectionToMap)->Segment->ImageInformation;
01129
if ((
ExVerifySuite(Enterprise) ==
FALSE) ||
01130 ((ImageInfo->ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) == 0)) {
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 VadReserve =
MiAllocateVad (
_2gb,
01141 (ULONG_PTR)MM_HIGHEST_USER_ADDRESS,
01142
FALSE);
01143
01144
if (VadReserve ==
NULL) {
01145
KeDetachProcess ();
01146
ExFreePool (VadShare);
01147
return STATUS_NO_MEMORY;
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
MiInsertVad (VadReserve);
01157 }
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
MiInsertVad (VadShare);
01167 }
01168
01169
#endif
01170
01171
#if defined(_WIN64)
01172
01173
if (ProcessToClone ==
NULL) {
01174
01175
01176
01177
01178
01179
01180
01181
ASSERT(
MiCheckForConflictingVad(WOW64_COMPATIBILITY_AREA_ADDRESS, MM_SHARED_USER_DATA_VA) ==
NULL);
01182
01183 VadShare =
MiAllocateVad (WOW64_COMPATIBILITY_AREA_ADDRESS,
01184 MM_SHARED_USER_DATA_VA,
01185
TRUE);
01186
01187
if (VadShare ==
NULL) {
01188
KeDetachProcess ();
01189
return STATUS_NO_MEMORY;
01190 }
01191
01192
01193
01194
01195
01196
01197
if (SectionToMap !=
NULL) {
01198
if (!((
PSECTION)SectionToMap)->u.Flags.Image) {
01199
KeDetachProcess ();
01200
ExFreePool (VadShare);
01201
return STATUS_SECTION_NOT_IMAGE;
01202 }
01203 ImageInfo = ((
PSECTION)SectionToMap)->Segment->ImageInformation;
01204
01205
if ((ImageInfo->ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) == 0 ||
01206
#if defined(_AXP64_)
01207
ImageInfo->Machine == IMAGE_FILE_MACHINE_ALPHA ||
01208
#endif
01209
ImageInfo->Machine == IMAGE_FILE_MACHINE_I386) {
01210
01211
01212
01213
01214
01215
01216
01217
01218 VadReserve =
MiAllocateVad (
_2gb,
01219 (ULONG_PTR)MM_HIGHEST_USER_ADDRESS,
01220
TRUE);
01221
01222
if (VadReserve ==
NULL) {
01223
KeDetachProcess ();
01224
ExFreePool (VadShare);
01225
return STATUS_NO_MEMORY;
01226 }
01227
01228
01229
01230
01231
01232
01233
01234
MiInsertVad (VadReserve);
01235
01236
01237
01238
01239
01240 Wow64Process =
01241 (
PWOW64_PROCESS)
ExAllocatePoolWithTag (
NonPagedPool,
01242
sizeof(
WOW64_PROCESS),
01243 'WowM');
01244
01245
if (Wow64Process == (
PWOW64_PROCESS)
NULL) {
01246
KeDetachProcess ();
01247
return STATUS_NO_MEMORY;
01248 }
01249
01250 RtlZeroMemory(Wow64Process,
sizeof(
WOW64_PROCESS));
01251
01252 ProcessToInitialize->Wow64Process = Wow64Process;
01253
01254
#if defined(_MIALT4K_)
01255
01256
01257
01258
01259
01260
Status =
MiInitializeAlternateTable (ProcessToInitialize);
01261
if (
Status != STATUS_SUCCESS) {
01262
KeDetachProcess ();
01263
return Status;
01264 }
01265
01266
#endif
01267
}
01268 }
01269
01270
01271
01272
01273
01274
01275
01276
MiInsertVad (VadShare);
01277 }
01278
01279
#endif
01280
01281
if (SectionToMap != (
PSECTION)
NULL) {
01282
01283
01284
01285
01286
01287
01288
if (!((
PSECTION)SectionToMap)->u.Flags.Image) {
01289
Status = STATUS_SECTION_NOT_IMAGE;
01290 }
else {
01291 UNICODE_STRING UnicodeString;
01292 ULONG
n;
01293 PWSTR Src;
01294 PCHAR Dst;
01295
01296 UnicodeString = ((
PSECTION)SectionToMap)->Segment->ControlArea->FilePointer->FileName;
01297 Src = (PWSTR)((PCHAR)UnicodeString.Buffer + UnicodeString.Length);
01298
n = 0;
01299
if (UnicodeString.Buffer !=
NULL) {
01300
while (Src > UnicodeString.Buffer) {
01301
if (*--Src == OBJ_NAME_PATH_SEPARATOR) {
01302 Src += 1;
01303
break;
01304 }
01305
else {
01306
n += 1;
01307 }
01308 }
01309 }
01310 Dst = ProcessToInitialize->ImageFileName;
01311
if (
n >=
sizeof( ProcessToInitialize->ImageFileName )) {
01312
n =
sizeof( ProcessToInitialize->ImageFileName ) - 1;
01313 }
01314
01315
while (
n--) {
01316 *Dst++ = (UCHAR)*Src++;
01317 }
01318 *Dst =
'\0';
01319
01320
if (AuditName) {
01321 *AuditName = &((
PSECTION)SectionToMap)->Segment->ControlArea->FilePointer->FileName ;
01322 }
01323
01324 ProcessToInitialize->SubSystemMajorVersion =
01325 (UCHAR)((
PSECTION)SectionToMap)->Segment->ImageInformation->SubSystemMajorVersion;
01326 ProcessToInitialize->SubSystemMinorVersion =
01327 (UCHAR)((
PSECTION)SectionToMap)->Segment->ImageInformation->SubSystemMinorVersion;
01328
01329 BaseAddress =
NULL;
01330 ViewSize = 0;
01331
ZERO_LARGE (SectionOffset);
01332
01333
Status =
MmMapViewOfSection ( (
PSECTION)SectionToMap,
01334 ProcessToInitialize,
01335 &BaseAddress,
01336 0,
01337 0,
01338 &SectionOffset,
01339 &ViewSize,
01340 ViewShare,
01341 0,
01342 PAGE_READWRITE
01343 );
01344
01345 ProcessToInitialize->SectionBaseAddress = BaseAddress;
01346
01347
#if DBG
01348
if (MmDebug &
MM_DBG_PTE_UPDATE) {
01349
DbgPrint(
"mapped image section vads\n");
01350
VadTreeWalk(ProcessToInitialize->VadRoot);
01351 }
01352
#endif //DBG
01353
}
01354
01355
KeDetachProcess ();
01356
return Status;
01357 }
01358
01359
if (ProcessToClone != (
PEPROCESS)
NULL) {
01360
#if DEVL
01361
strcpy( ProcessToInitialize->ImageFileName, ProcessToClone->ImageFileName );
01362
#endif // DEVL
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
KeDetachProcess ();
01377
return MiCloneProcessAddressSpace (ProcessToClone,
01378 ProcessToInitialize,
01379 #
if defined (_WIN64)
01380 PpePhysicalPage,
01381 #
else
01382 PdePhysicalPage,
01383 #endif
01384 PageContainingWorkingSet
01385 );
01386
01387 }
01388
01389
01390
01391
01392
01393
KeDetachProcess ();
01394
return STATUS_SUCCESS;
01395 }
01396
01397
VOID
01398 MmDeleteProcessAddressSpace (
01399 IN
PEPROCESS Process
01400 )
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 {
01423
PMMPFN Pfn1;
01424 KIRQL OldIrql;
01425 PFN_NUMBER PageFrameIndex;
01426 PFN_NUMBER PageFrameIndex2;
01427
#if defined (_WIN64)
01428
PMMPTE PageDirectoryParent;
01429
PMMPTE Ppe;
01430
#endif
01431
#if defined (_X86PAE_)
01432
ULONG i;
01433 KIRQL OldIrql2;
01434
PMMPTE PointerPte;
01435 PVOID PoolBlock;
01436 PFN_NUMBER PageDirectories[PD_PER_SYSTEM];
01437
01438 PoolBlock =
NULL;
01439
#endif
01440
01441
01442
01443
01444
01445
MiReturnCommitment (
MM_PROCESS_COMMIT_CHARGE);
01446
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PROCESS_DELETE,
MM_PROCESS_COMMIT_CHARGE);
01447
ASSERT (Process->CommitCharge == 0);
01448
01449
01450
01451
01452
01453 Pfn1 =
MI_PFN_ELEMENT (Process->WorkingSetPage);
01454
01455
LOCK_PFN (OldIrql);
01456
MmProcessCommit -=
MM_PROCESS_COMMIT_CHARGE;
01457
01458
if (Process->AddressSpaceInitialized == 2) {
01459
01460
MI_SET_PFN_DELETED (Pfn1);
01461
01462
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01463
MiDecrementShareCountOnly (Process->WorkingSetPage);
01464
01465
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01466
01467
01468
01469
01470
01471
#if defined (_X86PAE_)
01472
01473 PageFrameIndex = (PFN_NUMBER)Process->Pcb.DirectoryTableBase[1];
01474
01475
01476
01477
01478 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql2);
01479 PageFrameIndex2 =
MI_GET_PAGE_FRAME_FROM_PTE(PointerPte);
01480
MiUnmapPageInHyperSpace (OldIrql2);
01481
01482 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex2);
01483
01484
MI_SET_PFN_DELETED (Pfn1);
01485
01486
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01487
MiDecrementShareCountOnly (PageFrameIndex2);
01488
01489
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01490
#else
01491
PageFrameIndex =
01492
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(Process->Pcb.DirectoryTableBase[1])));
01493
#endif
01494
01495 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01496
01497
MI_SET_PFN_DELETED (Pfn1);
01498
01499
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01500
MiDecrementShareCountOnly (PageFrameIndex);
01501
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01502
01503
01504
01505
01506
01507 PageFrameIndex =
MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process);
01508
01509
#if defined (_X86PAE_)
01510
01511 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql2);
01512
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
01513 PageDirectories[i] =
MI_GET_PAGE_FRAME_FROM_PTE(&PointerPte[i]);
01514 }
01515
MiUnmapPageInHyperSpace (OldIrql2);
01516
01517
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
01518 Pfn1 =
MI_PFN_ELEMENT (PageDirectories[i]);
01519
01520
MI_SET_PFN_DELETED (Pfn1);
01521
01522
MiDecrementShareAndValidCount (PageDirectories[i]);
01523
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01524
01525
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01526 }
01527
#endif
01528
01529
#if defined (_WIN64)
01530
01531
01532
01533
01534
01535
01536 PageDirectoryParent = KSEG_ADDRESS (PageFrameIndex);
01537
01538
01539
01540
01541
01542 Ppe = &PageDirectoryParent[
MiGetPpeOffset(
HYPER_SPACE)];
01543 PageFrameIndex2 =
MI_GET_PAGE_FRAME_FROM_PTE(Ppe);
01544 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex2);
01545
01546
MI_SET_PFN_DELETED (Pfn1);
01547
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01548
MiDecrementShareCountOnly (PageFrameIndex2);
01549
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01550
#endif
01551
01552 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01553
01554
MI_SET_PFN_DELETED (Pfn1);
01555
01556
MiDecrementShareAndValidCount (PageFrameIndex);
01557
01558
MiDecrementShareCountOnly (PageFrameIndex);
01559
01560
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01561
01562
#if defined (_X86PAE_)
01563
01564
01565
01566
01567
01568 PoolBlock = MiPaeFree ((PPAE_ENTRY)Process->PaeTop);
01569
#endif
01570
01571
#if defined(_IA64_)
01572
01573
01574
01575
01576
01577 PageFrameIndex =
01578
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(Process->Pcb.SessionParentBase)));
01579
01580 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01581
01582
MI_SET_PFN_DELETED (Pfn1);
01583
01584
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01585
01586
MiDecrementShareCountOnly (PageFrameIndex);
01587
01588
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) || (Pfn1->
u3.e1.WriteInProgress));
01589
01590
#endif
01591
01592 }
else {
01593
01594
01595
01596
01597
01598
01599
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01600 Process->WorkingSetPage);
01601
01602
#if defined (_WIN64)
01603
01604
01605
01606
01607
01608
01609 PageFrameIndex =
01610
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(Process->Pcb.DirectoryTableBase[0])));
01611
01612 PageDirectoryParent = KSEG_ADDRESS (PageFrameIndex);
01613
01614 Ppe = &PageDirectoryParent[
MiGetPpeOffset(
HYPER_SPACE)];
01615 PageFrameIndex2 =
MI_GET_PAGE_FRAME_FROM_PTE(Ppe);
01616
01617
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01618 PageFrameIndex2);
01619
#endif
01620
01621
#if defined (_X86PAE_)
01622
PageFrameIndex =
MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process);
01623
01624 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql2);
01625
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
01626 PageDirectories[i] =
MI_GET_PAGE_FRAME_FROM_PTE(&PointerPte[i]);
01627 }
01628
MiUnmapPageInHyperSpace (OldIrql2);
01629
01630
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
01631
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01632 PageDirectories[i]);
01633 }
01634
01635
01636
01637
01638
01639 PageFrameIndex = (PFN_NUMBER)Process->Pcb.DirectoryTableBase[1];
01640
01641 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql2);
01642 PageFrameIndex2 =
MI_GET_PAGE_FRAME_FROM_PTE(PointerPte);
01643
MiUnmapPageInHyperSpace (OldIrql2);
01644
MiInsertPageInList (
MmPageLocationList[
FreePageList], PageFrameIndex2);
01645
01646
01647
01648
01649
01650
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01651 (PFN_NUMBER)Process->Pcb.DirectoryTableBase[1]);
01652
01653
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01654
MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process));
01655
01656
01657
01658
01659
01660 PoolBlock = MiPaeFree ((PPAE_ENTRY)Process->PaeTop);
01661
#else
01662
01663
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01664
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(Process->Pcb.DirectoryTableBase[1]))));
01665
01666
MiInsertPageInList (
MmPageLocationList[
FreePageList],
01667
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(Process->Pcb.DirectoryTableBase[0]))));
01668
#endif
01669
#if defined(_IA64_)
01670
MiInsertPageInList (
MmPageLocationList[
FreePageList], Process->Pcb.SessionParentBase);
01671
#endif
01672
}
01673
01674
MmResidentAvailablePages +=
MM_PROCESS_CREATE_CHARGE;
01675
MM_BUMP_COUNTER(7,
MM_PROCESS_CREATE_CHARGE);
01676
01677
UNLOCK_PFN (OldIrql);
01678
01679
#if defined (_X86PAE_)
01680
if (PoolBlock !=
NULL) {
01681 MiPaeFreeEntirePage (PoolBlock);
01682 }
01683
#endif
01684
01685
01686
01687
01688
01689
MiContractPagingFiles ();
01690
01691
return;
01692 }
01693
01694
VOID
01695 MmCleanProcessAddressSpace (
01696 )
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721 {
01722
PEPROCESS Process;
01723
PMMVAD Vad;
01724
KEVENT Event;
01725 KIRQL OldIrql;
01726
#if defined(_ALPHA_) && !defined(_AXP64_)
01727
KIRQL OldIrql2;
01728
#endif
01729
PMMPTE LastPte;
01730
PMMPTE PointerPte;
01731
PMMPTE PointerPde;
01732
PMMPTE PointerPpe;
01733
PMMPFN Pfn1;
01734 PVOID TempVa;
01735 LONG AboveWsMin;
01736
MMPTE_FLUSH_LIST PteFlushList;
01737
01738 PteFlushList.
Count = 0;
01739 Process =
PsGetCurrentProcess();
01740
if ((Process->
AddressSpaceDeleted != 0) ||
01741 (Process->
AddressSpaceInitialized == 0)) {
01742
01743
01744
01745
01746
01747
01748
if (
MiHydra ==
TRUE) {
01749
MiSessionRemoveProcess ();
01750 }
01751
01752
return;
01753 }
01754
01755
if (Process->
AddressSpaceInitialized == 1) {
01756
01757
01758
01759
01760
01761
01762
MmResidentAvailablePages += (Process->
Vm.
MinimumWorkingSetSize -
01763
MM_PROCESS_CREATE_CHARGE);
01764
01765
MM_BUMP_COUNTER(41, Process->
Vm.
MinimumWorkingSetSize -
01766
MM_PROCESS_CREATE_CHARGE);
01767
01768
01769
01770
01771
01772
01773
if (
MiHydra ==
TRUE) {
01774
MiSessionRemoveProcess ();
01775 }
01776
01777
return;
01778 }
01779
01780
01781
01782
01783
01784
01785
01786
LOCK_EXPANSION (OldIrql);
01787
01788
if (Process->
Vm.
u.Flags.BeingTrimmed) {
01789
01790
01791
01792
01793
01794
01795
01796
KeInitializeEvent(&
Event, NotificationEvent,
FALSE);
01797
01798 Process->
Vm.
WorkingSetExpansionLinks.Blink = (PLIST_ENTRY)&
Event;
01799
01800
01801
01802
01803
01804
KeEnterCriticalRegion();
01805
UNLOCK_EXPANSION_AND_THEN_WAIT (OldIrql);
01806
01807
KeWaitForSingleObject(&
Event,
01808
WrVirtualMemory,
01809
KernelMode,
01810
FALSE,
01811 (PLARGE_INTEGER)
NULL);
01812
KeLeaveCriticalRegion();
01813 }
01814
else if (Process->
Vm.
WorkingSetExpansionLinks.Flink ==
MM_NO_WS_EXPANSION) {
01815
01816
01817
01818
01819
01820
01821
ASSERT (Process->
Vm.
WorkingSetExpansionLinks.Blink !=
MM_WS_EXPANSION_IN_PROGRESS);
01822
01823
UNLOCK_EXPANSION (OldIrql);
01824 }
else {
01825
01826 RemoveEntryList (&Process->
Vm.
WorkingSetExpansionLinks);
01827
01828
01829
01830
01831
01832 Process->
Vm.
WorkingSetExpansionLinks.Flink =
MM_NO_WS_EXPANSION;
01833
01834
01835
01836
01837
01838
UNLOCK_EXPANSION (OldIrql);
01839 }
01840
01841
if (
MiHydra ==
TRUE) {
01842
MiSessionRemoveProcess ();
01843 }
01844
01845
01846
01847
01848
01849
LOCK_WS_AND_ADDRESS_SPACE (Process);
01850
01851
01852
01853
01854
01855
01856
MiLockSystemSpace(OldIrql);
01857 Process->
AddressSpaceDeleted = 1;
01858
if ( Process->
VmOperation != 0) {
01859
01860
01861
01862
01863
01864
01865
01866
KeInitializeEvent(&
Event, NotificationEvent,
FALSE);
01867 Process->
VmOperationEvent = &
Event;
01868
01869
do {
01870
01871
MiUnlockSystemSpace(OldIrql);
01872
01873
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
01874
KeWaitForSingleObject(&
Event,
01875
WrVirtualMemory,
01876
KernelMode,
01877
FALSE,
01878 (PLARGE_INTEGER)
NULL);
01879
01880
LOCK_WS_AND_ADDRESS_SPACE (Process);
01881
01882
01883
01884
01885
01886
01887
MiLockSystemSpace(OldIrql);
01888
01889 }
while (Process->
VmOperation != 0);
01890
01891
MiUnlockSystemSpace(OldIrql);
01892
01893 }
else {
01894
MiUnlockSystemSpace(OldIrql);
01895 }
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
MiDeleteAddressesInWorkingSet (Process);
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 PointerPte =
MiGetPteAddress (&
MmWsle[
MM_MAXIMUM_WORKING_SET]) + 1;
01919 LastPte =
MiGetPteAddress (
MmWorkingSetList->
HighestPermittedHashAddress);
01920
01921
#if defined (_WIN64)
01922
PointerPpe =
MiGetPdeAddress (PointerPte);
01923 PointerPde =
MiGetPteAddress (PointerPte);
01924
01925
if ((PointerPpe->
u.Hard.Valid == 1) &&
01926 (PointerPde->
u.Hard.Valid == 1) &&
01927 (PointerPte->
u.Hard.Valid == 1)) {
01928
01929 PteFlushList.
Count = 0;
01930
LOCK_PFN (OldIrql);
01931
while (PointerPte->
u.Hard.Valid) {
01932 TempVa =
MiGetVirtualAddressMappedByPte(PointerPte);
01933
MiDeletePte (PointerPte,
01934 TempVa,
01935
FALSE,
01936 Process,
01937
NULL,
01938 &PteFlushList);
01939
01940 PointerPte += 1;
01941 Process->
NumberOfPrivatePages += 1;
01942
01943
01944
01945
01946
01947
01948
01949
if ((
MiIsPteOnPdeBoundary(PointerPte)) ||
01950 ((
MiGetPdeAddress(PointerPte))->u.Hard.Valid == 0) ||
01951 ((
MiGetPteAddress(PointerPte))->u.Hard.Valid == 0) ||
01952 (PointerPte->
u.Hard.Valid == 0)) {
01953
01954
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
01955
01956 PointerPde =
MiGetPteAddress (PointerPte - 1);
01957
01958
ASSERT (PointerPde->
u.Hard.Valid == 1);
01959
01960 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
01961
01962
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
01963 {
01964
MiDeletePte (PointerPde,
01965 PointerPte - 1,
01966
FALSE,
01967 Process,
01968
NULL,
01969
NULL);
01970 Process->
NumberOfPrivatePages += 1;
01971 }
01972
01973
if (
MiIsPteOnPpeBoundary(PointerPte)) {
01974
01975 PointerPpe =
MiGetPteAddress (PointerPde);
01976
01977
ASSERT (PointerPpe->
u.Hard.Valid == 1);
01978
01979 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe));
01980
01981
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
01982 {
01983
MiDeletePte (PointerPpe,
01984 PointerPde,
01985
FALSE,
01986 Process,
01987
NULL,
01988
NULL);
01989 Process->
NumberOfPrivatePages += 1;
01990 }
01991 }
01992 PointerPde =
MiGetPteAddress (PointerPte);
01993 PointerPpe =
MiGetPdeAddress (PointerPte);
01994
if ((PointerPpe->
u.Hard.Valid == 0) ||
01995 (PointerPde->u.Hard.Valid == 0)) {
01996
break;
01997 }
01998 }
01999 }
02000
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
02001
UNLOCK_PFN (OldIrql);
02002 }
02003
#else
02004
if (PointerPte->
u.Hard.Valid) {
02005 PteFlushList.
Count = 0;
02006
LOCK_PFN (OldIrql);
02007
while ((PointerPte < LastPte) && (PointerPte->
u.Hard.Valid)) {
02008 TempVa =
MiGetVirtualAddressMappedByPte(PointerPte);
02009
MiDeletePte (PointerPte,
02010 TempVa,
02011
FALSE,
02012 Process,
02013
NULL,
02014 &PteFlushList);
02015
02016 PointerPte += 1;
02017 Process->
NumberOfPrivatePages += 1;
02018 }
02019
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
02020
UNLOCK_PFN (OldIrql);
02021 }
02022
#endif
02023
02024
02025
02026
02027
02028
02029
02030
02031
MmWorkingSetList->
HashTableSize = 0;
02032
MmWorkingSetList->
HashTable =
NULL;
02033
02034
02035
02036
02037
02038
02039 Vad = Process->
VadRoot;
02040
02041
while (Vad != (
PMMVAD)
NULL) {
02042
02043
MiRemoveVad (Vad);
02044
02045
02046
02047
02048
02049
02050
02051
#if defined(_X86_) && defined(MM_SHARED_USER_DATA_VA)
02052
02053
if (
MmVirtualBias != 0) {
02054
02055
02056
02057
02058
02059
02060
if (Vad->
StartingVpn ==
MI_VA_TO_VPN (MM_SHARED_USER_DATA_VA)) {
02061
goto LoopEnd;
02062 }
02063 }
02064
#endif
02065
02066
if (((Vad->
u.VadFlags.PrivateMemory == 0) &&
02067 (Vad->
ControlArea !=
NULL)) ||
02068 (Vad->
u.VadFlags.PhysicalMapping == 1)) {
02069
02070
02071
02072
02073
02074
02075
02076
MiRemoveMappedView (Process, Vad);
02077
02078 }
else {
02079
02080
if (Vad->
u.VadFlags.UserPhysicalPages == 1) {
02081
02082
02083
02084
02085
02086
02087
02088
MiPhysicalViewRemover (Process, Vad);
02089
02090
MiRemoveUserPhysicalPagesVad ((
PMMVAD_SHORT)Vad);
02091
02092
MiDeletePageTablesForPhysicalRange (
02093
MI_VPN_TO_VA (Vad->
StartingVpn),
02094
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn));
02095 }
02096
else {
02097
02098
if (Vad->
u.VadFlags.WriteWatch == 1) {
02099
MiPhysicalViewRemover (Process, Vad);
02100 }
02101
02102
LOCK_PFN (OldIrql);
02103
02104
02105
02106
02107
02108
02109
02110
MiDeleteVirtualAddresses (
MI_VPN_TO_VA (Vad->
StartingVpn),
02111
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn),
02112
FALSE,
02113 Vad);
02114
02115
UNLOCK_PFN (OldIrql);
02116 }
02117 }
02118
02119
#if defined(_X86_) && defined(MM_SHARED_USER_DATA_VA)
02120
LoopEnd:
02121
#endif
02122
02123
ExFreePool (Vad);
02124 Vad = Process->
VadRoot;
02125 }
02126
02127
ASSERT (IsListEmpty (&Process->
PhysicalVadList) != 0);
02128
02129
MiCleanPhysicalProcessPages (Process);
02130
02131
02132
02133
02134
02135
LOCK_PFN (OldIrql);
02136
02137
#if defined(MM_SHARED_USER_DATA_VA)
02138
MiDeleteVirtualAddresses ((PVOID) MM_SHARED_USER_DATA_VA,
02139 (PVOID) MM_SHARED_USER_DATA_VA,
02140
FALSE,
02141
NULL);
02142
#endif
02143
02144
02145
02146
02147
02148
02149
02150
#if defined(_ALPHA_) && !defined(_AXP64_)
02151
LOCK_EXPANSION_IF_ALPHA (OldIrql2);
02152
#endif
02153
Process->
Vm.
AddressSpaceBeingDeleted = 1;
02154
#if defined(_ALPHA_) && !defined(_AXP64_)
02155
UNLOCK_EXPANSION_IF_ALPHA (OldIrql2);
02156
#endif
02157
02158
02159
02160
02161
02162
02163
02164 AboveWsMin = (LONG)Process->
Vm.
WorkingSetSize - (LONG)Process->
Vm.
MinimumWorkingSetSize;
02165
if (AboveWsMin > 0) {
02166
MmPagesAboveWsMinimum -= AboveWsMin;
02167 }
02168
02169
UNLOCK_PFN (OldIrql);
02170
02171
02172
02173
02174
02175
#ifdef _WIN64
02176
ASSERT (
MmWorkingSetList->
NumberOfCommittedPageTables == 0);
02177
#else
02178
MiReturnCommitment (
MmWorkingSetList->
NumberOfCommittedPageTables);
02179
02180
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PROCESS_CLEAN_PAGETABLES,
02181
MmWorkingSetList->
NumberOfCommittedPageTables);
02182
02183
if (Process->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
02184
PsChangeJobMemoryUsage(-(SSIZE_T)
MmWorkingSetList->
NumberOfCommittedPageTables);
02185 }
02186 Process->
CommitCharge -=
MmWorkingSetList->
NumberOfCommittedPageTables;
02187
#endif
02188
02189
02190
02191
02192
02193
ASSERT (Process->
CloneRoot == (
PMMCLONE_DESCRIPTOR)
NULL);
02194
02195
if (Process->
NumberOfLockedPages != 0) {
02196
if (Process->
LockedPagesList) {
02197
02198 PLIST_ENTRY NextEntry;
02199
PLOCK_TRACKER Tracker;
02200
PLOCK_HEADER LockedPagesHeader;
02201
02202 LockedPagesHeader = (
PLOCK_HEADER)Process->
LockedPagesList;
02203
if ((LockedPagesHeader->
Count != 0) && (
MiTrackingAborted ==
FALSE)) {
02204
ASSERT (IsListEmpty (&LockedPagesHeader->
ListHead) == 0);
02205 NextEntry = LockedPagesHeader->
ListHead.Flink;
02206
02207 Tracker = CONTAINING_RECORD (NextEntry,
02208
LOCK_TRACKER,
02209 ListEntry);
02210
02211
KeBugCheckEx (DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS,
02212 (ULONG_PTR)Tracker->
CallingAddress,
02213 (ULONG_PTR)Tracker->
CallersCaller,
02214 (ULONG_PTR)Tracker->
Mdl,
02215 Process->
NumberOfLockedPages);
02216 }
02217 }
02218
02219
KeBugCheckEx (PROCESS_HAS_LOCKED_PAGES,
02220 0,
02221 (ULONG_PTR)Process,
02222 Process->
NumberOfLockedPages,
02223 (ULONG_PTR)Process->LockedPagesList);
02224
return;
02225 }
02226
02227
if (Process->
LockedPagesList) {
02228
ASSERT (
MmTrackLockedPages ==
TRUE);
02229
ExFreePool (Process->
LockedPagesList);
02230 Process->
LockedPagesList =
NULL;
02231 }
02232
02233
#if DBG
02234
if ((Process->
NumberOfPrivatePages != 0) && (MmDebug &
MM_DBG_PRIVATE_PAGES)) {
02235
DbgPrint(
"MM: Process contains private pages %ld\n",
02236 Process->
NumberOfPrivatePages);
02237 DbgBreakPoint();
02238 }
02239
#endif //DBG
02240
02241
02242
#if defined(_WIN64)
02243
02244
02245
02246
02247
if (Process->
Wow64Process !=
NULL) {
02248
#if defined(_MIALT4K_)
02249
MiDeleteAlternateTable(Process);
02250
#endif
02251
ExFreePool(Process->
Wow64Process);
02252 Process->
Wow64Process =
NULL;
02253 }
02254
#endif
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 PointerPte =
MiGetPteAddress (
MmWorkingSetList) + 1;
02265
02266 PteFlushList.
Count = 0;
02267
02268
LOCK_PFN (OldIrql);
02269
while (PointerPte->
u.Hard.Valid) {
02270 TempVa =
MiGetVirtualAddressMappedByPte(PointerPte);
02271
MiDeletePte (PointerPte,
02272 TempVa,
02273
TRUE,
02274 Process,
02275
NULL,
02276 &PteFlushList);
02277
02278 PointerPte += 1;
02279
#if defined (_WIN64)
02280
02281
02282
02283
02284
02285
02286
if ((
MiIsPteOnPdeBoundary(PointerPte)) ||
02287 ((
MiGetPdeAddress(PointerPte))->u.Hard.Valid == 0) ||
02288 ((
MiGetPteAddress(PointerPte))->u.Hard.Valid == 0) ||
02289 (PointerPte->
u.Hard.Valid == 0)) {
02290
02291
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
02292
02293 PointerPde =
MiGetPteAddress (PointerPte - 1);
02294
02295
ASSERT (PointerPde->
u.Hard.Valid == 1);
02296
02297 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
02298
02299
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
02300 {
02301
MiDeletePte (PointerPde,
02302 PointerPte - 1,
02303
TRUE,
02304 Process,
02305
NULL,
02306
NULL);
02307 }
02308
02309
if (
MiIsPteOnPpeBoundary(PointerPte)) {
02310
02311 PointerPpe =
MiGetPteAddress (PointerPde);
02312
02313
ASSERT (PointerPpe->
u.Hard.Valid == 1);
02314
02315 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe));
02316
02317
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
02318 {
02319
MiDeletePte (PointerPpe,
02320 PointerPde,
02321
TRUE,
02322 Process,
02323
NULL,
02324
NULL);
02325 }
02326 }
02327 }
02328
#endif
02329
}
02330
02331
02332
02333
02334
02335
02336
02337 PointerPte =
MiGetPteAddress (&
MmWsle[
MM_MAXIMUM_WORKING_SET]) + 1;
02338
02339
#if defined (_WIN64)
02340
PointerPpe =
MiGetPdeAddress (PointerPte);
02341 PointerPde =
MiGetPteAddress (PointerPte);
02342
02343
if ((PointerPpe->
u.Hard.Valid == 1) &&
02344 (PointerPde->
u.Hard.Valid == 1) &&
02345 (PointerPte->
u.Hard.Valid == 1)) {
02346
02347
while (PointerPte->
u.Hard.Valid) {
02348 TempVa =
MiGetVirtualAddressMappedByPte(PointerPte);
02349
MiDeletePte (PointerPte,
02350 TempVa,
02351
TRUE,
02352 Process,
02353
NULL,
02354 &PteFlushList);
02355
02356 PointerPte += 1;
02357
02358
02359
02360
02361
02362
02363
02364
if ((
MiIsPteOnPdeBoundary(PointerPte)) ||
02365 ((
MiGetPdeAddress(PointerPte))->u.Hard.Valid == 0) ||
02366 ((
MiGetPteAddress(PointerPte))->u.Hard.Valid == 0) ||
02367 (PointerPte->
u.Hard.Valid == 0)) {
02368
02369
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
02370
02371 PointerPde =
MiGetPteAddress (PointerPte - 1);
02372
02373
ASSERT (PointerPde->
u.Hard.Valid == 1);
02374
02375 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
02376
02377
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
02378 {
02379
MiDeletePte (PointerPde,
02380 PointerPte - 1,
02381
TRUE,
02382 Process,
02383
NULL,
02384
NULL);
02385 }
02386
02387
if (
MiIsPteOnPpeBoundary(PointerPte)) {
02388
02389 PointerPpe =
MiGetPteAddress (PointerPde);
02390
02391
ASSERT (PointerPpe->
u.Hard.Valid == 1);
02392
02393 Pfn1 =
MI_PFN_ELEMENT (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe));
02394
02395
if (Pfn1->
u2.ShareCount == 1 && Pfn1->
u3.e2.ReferenceCount == 1)
02396 {
02397
MiDeletePte (PointerPpe,
02398 PointerPde,
02399
TRUE,
02400 Process,
02401
NULL,
02402
NULL);
02403 }
02404 }
02405 }
02406 }
02407 }
02408
#else
02409
while ((PointerPte < LastPte) && (PointerPte->
u.Hard.Valid)) {
02410 TempVa =
MiGetVirtualAddressMappedByPte(PointerPte);
02411
MiDeletePte (PointerPte,
02412 TempVa,
02413
TRUE,
02414 Process,
02415
NULL,
02416 &PteFlushList);
02417
02418 PointerPte += 1;
02419 }
02420
#endif
02421
02422
MiFlushPteList (&PteFlushList,
FALSE,
ZeroPte);
02423
02424
02425
02426
02427
02428
ASSERT (Process->
Vm.
MinimumWorkingSetSize >=
MM_PROCESS_CREATE_CHARGE);
02429
MmResidentAvailablePages += Process->
Vm.
MinimumWorkingSetSize -
02430
MM_PROCESS_CREATE_CHARGE;
02431
MM_BUMP_COUNTER(8, Process->
Vm.
MinimumWorkingSetSize -
02432
MM_PROCESS_CREATE_CHARGE);
02433
ASSERT (Process->
Vm.
WorkingSetExpansionLinks.Flink ==
MM_NO_WS_EXPANSION);
02434
UNLOCK_PFN (OldIrql);
02435
02436
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
02437
return;
02438 }
02439
02440
02441
#if DBG
02442
typedef struct _MMKSTACK {
02443
PMMPFN Pfn;
02444
PMMPTE Pte;
02445 } MMKSTACK, *PMMKSTACK;
02446 MMKSTACK MmKstacks[10];
02447
#endif //DBG
02448
02449 PVOID
02450 MmCreateKernelStack (
02451 IN BOOLEAN LargeStack
02452 )
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480 {
02481
PMMPTE PointerPte;
02482
MMPTE TempPte;
02483 PFN_NUMBER NumberOfPages;
02484 ULONG NumberOfPtes;
02485 ULONG ChargedPtes;
02486 ULONG RequestedPtes;
02487
#if defined(_IA64_)
02488
ULONG NumberOfBStorePtes;
02489
#endif
02490
PFN_NUMBER PageFrameIndex;
02491 ULONG i;
02492 PVOID StackVa;
02493 KIRQL OldIrql;
02494
02495
02496
02497
02498
02499
02500
LOCK_PFN (OldIrql);
02501
02502
02503
02504
02505
02506
if ((!LargeStack) && (
MmNumberDeadKernelStacks != 0)) {
02507
02508
#if DBG
02509
{
02510 ULONG i =
MmNumberDeadKernelStacks;
02511
PMMPFN PfnList =
MmFirstDeadKernelStack;
02512
02513
while (i > 0) {
02514 i--;
02515
if ((PfnList != MmKstacks[i].Pfn) ||
02516 (PfnList->
PteAddress != MmKstacks[i].Pte)) {
02517
DbgPrint(
"MMPROCSUP: kstacks %p %ld. %p\n",
02518 PfnList, i, MmKstacks[i].Pfn);
02519 DbgBreakPoint();
02520 }
02521 PfnList = PfnList->
u1.NextStackPfn;
02522 }
02523 }
02524
#if defined(_IA64_)
02525
NumberOfPages =
BYTES_TO_PAGES (KERNEL_STACK_SIZE + KERNEL_BSTORE_SIZE);
02526
#else
02527
NumberOfPages =
BYTES_TO_PAGES (KERNEL_STACK_SIZE);
02528
#endif
02529
#endif //DBG
02530
02531
MmNumberDeadKernelStacks -= 1;
02532 PointerPte =
MmFirstDeadKernelStack->
PteAddress;
02533
MmFirstDeadKernelStack =
MmFirstDeadKernelStack->
u1.NextStackPfn;
02534
02535 }
else {
02536
02537
UNLOCK_PFN (OldIrql);
02538
02539
#if defined(_IA64_)
02540
if (LargeStack) {
02541 NumberOfPtes =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_SIZE);
02542 NumberOfBStorePtes =
BYTES_TO_PAGES (KERNEL_LARGE_BSTORE_SIZE);
02543 NumberOfPages =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_COMMIT
02544 + KERNEL_LARGE_BSTORE_COMMIT);
02545
02546 }
else {
02547 NumberOfPtes =
BYTES_TO_PAGES (KERNEL_STACK_SIZE);
02548 NumberOfBStorePtes =
BYTES_TO_PAGES (KERNEL_BSTORE_SIZE);
02549 NumberOfPages = NumberOfPtes + NumberOfBStorePtes;
02550 }
02551 ChargedPtes = NumberOfPtes + NumberOfBStorePtes;
02552 RequestedPtes = ChargedPtes + 2 + (
MM_STACK_ALIGNMENT ? 1 : 0);
02553
#else
02554
if (LargeStack) {
02555 NumberOfPtes =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_SIZE);
02556 NumberOfPages =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_COMMIT);
02557 }
else {
02558 NumberOfPtes =
BYTES_TO_PAGES (KERNEL_STACK_SIZE);
02559 NumberOfPages = NumberOfPtes;
02560 }
02561 ChargedPtes = NumberOfPtes;
02562 RequestedPtes = ChargedPtes + 1 + (
MM_STACK_ALIGNMENT ? 1 : 0);
02563
#endif // _IA64_
02564
02565
02566
02567
02568
02569
if (
MiGetSystemPteListCount (RequestedPtes) < 8) {
02570
return NULL;
02571 }
02572
02573
02574
02575
02576
02577
if (
MiChargeCommitment (ChargedPtes,
NULL) ==
FALSE) {
02578
02579
02580
02581
02582
02583
02584
return NULL;
02585 }
02586
MM_TRACK_COMMIT (
MM_DBG_COMMIT_KERNEL_STACK_CREATE, ChargedPtes);
02587
02588
LOCK_PFN (OldIrql);
02589
02590
02591
02592
02593
02594
if (
MmResidentAvailablePages <= (SPFN_NUMBER)NumberOfPages) {
02595
UNLOCK_PFN (OldIrql);
02596
MiReturnCommitment (ChargedPtes);
02597
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE1,
02598 ChargedPtes);
02599
return NULL;
02600 }
02601
02602
MmResidentAvailablePages -= NumberOfPages;
02603
MM_BUMP_COUNTER(9, NumberOfPages);
02604
02605
UNLOCK_PFN (OldIrql);
02606
02607
02608
02609
02610
02611
02612
02613
MmKernelStackPages += RequestedPtes;
02614
02615 PointerPte =
MiReserveSystemPtes (RequestedPtes,
02616
SystemPteSpace,
02617
MM_STACK_ALIGNMENT,
02618
MM_STACK_OFFSET,
02619
FALSE);
02620
02621
if (PointerPte ==
NULL) {
02622
02623
LOCK_PFN (OldIrql);
02624
MmResidentAvailablePages += NumberOfPages;
02625
MM_BUMP_COUNTER(13, NumberOfPages);
02626
UNLOCK_PFN (OldIrql);
02627
02628
MiReturnCommitment (ChargedPtes);
02629
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE2,
02630 ChargedPtes);
02631
return NULL;
02632 }
02633
02634
#if defined(_IA64_)
02635
02636
02637
02638
02639
02640 StackVa = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte + NumberOfPtes + 1);
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
if (LargeStack) {
02653 PointerPte +=
BYTES_TO_PAGES (KERNEL_LARGE_STACK_SIZE - KERNEL_LARGE_STACK_COMMIT -1);
02654 }
02655
02656
#else
02657
PointerPte += (NumberOfPtes - NumberOfPages);
02658
#endif // _IA64_
02659
02660
LOCK_PFN (OldIrql);
02661
02662
for (i = 0; i < NumberOfPages; i += 1) {
02663 PointerPte += 1;
02664
ASSERT (PointerPte->
u.Hard.Valid == 0);
02665
MiEnsureAvailablePageOrWait (
NULL,
NULL);
02666 PageFrameIndex =
MiRemoveAnyPage (
02667
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
02668
02669 PointerPte->u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
02670
02671
#ifdef PROTECT_KSTACKS
02672
PointerPte->u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
02673
#endif
02674
02675
MiInitializePfn (PageFrameIndex, PointerPte, 1);
02676
02677
MI_MAKE_VALID_PTE (TempPte,
02678 PageFrameIndex,
02679
MM_READWRITE,
02680 PointerPte );
02681
MI_SET_PTE_DIRTY (TempPte);
02682
02683
MI_WRITE_VALID_PTE (PointerPte, TempPte);
02684 }
02685
MmProcessCommit += ChargedPtes;
02686
MmKernelStackResident += NumberOfPages;
02687
MmLargeStacks += LargeStack;
02688
MmSmallStacks += !LargeStack;
02689
02690
#if defined(_IA64_)
02691
02692
UNLOCK_PFN (OldIrql);
02693
02694
return StackVa;
02695
#endif
02696
02697 }
02698
02699
UNLOCK_PFN (OldIrql);
02700
02701 PointerPte += 1;
02702 StackVa = (PVOID)
MiGetVirtualAddressMappedByPte (PointerPte);
02703
#if !defined(_IA64_)
02704
#if DBG
02705
{
02706 PULONG p;
02707 ULONG_PTR i;
02708
02709 p = (PULONG)((ULONG_PTR)StackVa - ((ULONG_PTR)NumberOfPages *
PAGE_SIZE));
02710 i = ((ULONG_PTR)NumberOfPages *
PAGE_SIZE) >> 2;
02711
while(i--) {
02712 *p++ = 0x12345678;
02713 }
02714
02715 }
02716
#endif // DBG
02717
#endif // _IA64_
02718
02719
return StackVa;
02720 }
02721
02722
VOID
02723 MmDeleteKernelStack (
02724 IN PVOID PointerKernelStack,
02725 IN BOOLEAN LargeStack
02726 )
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752 {
02753
PMMPTE PointerPte;
02754
PMMPFN Pfn1;
02755 PFN_NUMBER NumberOfPages;
02756 ULONG NumberOfPtes;
02757 PFN_NUMBER PageFrameIndex;
02758 ULONG i;
02759 KIRQL OldIrql;
02760
MMPTE PteContents;
02761
02762
if (LargeStack) {
02763
#if defined(_IA64_)
02764
NumberOfPtes =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_SIZE + KERNEL_LARGE_BSTORE_SIZE);
02765
#else
02766
NumberOfPtes =
BYTES_TO_PAGES (KERNEL_LARGE_STACK_SIZE);
02767
#endif
02768
}
else {
02769
#if defined(_IA64_)
02770
NumberOfPtes =
BYTES_TO_PAGES (KERNEL_STACK_SIZE + KERNEL_BSTORE_SIZE);
02771
#else
02772
NumberOfPtes =
BYTES_TO_PAGES (KERNEL_STACK_SIZE);
02773
#endif
02774
}
02775
02776 PointerPte =
MiGetPteAddress (PointerKernelStack);
02777
02778
02779
02780
02781
02782
02783 PointerPte -= 1;
02784
02785
LOCK_PFN (OldIrql);
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
if ((!LargeStack) &&
02799 (
MmNumberDeadKernelStacks <
MmMaximumDeadKernelStacks)) {
02800
02801 Pfn1 =
MI_PFN_ELEMENT (PointerPte->
u.Hard.PageFrameNumber);
02802
02803
#if DBG
02804
{
02805 ULONG i =
MmNumberDeadKernelStacks;
02806
PMMPFN PfnList =
MmFirstDeadKernelStack;
02807
02808
while (i > 0) {
02809 i--;
02810
if ((PfnList != MmKstacks[i].Pfn) ||
02811 (PfnList->
PteAddress != MmKstacks[i].Pte)) {
02812
DbgPrint(
"MMPROCSUP: kstacks %p %ld. %p\n",
02813 PfnList, i, MmKstacks[i].Pfn);
02814 DbgBreakPoint();
02815 }
02816 PfnList = PfnList->
u1.NextStackPfn;
02817 }
02818 MmKstacks[
MmNumberDeadKernelStacks].Pte = Pfn1->
PteAddress;
02819 MmKstacks[
MmNumberDeadKernelStacks].Pfn = Pfn1;
02820 }
02821
#endif //DBG
02822
02823
MmNumberDeadKernelStacks += 1;
02824 Pfn1->
u1.NextStackPfn =
MmFirstDeadKernelStack;
02825
MmFirstDeadKernelStack = Pfn1;
02826
02827
PERFINFO_DELETE_STACK(PointerPte, NumberOfPtes);
02828
02829
UNLOCK_PFN (OldIrql);
02830
02831
return;
02832 }
02833
02834
#if defined(_IA64_)
02835
02836
02837
02838
02839
02840
02841
02842 PointerPte =
MiGetPteAddress (LargeStack ?
02843 (PCHAR)PointerKernelStack+KERNEL_LARGE_BSTORE_SIZE :
02844 (PCHAR)PointerKernelStack+KERNEL_BSTORE_SIZE);
02845
02846
02847
02848
02849
02850
02851 PointerPte -= 1;
02852
02853
#endif
02854
02855
02856
02857
02858
02859
02860 NumberOfPages = 0;
02861
for (i = 0; i < NumberOfPtes; i += 1) {
02862
02863 PteContents = *PointerPte;
02864
02865
if (PteContents.
u.Hard.Valid == 1) {
02866 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
02867 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02868
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
02869
02870
02871
02872
02873
02874
02875
MI_SET_PFN_DELETED (Pfn1);
02876
MiDecrementShareCountOnly (
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents));
02877 NumberOfPages += 1;
02878 }
02879 PointerPte -= 1;
02880 }
02881
02882
#if defined(_IA64_)
02883
MmKernelStackPages -= NumberOfPtes + 2 + (
MM_STACK_ALIGNMENT?1:0);
02884
02885
MiReleaseSystemPtes (PointerPte,
02886 NumberOfPtes + 2 + (
MM_STACK_ALIGNMENT?1:0),
02887
SystemPteSpace);
02888
#else
02889
MmKernelStackPages -= NumberOfPtes + 1 + (
MM_STACK_ALIGNMENT?1:0);
02890
02891
MiReleaseSystemPtes (PointerPte,
02892 NumberOfPtes + 1 + (
MM_STACK_ALIGNMENT?1:0),
02893
SystemPteSpace);
02894
#endif
02895
02896
02897
02898
02899
02900
MmKernelStackResident -= NumberOfPages;
02901
MmResidentAvailablePages += NumberOfPages;
02902
MM_BUMP_COUNTER(10, NumberOfPages);
02903
MmProcessCommit -= NumberOfPtes;
02904
02905
MmLargeStacks -= LargeStack;
02906
MmSmallStacks -= !LargeStack;
02907
UNLOCK_PFN (OldIrql);
02908
02909
02910
02911
02912
02913
MiReturnCommitment (NumberOfPtes);
02914
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_KERNEL_STACK_DELETE, NumberOfPtes);
02915
02916
return;
02917 }
02918
02919
02920
NTSTATUS
02921 MmGrowKernelStack (
02922 IN PVOID CurrentStack
02923 )
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949 {
02950
PMMPTE NewLimit;
02951
PMMPTE StackLimit;
02952
PMMPTE EndStack;
02953
PETHREAD Thread;
02954 PFN_NUMBER NumberOfPages;
02955 KIRQL OldIrql;
02956 PFN_NUMBER PageFrameIndex;
02957
MMPTE TempPte;
02958
02959 Thread =
PsGetCurrentThread ();
02960
ASSERT (((PCHAR)Thread->
Tcb.
StackBase - (PCHAR)Thread->
Tcb.
StackLimit) <=
02961 (KERNEL_LARGE_STACK_SIZE +
PAGE_SIZE));
02962 NewLimit =
MiGetPteAddress ((PVOID)((PUCHAR)CurrentStack -
02963 KERNEL_LARGE_STACK_COMMIT));
02964
02965 StackLimit =
MiGetPteAddress (Thread->
Tcb.
StackLimit);
02966
02967
02968
02969
02970
02971
02972 EndStack =
MiGetPteAddress ((PVOID)((PUCHAR)Thread->
Tcb.
StackBase -
02973 KERNEL_LARGE_STACK_SIZE));
02974
02975
if (NewLimit < EndStack) {
02976
02977
02978
02979
02980
02981
return STATUS_STACK_OVERFLOW;
02982
02983 }
02984
02985
ASSERT (StackLimit->
u.Hard.Valid == 1);
02986
02987
02988
02989
02990
02991 StackLimit -= 1;
02992
02993 NumberOfPages = (PFN_NUMBER) (StackLimit - NewLimit + 1);
02994
02995
LOCK_PFN (OldIrql);
02996
02997
if (
MmResidentAvailablePages <= (SPFN_NUMBER)NumberOfPages) {
02998
UNLOCK_PFN (OldIrql);
02999
return STATUS_NO_MEMORY;
03000 }
03001
03002
03003
03004
03005
03006
03007
MmResidentAvailablePages -= NumberOfPages;
03008
MM_BUMP_COUNTER(11, NumberOfPages);
03009
03010
while (StackLimit >= NewLimit) {
03011
03012
ASSERT (StackLimit->
u.Hard.Valid == 0);
03013
03014
MiEnsureAvailablePageOrWait (
NULL,
NULL);
03015 PageFrameIndex =
MiRemoveAnyPage (
MI_GET_PAGE_COLOR_FROM_PTE (StackLimit));
03016 StackLimit->u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
03017
03018
#ifdef PROTECT_KSTACKS
03019
StackLimit->u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03020
#endif
03021
03022
MiInitializePfn (PageFrameIndex, StackLimit, 1);
03023
03024
MI_MAKE_VALID_PTE (TempPte,
03025 PageFrameIndex,
03026
MM_READWRITE,
03027 StackLimit );
03028
03029
MI_SET_PTE_DIRTY (TempPte);
03030 *StackLimit = TempPte;
03031 StackLimit -= 1;
03032 }
03033
03034
MmKernelStackResident += NumberOfPages;
03035
UNLOCK_PFN (OldIrql);
03036
03037
#if DBG
03038
ASSERT (NewLimit->
u.Hard.Valid == 1);
03039
if (NewLimit != EndStack) {
03040
ASSERT ((NewLimit - 1)->u.Hard.Valid == 0);
03041 }
03042
#endif
03043
03044 Thread->
Tcb.
StackLimit =
MiGetVirtualAddressMappedByPte (NewLimit);
03045
03046
PERFINFO_GROW_STACK(Thread);
03047
03048
return STATUS_SUCCESS;
03049 }
03050
03051
#if defined(_IA64_)
03052
03053
NTSTATUS
03054 MmGrowKernelBackingStore (
03055 IN PVOID CurrentStack
03056 )
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078 {
03079
PMMPTE NewLimit;
03080
PMMPTE StackLimit;
03081
PMMPTE EndStack;
03082
PETHREAD Thread;
03083 PFN_NUMBER NumberOfPages;
03084 KIRQL OldIrql;
03085 PFN_NUMBER PageFrameIndex;
03086
MMPTE TempPte;
03087
03088 Thread =
PsGetCurrentThread ();
03089
ASSERT (((PCHAR)Thread->
Tcb.BStoreLimit - (PCHAR)Thread->
Tcb.
StackBase) <=
03090 (KERNEL_LARGE_BSTORE_SIZE + PAGE_SIZE));
03091 NewLimit =
MiGetPteAddress ((PVOID)((PUCHAR)CurrentStack +
03092 KERNEL_LARGE_BSTORE_COMMIT-1));
03093
03094 StackLimit =
MiGetPteAddress ((PCHAR)Thread->
Tcb.BStoreLimit - (PCHAR)1);
03095
03096
03097
03098
03099
03100
03101 EndStack =
MiGetPteAddress ((PVOID)((PUCHAR)Thread->
Tcb.
StackBase +
03102 KERNEL_LARGE_BSTORE_SIZE-1));
03103
03104
if (NewLimit > EndStack) {
03105
03106
03107
03108
03109
03110
return STATUS_STACK_OVERFLOW;
03111
03112 }
03113
03114
ASSERT (StackLimit->
u.Hard.Valid == 1);
03115
03116
03117
03118
03119
03120 StackLimit += 1;
03121
03122 NumberOfPages = (PFN_NUMBER)(NewLimit - StackLimit + 1);
03123
03124
LOCK_PFN (OldIrql);
03125
03126
if (
MmResidentAvailablePages <= (SPFN_NUMBER)NumberOfPages) {
03127
UNLOCK_PFN (OldIrql);
03128
return STATUS_NO_MEMORY;
03129 }
03130
03131
03132
03133
03134
03135
03136
MmResidentAvailablePages -= NumberOfPages;
03137
03138
while (StackLimit <= NewLimit) {
03139
03140
ASSERT (StackLimit->
u.Hard.Valid == 0);
03141
03142
MiEnsureAvailablePageOrWait (NULL, NULL);
03143 PageFrameIndex =
MiRemoveAnyPage (MI_GET_PAGE_COLOR_FROM_PTE (StackLimit));
03144 StackLimit->
u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
03145
03146
#ifdef PROTECT_KSTACKS
03147
StackLimit->
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03148
#endif
03149
03150
MiInitializePfn (PageFrameIndex, StackLimit, 1);
03151
03152
MI_MAKE_VALID_PTE (TempPte,
03153 PageFrameIndex,
03154 MM_READWRITE,
03155 StackLimit );
03156
03157
MI_SET_PTE_DIRTY (TempPte);
03158 *StackLimit = TempPte;
03159 StackLimit += 1;
03160 }
03161
03162
MmKernelStackResident += NumberOfPages;
03163
UNLOCK_PFN (OldIrql);
03164
03165
#if DBG
03166
ASSERT (NewLimit->
u.Hard.Valid == 1);
03167
if (NewLimit != EndStack) {
03168
ASSERT ((NewLimit + 1)->u.Hard.Valid == 0);
03169 }
03170
#endif
03171
03172 Thread->
Tcb.BStoreLimit =
MiGetVirtualAddressMappedByPte (NewLimit+1);
03173
03174
return STATUS_SUCCESS;
03175 }
03176
#endif // defined(_IA64_)
03177
03178
03179
VOID
03180 MmOutPageKernelStack (
03181 IN
PKTHREAD Thread
03182 )
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209 #
if defined(_IA64_)
03210 #define
MAX_STACK_PAGES ((KERNEL_LARGE_STACK_SIZE + KERNEL_LARGE_BSTORE_SIZE) / PAGE_SIZE)
03211 #
else
03212
#define MAX_STACK_PAGES (KERNEL_LARGE_STACK_SIZE / PAGE_SIZE)
03213
#endif
03214
03215 {
03216
PMMPTE PointerPte;
03217
PMMPTE LastPte;
03218
PMMPTE EndOfStackPte;
03219
PMMPFN Pfn1;
03220 PFN_NUMBER PageFrameIndex;
03221 KIRQL OldIrql;
03222
MMPTE TempPte;
03223 PVOID BaseOfKernelStack;
03224
PMMPTE FlushPte[
MAX_STACK_PAGES];
03225 PVOID FlushVa[
MAX_STACK_PAGES];
03226
MMPTE FlushPteSave[
MAX_STACK_PAGES];
03227 ULONG StackSize;
03228 ULONG
Count;
03229
PMMPTE LimitPte;
03230
PMMPTE LowestLivePte;
03231
03232
ASSERT (((PCHAR)Thread->StackBase - (PCHAR)Thread->StackLimit) <=
03233 (KERNEL_LARGE_STACK_SIZE +
PAGE_SIZE));
03234
03235
if (
NtGlobalFlag & FLG_DISABLE_PAGE_KERNEL_STACKS) {
03236
return;
03237 }
03238
03239
03240
03241
03242
03243
03244 BaseOfKernelStack = ((PCHAR)Thread->StackBase -
PAGE_SIZE);
03245 PointerPte =
MiGetPteAddress (BaseOfKernelStack);
03246 LastPte =
MiGetPteAddress ((PULONG)Thread->KernelStack - 1);
03247
if (Thread->LargeStack) {
03248 StackSize = KERNEL_LARGE_STACK_SIZE >>
PAGE_SHIFT;
03249
03250
03251
03252
03253
03254
03255 LimitPte =
MiGetPteAddress (Thread->StackLimit);
03256
03257 LowestLivePte =
MiGetPteAddress ((PVOID)((PUCHAR)Thread->InitialStack -
03258 KERNEL_LARGE_STACK_COMMIT));
03259
03260
if (LowestLivePte < LimitPte) {
03261 LowestLivePte = LimitPte;
03262 }
03263 }
else {
03264 StackSize = KERNEL_STACK_SIZE >>
PAGE_SHIFT;
03265 LowestLivePte =
MiGetPteAddress (Thread->StackLimit);
03266 }
03267 EndOfStackPte = PointerPte - StackSize;
03268
03269
ASSERT (LowestLivePte <= LastPte);
03270
03271
03272
03273
03274
03275 *((PULONG_PTR)Thread->KernelStack - 1) = (ULONG_PTR)Thread;
03276
03277
Count = 0;
03278
03279
LOCK_PFN (OldIrql);
03280
03281
do {
03282
ASSERT (PointerPte->
u.Hard.Valid == 1);
03283 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03284 TempPte = *PointerPte;
03285
MI_MAKE_VALID_PTE_TRANSITION (TempPte, 0);
03286
03287
#ifdef PROTECT_KSTACKS
03288
TempPte.
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03289 {
03290
PMMPFN x;
03291 x =
MI_PFN_ELEMENT(PageFrameIndex);
03292 x->
OriginalPte.
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03293 }
03294
#endif
03295
03296 FlushPteSave[
Count] = TempPte;
03297 FlushPte[
Count] = PointerPte;
03298 FlushVa[
Count] = BaseOfKernelStack;
03299
03300
MiDecrementShareCount (PageFrameIndex);
03301 PointerPte -= 1;
03302
Count += 1;
03303 BaseOfKernelStack = ((PCHAR)BaseOfKernelStack -
PAGE_SIZE);
03304 }
while (PointerPte >= LastPte);
03305
03306
while (PointerPte != EndOfStackPte) {
03307
if (PointerPte->
u.Hard.Valid == 0) {
03308
break;
03309 }
03310
03311 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03312 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03313
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
03314
MI_SET_PFN_DELETED (Pfn1);
03315
MiDecrementShareCountOnly (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte));
03316
03317 FlushPteSave[
Count] =
KernelDemandZeroPte;
03318
03319
#ifdef PROTECT_KSTACKS
03320
FlushPteSave[
Count].
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03321
#endif
03322
03323 FlushPte[
Count] = PointerPte;
03324
03325 FlushVa[
Count] = BaseOfKernelStack;
03326
Count += 1;
03327
03328
03329
03330
03331
03332
if (PointerPte < LowestLivePte) {
03333
ASSERT (Thread->LargeStack);
03334
MmResidentAvailablePages += 1;
03335
MM_BUMP_COUNTER(12, 1);
03336 }
03337
03338 PointerPte -= 1;
03339 BaseOfKernelStack = ((PCHAR)BaseOfKernelStack -
PAGE_SIZE);
03340 }
03341
03342
#if defined(_IA64_)
03343
03344
03345
03346
03347 BaseOfKernelStack = Thread->StackBase;
03348 PointerPte =
MiGetPteAddress (BaseOfKernelStack);
03349 LastPte =
MiGetPteAddress ((PULONG)Thread->KernelBStore);
03350
03351
if (Thread->LargeStack) {
03352 StackSize = KERNEL_LARGE_BSTORE_SIZE >>
PAGE_SHIFT;
03353 }
else {
03354 StackSize = KERNEL_BSTORE_SIZE >>
PAGE_SHIFT;
03355 }
03356 EndOfStackPte = PointerPte + StackSize;
03357
03358
do {
03359
ASSERT (PointerPte->
u.Hard.Valid == 1);
03360 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03361 TempPte = *PointerPte;
03362
MI_MAKE_VALID_PTE_TRANSITION (TempPte, 0);
03363
03364
#ifdef PROTECT_KSTACKS
03365
TempPte.
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03366 {
03367
PMMPFN x;
03368 x =
MI_PFN_ELEMENT(PageFrameIndex);
03369 x->
OriginalPte.
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03370 }
03371
#endif
03372
03373 FlushPteSave[
Count] = TempPte;
03374 FlushPte[
Count] = PointerPte;
03375 FlushVa[
Count] = BaseOfKernelStack;
03376
03377
MiDecrementShareCount (PageFrameIndex);
03378 PointerPte += 1;
03379
Count += 1;
03380 BaseOfKernelStack = ((PCHAR)BaseOfKernelStack +
PAGE_SIZE);
03381 }
while (PointerPte <= LastPte);
03382
03383
while (PointerPte != EndOfStackPte) {
03384
if (PointerPte->
u.Hard.Valid == 0) {
03385
break;
03386 }
03387
03388 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03389 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
03390
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
03391
MI_SET_PFN_DELETED (Pfn1);
03392
MiDecrementShareCountOnly (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte));
03393
03394 FlushPteSave[
Count] =
KernelDemandZeroPte;
03395
03396
#ifdef PROTECT_KSTACKS
03397
FlushPteSave[
Count].
u.Soft.Protection =
MM_KSTACK_OUTSWAPPED;
03398
#endif
03399
03400 FlushPte[
Count] = PointerPte;
03401 FlushVa[
Count] = BaseOfKernelStack;
03402
Count += 1;
03403
03404 PointerPte += 1;
03405 BaseOfKernelStack = ((PCHAR)BaseOfKernelStack +
PAGE_SIZE);
03406 }
03407
03408
#endif // _IA64_
03409
03410
ASSERT (
Count <=
MAX_STACK_PAGES);
03411
03412
if (
Count <
MM_MAXIMUM_FLUSH_COUNT) {
03413
KeFlushMultipleTb (
Count,
03414 &FlushVa[0],
03415
TRUE,
03416
TRUE,
03417 &((PHARDWARE_PTE)FlushPte[0]),
03418
ZeroPte.
u.Flush);
03419 }
else {
03420
KeFlushEntireTb (
TRUE,
TRUE);
03421 }
03422
03423
03424
03425
03426
03427
03428
MmKernelStackResident -=
Count;
03429
03430
03431
03432
03433
03434
do {
03435
Count -= 1;
03436 *FlushPte[
Count] = FlushPteSave[
Count];
03437 }
while (
Count != 0);
03438
03439
03440
UNLOCK_PFN (OldIrql);
03441
return;
03442 }
03443
03444
VOID
03445 MmInPageKernelStack (
03446 IN
PKTHREAD Thread
03447 )
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470 {
03471 PVOID BaseOfKernelStack;
03472
PMMPTE PointerPte;
03473
PMMPTE EndOfStackPte;
03474
PMMPTE SignaturePte;
03475 ULONG DiskRead;
03476 PFN_NUMBER ContainingPage;
03477 KIRQL OldIrql;
03478
03479
ASSERT (((PCHAR)Thread->StackBase - (PCHAR)Thread->StackLimit) <=
03480 (KERNEL_LARGE_STACK_SIZE +
PAGE_SIZE));
03481
03482
if (
NtGlobalFlag & FLG_DISABLE_PAGE_KERNEL_STACKS) {
03483
return;
03484 }
03485
03486
03487
03488
03489
03490
03491
if (Thread->LargeStack) {
03492 PointerPte =
MiGetPteAddress ((PVOID)((PUCHAR)Thread->StackLimit));
03493
03494 EndOfStackPte =
MiGetPteAddress ((PVOID)((PUCHAR)Thread->InitialStack -
03495 KERNEL_LARGE_STACK_COMMIT));
03496
03497
03498
03499
03500
03501
if (EndOfStackPte < PointerPte) {
03502 EndOfStackPte = PointerPte;
03503 }
03504 Thread->StackLimit =
MiGetVirtualAddressMappedByPte (EndOfStackPte);
03505 }
else {
03506 EndOfStackPte =
MiGetPteAddress (Thread->StackLimit);
03507 }
03508
03509
#if defined(_IA64_)
03510
03511
if (Thread->LargeStack) {
03512
03513 PVOID TempAddress = (PVOID)((PUCHAR)Thread->BStoreLimit);
03514
03515 BaseOfKernelStack = (PVOID)(((ULONG_PTR)Thread->InitialBStore +
03516 KERNEL_LARGE_BSTORE_COMMIT) &
03517 ~(ULONG_PTR)(
PAGE_SIZE - 1));
03518
03519
03520
03521
03522
03523
if (BaseOfKernelStack > TempAddress) {
03524 BaseOfKernelStack = TempAddress;
03525 }
03526 Thread->BStoreLimit = BaseOfKernelStack;
03527 }
03528 BaseOfKernelStack = ((PCHAR)Thread->BStoreLimit -
PAGE_SIZE);
03529
#else
03530
BaseOfKernelStack = ((PCHAR)Thread->StackBase -
PAGE_SIZE);
03531
#endif // _IA64_
03532
03533 PointerPte =
MiGetPteAddress (BaseOfKernelStack);
03534
03535 DiskRead = 0;
03536 SignaturePte =
MiGetPteAddress ((PULONG_PTR)Thread->KernelStack - 1);
03537
ASSERT (SignaturePte->
u.Hard.Valid == 0);
03538
if ((SignaturePte->
u.Long !=
MM_KERNEL_DEMAND_ZERO_PTE) &&
03539 (SignaturePte->
u.Soft.Transition == 0)) {
03540 DiskRead = 1;
03541 }
03542
03543
LOCK_PFN (OldIrql);
03544
03545
while (PointerPte >= EndOfStackPte) {
03546
03547
#ifdef PROTECT_KSTACKS
03548
if (!((PointerPte->
u.Long ==
KernelDemandZeroPte.
u.Long) ||
03549 (PointerPte->
u.Soft.Protection ==
MM_KSTACK_OUTSWAPPED))) {
03550
KeBugCheckEx (MEMORY_MANAGEMENT,
03551 0x3451,
03552 (ULONG_PTR)PointerPte,
03553 (ULONG_PTR)Thread,
03554 0);
03555 }
03556
ASSERT (PointerPte->
u.Hard.Valid == 0);
03557
if (PointerPte->
u.Soft.Protection ==
MM_KSTACK_OUTSWAPPED) {
03558 PointerPte->
u.Soft.Protection = PAGE_READWRITE;
03559 }
03560
#endif
03561
03562 ContainingPage =
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress (PointerPte));
03563
MiMakeOutswappedPageResident (PointerPte,
03564 PointerPte,
03565 1,
03566 ContainingPage);
03567
03568 PointerPte -= 1;
03569
MmKernelStackResident += 1;
03570 }
03571
03572
03573
03574
03575
03576
if (*((PULONG_PTR)Thread->KernelStack - 1) != (ULONG_PTR)Thread) {
03577
KeBugCheckEx (KERNEL_STACK_INPAGE_ERROR,
03578 DiskRead,
03579 *((PULONG_PTR)Thread->KernelStack - 1),
03580 0,
03581 (ULONG_PTR)Thread->KernelStack);
03582 }
03583
03584
UNLOCK_PFN (OldIrql);
03585
return;
03586 }
03587
03588
03589
VOID
03590 MmOutSwapProcess (
03591 IN
PKPROCESS Process
03592 )
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610 {
03611 KIRQL OldIrql;
03612 KIRQL OldIrql2;
03613
PEPROCESS OutProcess;
03614
PMMPTE PointerPte;
03615
PMMPFN Pfn1;
03616 PFN_NUMBER HyperSpacePageTable;
03617
PMMPTE HyperSpacePageTableMap;
03618 PFN_NUMBER PpePage;
03619 PFN_NUMBER PdePage;
03620
PMMPTE PageDirectoryMap;
03621 PFN_NUMBER ProcessPage;
03622
MMPTE TempPte;
03623
#if defined (_X86PAE_)
03624
ULONG i;
03625
MMPTE TempPte2;
03626 PFN_NUMBER PdePage2;
03627 PFN_NUMBER HyperPage2;
03628 PPAE_ENTRY PaeVa;
03629
#endif
03630
03631 OutProcess = CONTAINING_RECORD (Process,
EPROCESS, Pcb);
03632
03633 OutProcess->
ProcessOutswapEnabled =
TRUE;
03634
03635
#if DBG
03636
if ((MmDebug &
MM_DBG_SWAP_PROCESS) != 0) {
03637
return;
03638 }
03639
#endif //DBG
03640
03641
if (
MiHydra ==
TRUE && OutProcess->
Vm.
u.Flags.ProcessInSession == 1) {
03642
MiSessionOutSwapProcess (OutProcess);
03643 }
03644
03645
if ((OutProcess->
Vm.
WorkingSetSize ==
MM_PROCESS_COMMIT_CHARGE) &&
03646 (OutProcess->
Vm.
AllowWorkingSetAdjustment)) {
03647
03648
LOCK_EXPANSION (OldIrql);
03649
03650
ASSERT (OutProcess->
ProcessOutswapped ==
FALSE);
03651
03652
if (OutProcess->
Vm.
u.Flags.BeingTrimmed ==
TRUE) {
03653
03654
03655
03656
03657
03658
03659
UNLOCK_EXPANSION (OldIrql);
03660
return;
03661 }
03662
03663
03664
03665
03666
03667
03668 OutProcess->
ProcessOutswapped =
TRUE;
03669
03670
UNLOCK_EXPANSION (OldIrql);
03671
03672
LOCK_PFN (OldIrql);
03673
03674
03675
03676
03677
03678
#if !defined (_X86PAE_)
03679
HyperSpacePageTable =
03680
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(OutProcess->
Pcb.
DirectoryTableBase[1])));
03681
#else
03682
HyperSpacePageTable = (PFN_NUMBER)OutProcess->
Pcb.
DirectoryTableBase[1];
03683
#endif
03684
03685 HyperSpacePageTableMap =
MiMapPageInHyperSpace (HyperSpacePageTable, &OldIrql2);
03686
03687 TempPte = HyperSpacePageTableMap[
MiGetPteOffset(
MmWorkingSetList)];
03688
03689
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03690
MM_READWRITE);
03691
03692 HyperSpacePageTableMap[
MiGetPteOffset(
MmWorkingSetList)] = TempPte;
03693
03694
#if defined (_X86PAE_)
03695
TempPte2 = HyperSpacePageTableMap[0];
03696
03697 HyperPage2 =
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)&TempPte2);
03698
03699
MI_MAKE_VALID_PTE_TRANSITION (TempPte2,
03700
MM_READWRITE);
03701
03702 HyperSpacePageTableMap[0] = TempPte2;
03703
#endif
03704
03705
MiUnmapPageInHyperSpace (OldIrql2);
03706
03707
#if DBG
03708
Pfn1 =
MI_PFN_ELEMENT (OutProcess->
WorkingSetPage);
03709
ASSERT (Pfn1->
u3.e1.Modified == 1);
03710
#endif
03711
MiDecrementShareCount (OutProcess->
WorkingSetPage);
03712
03713
03714
03715
03716
03717 Pfn1 =
MI_PFN_ELEMENT (HyperSpacePageTable);
03718 PdePage = Pfn1->
PteFrame;
03719
ASSERT (PdePage);
03720
03721 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
03722
03723 TempPte = PageDirectoryMap[
MiGetPdeOffset(
MmWorkingSetList)];
03724
03725
ASSERT (TempPte.u.Hard.Valid == 1);
03726
ASSERT (TempPte.u.Hard.PageFrameNumber == HyperSpacePageTable);
03727
03728
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03729
MM_READWRITE);
03730
03731 PageDirectoryMap[
MiGetPdeOffset(
MmWorkingSetList)] = TempPte;
03732
03733
ASSERT (Pfn1->
u3.e1.Modified == 1);
03734
03735
MiDecrementShareCount (HyperSpacePageTable);
03736
03737
#if defined (_X86PAE_)
03738
03739
03740
03741
03742
03743 Pfn1 =
MI_PFN_ELEMENT (HyperPage2);
03744
03745
ASSERT (Pfn1->
u3.e1.Modified == 1);
03746
03747 PdePage = Pfn1->
PteFrame;
03748
ASSERT (PdePage);
03749
03750 PageDirectoryMap[
MiGetPdeOffset(HYPER_SPACE2)] = TempPte2;
03751
03752
MiDecrementShareCount (HyperPage2);
03753
03754
03755
03756
03757
03758 PaeVa = (PPAE_ENTRY)OutProcess->
PaeTop;
03759
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
03760
03761 TempPte = PageDirectoryMap[i];
03762 PdePage2 =
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)&TempPte);
03763
03764
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03765
MM_READWRITE);
03766
03767 PageDirectoryMap[i] = TempPte;
03768 Pfn1 =
MI_PFN_ELEMENT (PdePage2);
03769
ASSERT (Pfn1->
u3.e1.Modified == 1);
03770
03771
MiDecrementShareCount (PdePage2);
03772 PaeVa->PteEntry[i].u.Long = TempPte.u.Long;
03773 }
03774
03775
#if DBG
03776
TempPte = PageDirectoryMap[i];
03777 PdePage2 =
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)&TempPte);
03778 Pfn1 =
MI_PFN_ELEMENT (PdePage2);
03779
ASSERT (Pfn1->
u3.e1.Modified == 1);
03780
#endif
03781
03782
#endif
03783
03784
#if defined (_WIN64)
03785
03786
MiUnmapPageInHyperSpace (OldIrql2);
03787
03788
03789
03790
03791
03792 Pfn1 =
MI_PFN_ELEMENT (PdePage);
03793 PpePage = Pfn1->
PteFrame;
03794
ASSERT (PpePage);
03795
ASSERT (PpePage ==
MI_GET_PAGE_FRAME_FROM_PTE((
PMMPTE)(&(OutProcess->
Pcb.
DirectoryTableBase[0]))));
03796
03797 PageDirectoryMap =
MiMapPageInHyperSpace (PpePage, &OldIrql2);
03798
03799 TempPte = PageDirectoryMap[
MiGetPpeOffset(
MmWorkingSetList)];
03800
03801
ASSERT (TempPte.
u.Hard.Valid == 1);
03802
ASSERT (TempPte.
u.Hard.PageFrameNumber == PdePage);
03803
03804
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03805
MM_READWRITE);
03806
03807 PageDirectoryMap[
MiGetPpeOffset(
MmWorkingSetList)] = TempPte;
03808
03809
ASSERT (Pfn1->
u3.e1.Modified == 1);
03810
03811
MiDecrementShareCount (HyperSpacePageTable);
03812
03813
03814
03815
03816
03817 TempPte = PageDirectoryMap[
MiGetPpeOffset(PDE_TBASE)];
03818
03819
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03820
MM_READWRITE);
03821
03822 PageDirectoryMap[
MiGetPpeOffset(PDE_TBASE)] = TempPte;
03823
03824 Pfn1 =
MI_PFN_ELEMENT (PpePage);
03825
03826
#else
03827
03828
03829
03830
03831
03832 TempPte = PageDirectoryMap[
MiGetPdeOffset(PDE_BASE)];
03833
03834
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
03835
MM_READWRITE);
03836
03837 PageDirectoryMap[
MiGetPdeOffset(PDE_BASE)] = TempPte;
03838
03839 Pfn1 =
MI_PFN_ELEMENT (PdePage);
03840
03841
#endif
03842
03843
MiUnmapPageInHyperSpace (OldIrql2);
03844
03845
03846
03847
03848
03849
03850
03851
03852 Pfn1->
u2.ShareCount -= 2;
03853 Pfn1->
PteAddress = (
PMMPTE)&OutProcess->
PageDirectoryPte;
03854
03855 OutProcess->
PageDirectoryPte = TempPte.u.Flush;
03856
03857
#if defined (_X86PAE_)
03858
PaeVa->PteEntry[i].u.Long = TempPte.u.Long;
03859
#endif
03860
03861
if (
MI_IS_PHYSICAL_ADDRESS(OutProcess)) {
03862 ProcessPage =
MI_CONVERT_PHYSICAL_TO_PFN (OutProcess);
03863 }
else {
03864 PointerPte =
MiGetPteAddress (OutProcess);
03865 ProcessPage =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03866 }
03867
03868 Pfn1->
PteFrame = ProcessPage;
03869 Pfn1 =
MI_PFN_ELEMENT (ProcessPage);
03870
03871
03872
03873
03874
03875 Pfn1->
u2.ShareCount += 1;
03876
UNLOCK_PFN (OldIrql);
03877
03878
LOCK_EXPANSION (OldIrql);
03879
if (OutProcess->
Vm.
WorkingSetExpansionLinks.Flink >
03880
MM_IO_IN_PROGRESS) {
03881
03882
03883
03884
03885 RemoveEntryList (&OutProcess->
Vm.
WorkingSetExpansionLinks);
03886 OutProcess->
Vm.
WorkingSetExpansionLinks.Flink =
MM_WS_SWAPPED_OUT;
03887 }
03888
UNLOCK_EXPANSION (OldIrql);
03889
03890 OutProcess->
WorkingSetPage = 0;
03891 OutProcess->
Vm.
WorkingSetSize = 0;
03892
#if defined(_IA64_)
03893
03894
03895
03896
03897
03898
03899
03900
03901 Process->ProcessRegion.SequenceNumber = 0;
03902
#endif _IA64_
03903
03904 }
03905
03906
return;
03907 }
03908
03909
VOID
03910 MmInSwapProcess (
03911 IN
PKPROCESS Process
03912 )
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931 {
03932 KIRQL OldIrql;
03933 KIRQL OldIrql2;
03934
PEPROCESS OutProcess;
03935 PFN_NUMBER PdePage;
03936 PFN_NUMBER PageDirectoryPage;
03937
PMMPTE PageDirectoryMap;
03938
PMMPTE PageDirectoryParentMap;
03939
MMPTE TempPte;
03940
MMPTE TempPte2;
03941 PFN_NUMBER HyperSpacePageTable;
03942
PMMPTE HyperSpacePageTableMap;
03943 PFN_NUMBER WorkingSetPage;
03944
PMMPFN Pfn1;
03945
PMMPTE PointerPte;
03946 PFN_NUMBER ProcessPage;
03947
#if defined (_X86PAE_)
03948
ULONG i;
03949 PPAE_ENTRY PaeVa;
03950 PFN_NUMBER PdePage2;
03951
#endif
03952
03953 OutProcess = CONTAINING_RECORD (Process,
EPROCESS, Pcb);
03954
03955
if (OutProcess->
ProcessOutswapped ==
TRUE) {
03956
03957
03958
03959
03960
03961
03962
if (
MI_IS_PHYSICAL_ADDRESS(OutProcess)) {
03963 ProcessPage =
MI_CONVERT_PHYSICAL_TO_PFN (OutProcess);
03964 }
else {
03965 PointerPte =
MiGetPteAddress (OutProcess);
03966 ProcessPage =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
03967 }
03968
03969
LOCK_PFN (OldIrql);
03970
03971
#if defined (_WIN64)
03972
PdePage =
MiMakeOutswappedPageResident (
MiGetPteAddress (PDE_TBASE),
03973 (
PMMPTE)&OutProcess->
PageDirectoryPte,
03974 0,
03975 ProcessPage);
03976
#else
03977
PdePage =
MiMakeOutswappedPageResident (
MiGetPteAddress (PDE_BASE),
03978 (
PMMPTE)&OutProcess->
PageDirectoryPte,
03979 0,
03980 ProcessPage);
03981
#endif
03982
03983
03984
03985
03986
03987 Pfn1 =
MI_PFN_ELEMENT (ProcessPage);
03988 Pfn1->
u2.ShareCount -= 1;
03989
03990
ASSERT ((LONG)Pfn1->
u2.ShareCount >= 1);
03991
03992
03993
03994
03995
03996 Pfn1 =
MI_PFN_ELEMENT (PdePage);
03997 Pfn1->
u2.ShareCount += 1;
03998
#if !defined (_WIN64)
03999
Pfn1->
u1.Event = (PVOID)OutProcess;
04000
#endif
04001
Pfn1->
PteFrame = PdePage;
04002 Pfn1->
PteAddress =
MiGetPteAddress (PDE_BASE);
04003
04004
#if defined (_WIN64)
04005
04006
04007
04008
04009
04010
04011 PageDirectoryParentMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04012
04013 TempPte = PageDirectoryParentMap[
MiGetPpeOffset(
MmWorkingSetList)];
04014
04015
MiUnmapPageInHyperSpace (OldIrql2);
04016
04017 PageDirectoryPage =
MiMakeOutswappedPageResident (
04018
MiGetPpeAddress (
MmWorkingSetList),
04019 &TempPte,
04020 0,
04021 PdePage);
04022
04023
ASSERT (PageDirectoryPage == TempPte.
u.Hard.PageFrameNumber);
04024
ASSERT (Pfn1->
u2.ShareCount >= 3);
04025
04026 PageDirectoryParentMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04027
04028 PageDirectoryParentMap[
MiGetPpeOffset(PDE_TBASE)].u.Flush =
04029 OutProcess->
PageDirectoryPte;
04030 PageDirectoryParentMap[
MiGetPpeOffset(
MmWorkingSetList)] = TempPte;
04031
04032
MiUnmapPageInHyperSpace (OldIrql2);
04033
04034 PdePage = PageDirectoryPage;
04035
#endif
04036
04037
#if defined (_X86PAE_)
04038
04039 OutProcess->
PaePageDirectoryPage = PdePage;
04040
04041
04042
04043
04044
04045 PaeVa = (PPAE_ENTRY)OutProcess->
PaeTop;
04046
for (i = 0; i < PD_PER_SYSTEM - 1; i += 1) {
04047 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04048
04049 TempPte = PageDirectoryMap[i];
04050
04051
MiUnmapPageInHyperSpace (OldIrql2);
04052
04053 PdePage2 =
MiMakeOutswappedPageResident (
04054
MiGetPteAddress (PDE_BASE + (i <<
PAGE_SHIFT)),
04055 &TempPte,
04056 0,
04057 PdePage);
04058
04059
ASSERT (Pfn1->
u2.ShareCount >= 1);
04060
04061 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04062 PageDirectoryMap[i] = TempPte;
04063
MiUnmapPageInHyperSpace (OldIrql2);
04064 PaeVa->PteEntry[i].u.Long = (TempPte.u.Long & ~MM_PAE_PDPTE_MASK);
04065 }
04066
04067 TempPte.u.Flush = OutProcess->
PageDirectoryPte;
04068 TempPte.u.Long &= ~MM_PAE_PDPTE_MASK;
04069 PaeVa->PteEntry[i].u.Flush = TempPte.u.Flush;
04070
04071
04072
04073
04074
04075 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04076
04077 TempPte = PageDirectoryMap[
MiGetPdeOffset(HYPER_SPACE2)];
04078
04079
MiUnmapPageInHyperSpace (OldIrql2);
04080
04081 HyperSpacePageTable =
MiMakeOutswappedPageResident (
04082
MiGetPdeAddress (HYPER_SPACE2),
04083 &TempPte,
04084 0,
04085 PdePage);
04086
04087
ASSERT (Pfn1->
u2.ShareCount >= 1);
04088
04089 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04090 PageDirectoryMap[
MiGetPdeOffset(HYPER_SPACE2)] = TempPte;
04091
MiUnmapPageInHyperSpace (OldIrql2);
04092 TempPte2 = TempPte;
04093
#endif
04094
04095
04096
04097
04098
04099 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04100
04101 TempPte = PageDirectoryMap[
MiGetPdeOffset(
MmWorkingSetList)];
04102
04103
MiUnmapPageInHyperSpace (OldIrql2);
04104
04105 HyperSpacePageTable =
MiMakeOutswappedPageResident (
04106
MiGetPdeAddress (
HYPER_SPACE),
04107 &TempPte,
04108 0,
04109 PdePage);
04110
04111
ASSERT (Pfn1->
u2.ShareCount >= 3);
04112
04113 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql2);
04114
04115
#if !defined (_WIN64)
04116
PageDirectoryMap[
MiGetPdeOffset(PDE_BASE)].u.Flush =
04117 OutProcess->
PageDirectoryPte;
04118
#endif
04119
04120 PageDirectoryMap[
MiGetPdeOffset(
MmWorkingSetList)] = TempPte;
04121
04122
MiUnmapPageInHyperSpace (OldIrql2);
04123
04124
04125
04126
04127
04128
04129 HyperSpacePageTableMap =
MiMapPageInHyperSpace (HyperSpacePageTable, &OldIrql2);
04130 TempPte = HyperSpacePageTableMap[
MiGetPteOffset(
MmWorkingSetList)];
04131
MiUnmapPageInHyperSpace (OldIrql2);
04132 Pfn1 =
MI_PFN_ELEMENT (HyperSpacePageTable);
04133
04134 Pfn1->
u1.WsIndex = 1;
04135
04136 WorkingSetPage =
MiMakeOutswappedPageResident (
04137
MiGetPteAddress (
MmWorkingSetList),
04138 &TempPte,
04139 0,
04140 HyperSpacePageTable);
04141
04142 HyperSpacePageTableMap =
MiMapPageInHyperSpace (HyperSpacePageTable, &OldIrql2);
04143 HyperSpacePageTableMap[
MiGetPteOffset(
MmWorkingSetList)] = TempPte;
04144
#if defined (_X86PAE_)
04145
HyperSpacePageTableMap[0] = TempPte2;
04146
#endif
04147
MiUnmapPageInHyperSpace (OldIrql2);
04148
04149 Pfn1 =
MI_PFN_ELEMENT (WorkingSetPage);
04150
04151 Pfn1->
u1.WsIndex = 2;
04152
04153
UNLOCK_PFN (OldIrql);
04154
04155
LOCK_EXPANSION (OldIrql);
04156
04157
04158
04159
04160
04161 OutProcess->
Vm.
AllowWorkingSetAdjustment =
TRUE;
04162
if (OutProcess->
Vm.
WorkingSetExpansionLinks.Flink ==
MM_WS_SWAPPED_OUT) {
04163 InsertTailList (&
MmWorkingSetExpansionHead.
ListHead,
04164 &OutProcess->
Vm.
WorkingSetExpansionLinks);
04165 }
04166
UNLOCK_EXPANSION (OldIrql);
04167
04168
04169
04170
04171
04172 OutProcess->
WorkingSetPage = WorkingSetPage;
04173
04174
#if !defined (_X86PAE_)
04175
OutProcess->
Vm.
WorkingSetSize = 3;
04176
04177
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->DirectoryTableBase[0],
04178 PdePage);
04179
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->DirectoryTableBase[1],
04180 HyperSpacePageTable);
04181
#else
04182
04183
04184
04185
04186 OutProcess->
Vm.
WorkingSetSize = 7;
04187 Process->DirectoryTableBase[1] = HyperSpacePageTable;
04188
#endif
04189
04190 OutProcess->
ProcessOutswapped =
FALSE;
04191 }
04192
04193
if (
MiHydra ==
TRUE && OutProcess->
Vm.
u.Flags.ProcessInSession == 1) {
04194
MiSessionInSwapProcess (OutProcess);
04195 }
04196
04197 OutProcess->
ProcessOutswapEnabled =
FALSE;
04198
return;
04199 }
04200
04201 PVOID
04202 MiCreatePebOrTeb (
04203 IN
PEPROCESS TargetProcess,
04204 IN ULONG Size
04205 )
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230 {
04231
04232 PVOID Base;
04233
PMMVAD Vad;
04234
04235
04236
04237
04238
04239
04240
04241
04242
LOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
04243
04244
try {
04245 Vad = (
PMMVAD)
NULL;
04246
04247
04248
04249
04250
04251 Base =
MiFindEmptyAddressRangeDown (
04252
ROUND_TO_PAGES (
Size),
04253 ((PCHAR)
MM_HIGHEST_VAD_ADDRESS + 1),
04254
PAGE_SIZE);
04255
04256
04257
04258
04259
04260
04261 Vad = (
PMMVAD)
ExAllocatePoolWithTag (
NonPagedPool,
04262
sizeof(
MMVAD),
04263 ' daV');
04264
if (Vad == (
PMMVAD)0) {
04265
ExRaiseStatus (STATUS_NO_MEMORY);
04266 }
04267
04268 Vad->
StartingVpn =
MI_VA_TO_VPN (Base);
04269 Vad->
EndingVpn =
MI_VA_TO_VPN ((PCHAR)Base +
Size - 1);
04270
04271 Vad->
u.LongFlags = 0;
04272
04273 Vad->
u.VadFlags.CommitCharge =
BYTES_TO_PAGES (
Size);
04274 Vad->
u.VadFlags.MemCommit = 1;
04275 Vad->
u.VadFlags.PrivateMemory = 1;
04276 Vad->
u.VadFlags.Protection =
MM_EXECUTE_READWRITE;
04277
04278
04279
04280
04281
04282 Vad->
u.VadFlags.NoChange = 1;
04283 Vad->
u2.LongFlags2 = 0;
04284 Vad->
u2.VadFlags2.OneSecured = 1;
04285 Vad->
u2.VadFlags2.StoredInVad = 1;
04286 Vad->
u2.VadFlags2.ReadOnly = 0;
04287 Vad->
u3.Secured.StartVpn = (ULONG_PTR)Base;
04288 Vad->
u3.Secured.EndVpn = (ULONG_PTR)
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn);
04289
04290
MiInsertVad (Vad);
04291
04292 } except (
EXCEPTION_EXECUTE_HANDLER) {
04293
04294
04295
04296
04297
04298
04299
if (Vad != (
PMMVAD)
NULL) {
04300
ExFreePool (Vad);
04301 }
04302
04303
UNLOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
04304
KeDetachProcess();
04305
ExRaiseStatus (GetExceptionCode ());
04306 }
04307
04308
UNLOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
04309
04310
return Base;
04311 }
04312
04313 PTEB
04314 MmCreateTeb (
04315 IN
PEPROCESS TargetProcess,
04316 IN PINITIAL_TEB InitialTeb,
04317 IN PCLIENT_ID ClientId
04318 )
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348 {
04349 PTEB TebBase;
04350
04351
04352
04353
04354
04355
04356
KeAttachProcess (&TargetProcess->Pcb);
04357
04358 TebBase = (PTEB)
MiCreatePebOrTeb (TargetProcess,
04359 (ULONG)
sizeof(TEB));
04360
04361
04362
04363
04364
04365
#if defined(_WIN64)
04366
TebBase->NtTib.ExceptionList =
NULL;
04367
#else
04368
TebBase->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
04369
#endif
04370
04371 TebBase->NtTib.SubSystemTib =
NULL;
04372 TebBase->NtTib.Version = OS2_VERSION;
04373 TebBase->NtTib.ArbitraryUserPointer =
NULL;
04374 TebBase->NtTib.Self = (PNT_TIB)TebBase;
04375 TebBase->EnvironmentPointer =
NULL;
04376 TebBase->ProcessEnvironmentBlock = TargetProcess->Peb;
04377 TebBase->ClientId = *ClientId;
04378 TebBase->RealClientId = *ClientId;
04379
04380
if ((
InitialTeb->OldInitialTeb.OldStackBase ==
NULL) &&
04381 (
InitialTeb->OldInitialTeb.OldStackLimit ==
NULL)) {
04382
04383 TebBase->NtTib.StackBase =
InitialTeb->StackBase;
04384 TebBase->NtTib.StackLimit =
InitialTeb->StackLimit;
04385 TebBase->DeallocationStack =
InitialTeb->StackAllocationBase;
04386
04387
#if defined(_IA64_)
04388
TebBase->BStoreLimit =
InitialTeb->BStoreLimit;
04389 TebBase->DeallocationBStore = (PCHAR)
InitialTeb->StackBase
04390 + ((ULONG_PTR)
InitialTeb->StackBase - (ULONG_PTR)
InitialTeb->StackAllocationBase);
04391
#endif
04392
04393 }
04394
else {
04395 TebBase->NtTib.StackBase =
InitialTeb->OldInitialTeb.OldStackBase;
04396 TebBase->NtTib.StackLimit =
InitialTeb->OldInitialTeb.OldStackLimit;
04397 }
04398
04399 TebBase->StaticUnicodeString.Buffer = TebBase->StaticUnicodeBuffer;
04400 TebBase->StaticUnicodeString.MaximumLength = (
USHORT)
sizeof( TebBase->StaticUnicodeBuffer );
04401 TebBase->StaticUnicodeString.Length = (
USHORT)0;
04402
04403
04404
04405
04406
04407 TebBase->ReservedForPerf =
BBTBuffer;
04408
04409
KeDetachProcess();
04410
return TebBase;
04411 }
04412
04413
04414
04415
04416
04417
04418 #define MI_INIT_PEB_FROM_IMAGE(Hdrs, ImgConfig) { \
04419
PebBase->ImageSubsystem = (Hdrs)->OptionalHeader.Subsystem; \
04420
PebBase->ImageSubsystemMajorVersion = \
04421
(Hdrs)->OptionalHeader.MajorSubsystemVersion; \
04422
PebBase->ImageSubsystemMinorVersion = \
04423
(Hdrs)->OptionalHeader.MinorSubsystemVersion; \
04424
\
04425
\
04426 \
04427 \
04428 \
04429 \
04430 if ((Hdrs)->OptionalHeader.Win32VersionValue != 0) { \
04431 PebBase->OSMajorVersion = \
04432 (Hdrs)->OptionalHeader.Win32VersionValue & 0xFF; \
04433 PebBase->OSMinorVersion = \
04434 ((Hdrs)->OptionalHeader.Win32VersionValue >> 8) & 0xFF; \
04435 PebBase->OSBuildNumber = \
04436 (USHORT)(((Hdrs)->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF); \
04437 if ((ImgConfig) != NULL && (ImgConfig)->CSDVersion != 0) { \
04438 PebBase->OSCSDVersion = (ImgConfig)->CSDVersion; \
04439 } \
04440 \
04441 \
04442 \
04443 \
04444 \
04445 \
04446 \
04447 \
04448 \
04449 \
04450 \
04451 \
04452 \
04453 \
04454 \
04455 \
04456 \
04457 \
04458 \
04459 \
04460 \
04461 \
04462 \
04463 \
04464 PebBase->OSPlatformId = \
04465 ((Hdrs)->OptionalHeader.Win32VersionValue >> 30) ^ 0x2; \
04466 } \
04467 }
04468
04469
04470
#if defined(_WIN64)
04471
VOID
04472 MiInitializeWowPeb (
04473 IN PIMAGE_NT_HEADERS NtHeaders,
04474 IN PPEB PebBase,
04475 IN
PEPROCESS TargetProcess
04476 )
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510 {
04511
NTSTATUS Status;
04512 ULONG ReturnedSize;
04513 PPEB32 PebBase32;
04514 ULONG ProcessAffinityMask;
04515 PIMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigData32;
04516
04517 ProcessAffinityMask = 0;
04518 ImageConfigData32 =
NULL;
04519
04520
04521
04522
04523
04524
try {
04525 ImageConfigData32 =
RtlImageDirectoryEntryToData (
04526 PebBase->ImageBaseAddress,
04527
TRUE,
04528 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
04529 &ReturnedSize);
04530
04531
ProbeForRead ((PVOID)ImageConfigData32,
04532
sizeof (*ImageConfigData32),
04533
sizeof (ULONG));
04534
04535
MI_INIT_PEB_FROM_IMAGE ((PIMAGE_NT_HEADERS32)NtHeaders,
04536 ImageConfigData32);
04537
04538
if ((ImageConfigData32 !=
NULL) && (ImageConfigData32->ProcessAffinityMask != 0)) {
04539 ProcessAffinityMask = ImageConfigData32->ProcessAffinityMask;
04540 }
04541
04542 } except (
EXCEPTION_EXECUTE_HANDLER) {
04543
KeDetachProcess();
04544
ExRaiseStatus(STATUS_INVALID_IMAGE_PROTECT);
04545 }
04546
04547
04548
04549
04550
04551 PebBase32 = (PPEB32)
MiCreatePebOrTeb (TargetProcess,
04552 (ULONG)
sizeof (PEB32));
04553
04554
04555
04556
04557
04558
04559 TargetProcess->Wow64Process->Wow64 = PebBase32;
04560
04561
04562
04563
04564
04565 PebBase32->InheritedAddressSpace = PebBase->InheritedAddressSpace;
04566 PebBase32->Mutant = PtrToUlong(PebBase->Mutant);
04567 PebBase32->ImageBaseAddress = PtrToUlong(PebBase->ImageBaseAddress);
04568 PebBase32->AnsiCodePageData = PtrToUlong(PebBase->AnsiCodePageData);
04569 PebBase32->OemCodePageData = PtrToUlong(PebBase->OemCodePageData);
04570 PebBase32->UnicodeCaseTableData = PtrToUlong(PebBase->UnicodeCaseTableData);
04571 PebBase32->NumberOfProcessors = PebBase->NumberOfProcessors;
04572 PebBase32->BeingDebugged = PebBase->BeingDebugged;
04573 PebBase32->NtGlobalFlag = PebBase->NtGlobalFlag;
04574 PebBase32->CriticalSectionTimeout = PebBase->CriticalSectionTimeout;
04575
04576
if (PebBase->HeapSegmentReserve > 1024*1024*1024) {
04577 PebBase32->HeapSegmentReserve = 1024*1024;
04578 }
else {
04579 PebBase32->HeapSegmentReserve = (ULONG)PebBase->HeapSegmentReserve;
04580 }
04581
04582
if (PebBase->HeapSegmentCommit > PebBase32->HeapSegmentReserve) {
04583 PebBase32->HeapSegmentCommit = 2*
PAGE_SIZE;
04584 }
else {
04585 PebBase32->HeapSegmentCommit = (ULONG)PebBase->HeapSegmentCommit;
04586 }
04587
04588 PebBase32->HeapDeCommitTotalFreeThreshold = (ULONG)PebBase->HeapDeCommitTotalFreeThreshold;
04589 PebBase32->HeapDeCommitFreeBlockThreshold = (ULONG)PebBase->HeapDeCommitFreeBlockThreshold;
04590 PebBase32->NumberOfHeaps = PebBase->NumberOfHeaps;
04591 PebBase32->MaximumNumberOfHeaps = (
PAGE_SIZE -
sizeof(PEB32)) /
sizeof(ULONG);
04592 PebBase32->ProcessHeaps = PtrToUlong(PebBase32+1);
04593 PebBase32->OSMajorVersion = PebBase->OSMajorVersion;
04594 PebBase32->OSMinorVersion = PebBase->OSMinorVersion;
04595 PebBase32->OSBuildNumber = PebBase->OSBuildNumber;
04596 PebBase32->OSPlatformId = PebBase->OSPlatformId;
04597 PebBase32->OSCSDVersion = PebBase->OSCSDVersion;
04598 PebBase32->ImageSubsystem = PebBase->ImageSubsystem;
04599 PebBase32->ImageSubsystemMajorVersion = PebBase->ImageSubsystemMajorVersion;
04600 PebBase32->ImageSubsystemMinorVersion = PebBase->ImageSubsystemMinorVersion;
04601 PebBase32->SessionId = TargetProcess->SessionId;
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625 PebBase32->ImageProcessAffinityMask = ProcessAffinityMask;
04626 }
04627
#endif
04628
04629
04630 PPEB
04631 MmCreatePeb (
04632 IN
PEPROCESS TargetProcess,
04633 IN
PINITIAL_PEB InitialPeb
04634 )
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664 {
04665 PPEB PebBase;
04666
USHORT Magic;
04667
USHORT Characteristics;
04668
NTSTATUS Status;
04669 PVOID ViewBase;
04670 LARGE_INTEGER SectionOffset;
04671 PIMAGE_NT_HEADERS NtHeaders;
04672 SIZE_T ViewSize;
04673 ULONG ReturnedSize;
04674 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
04675 ULONG ProcessAffinityMask;
04676
04677 ViewBase =
NULL;
04678 SectionOffset.LowPart = 0;
04679 SectionOffset.HighPart = 0;
04680 ViewSize = 0;
04681
04682
04683
04684
04685
04686
04687
KeAttachProcess (&TargetProcess->Pcb);
04688
04689
04690
04691
04692
04693
Status =
MmMapViewOfSection(
04694
InitNlsSectionPointer,
04695 TargetProcess,
04696 &ViewBase,
04697 0
L,
04698 0
L,
04699 &SectionOffset,
04700 &ViewSize,
04701 ViewShare,
04702 MEM_TOP_DOWN | SEC_NO_CHANGE,
04703 PAGE_READONLY
04704 );
04705
04706
if ( !
NT_SUCCESS(
Status) ) {
04707
KeDetachProcess();
04708
ExRaiseStatus(
Status);
04709 }
04710
04711 PebBase = (PPEB)
MiCreatePebOrTeb (TargetProcess,
04712 (ULONG)
sizeof( PEB ));
04713
04714
04715
04716
04717
04718 PebBase->InheritedAddressSpace = InitialPeb->InheritedAddressSpace;
04719 PebBase->Mutant = InitialPeb->Mutant;
04720 PebBase->ImageBaseAddress = TargetProcess->SectionBaseAddress;
04721
04722 PebBase->AnsiCodePageData = (PVOID)((PUCHAR)ViewBase+
InitAnsiCodePageDataOffset);
04723 PebBase->OemCodePageData = (PVOID)((PUCHAR)ViewBase+
InitOemCodePageDataOffset);
04724 PebBase->UnicodeCaseTableData = (PVOID)((PUCHAR)ViewBase+
InitUnicodeCaseTableDataOffset);
04725
04726 PebBase->NumberOfProcessors =
KeNumberProcessors;
04727 PebBase->BeingDebugged = (BOOLEAN)(TargetProcess->DebugPort !=
NULL ?
TRUE :
FALSE);
04728 PebBase->NtGlobalFlag =
NtGlobalFlag;
04729 PebBase->CriticalSectionTimeout =
MmCriticalSectionTimeout;
04730 PebBase->HeapSegmentReserve =
MmHeapSegmentReserve;
04731 PebBase->HeapSegmentCommit =
MmHeapSegmentCommit;
04732 PebBase->HeapDeCommitTotalFreeThreshold =
MmHeapDeCommitTotalFreeThreshold;
04733 PebBase->HeapDeCommitFreeBlockThreshold =
MmHeapDeCommitFreeBlockThreshold;
04734 PebBase->NumberOfHeaps = 0;
04735 PebBase->MaximumNumberOfHeaps = (
PAGE_SIZE -
sizeof( PEB )) /
sizeof( PVOID );
04736 PebBase->ProcessHeaps = (PVOID *)(PebBase+1);
04737
04738 PebBase->OSMajorVersion =
NtMajorVersion;
04739 PebBase->OSMinorVersion =
NtMinorVersion;
04740 PebBase->OSBuildNumber = (
USHORT)(
NtBuildNumber & 0x3FFF);
04741 PebBase->OSPlatformId = 2;
04742 PebBase->OSCSDVersion = (
USHORT)
CmNtCSDVersion;
04743
04744
04745
04746
04747
04748
04749
04750
try {
04751 NtHeaders =
RtlImageNtHeader( PebBase->ImageBaseAddress );
04752 Magic = NtHeaders->OptionalHeader.Magic;
04753 Characteristics = NtHeaders->FileHeader.Characteristics;
04754 } except (
EXCEPTION_EXECUTE_HANDLER) {
04755
KeDetachProcess();
04756
ExRaiseStatus(STATUS_INVALID_IMAGE_PROTECT);
04757 }
04758
04759
if (NtHeaders !=
NULL) {
04760
04761 ProcessAffinityMask = 0;
04762
#if defined(_WIN64)
04763
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
04764
04765
04766
04767
04768
04769
04770 MiInitializeWowPeb (NtHeaders, PebBase, TargetProcess);
04771
04772 }
else
04773
#endif
04774
{
04775
try {
04776 ImageConfigData =
RtlImageDirectoryEntryToData (
04777 PebBase->ImageBaseAddress,
04778
TRUE,
04779 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
04780 &ReturnedSize);
04781
04782
ProbeForRead ((PVOID)ImageConfigData,
04783
sizeof (*ImageConfigData),
04784
sizeof (ULONG));
04785
04786
MI_INIT_PEB_FROM_IMAGE(NtHeaders, ImageConfigData);
04787
04788
if (ImageConfigData !=
NULL && ImageConfigData->ProcessAffinityMask != 0) {
04789 ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
04790 }
04791
04792 } except (
EXCEPTION_EXECUTE_HANDLER) {
04793
KeDetachProcess();
04794
ExRaiseStatus(STATUS_INVALID_IMAGE_PROTECT);
04795 }
04796
04797 }
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
if (Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) {
04810
04811
04812
04813
04814
04815
04816
do {
04817 PebBase->ImageProcessAffinityMask = (KAFFINITY)(0x1 <<
MmRotatingUniprocessorNumber);
04818
if (++
MmRotatingUniprocessorNumber >=
KeNumberProcessors) {
04819
MmRotatingUniprocessorNumber = 0;
04820 }
04821 }
while ((PebBase->ImageProcessAffinityMask &
KeActiveProcessors) == 0);
04822 }
else {
04823
04824
if (ProcessAffinityMask != 0) {
04825
04826
04827
04828
04829
04830
04831 PebBase->ImageProcessAffinityMask = ProcessAffinityMask;
04832 }
04833 }
04834 }
04835
04836 PebBase->SessionId = TargetProcess->SessionId;
04837
04838
KeDetachProcess();
04839
return PebBase;
04840 }
04841
04842
VOID
04843 MmDeleteTeb (
04844 IN
PEPROCESS TargetProcess,
04845 IN PVOID TebBase
04846 )
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871 {
04872 PVOID EndingAddress;
04873
PMMVAD Vad;
04874
NTSTATUS Status;
04875
PMMSECURE_ENTRY Secure;
04876
04877 EndingAddress = ((PCHAR)TebBase +
04878
ROUND_TO_PAGES (
sizeof(TEB)) - 1);
04879
04880
04881
04882
04883
04884
KeAttachProcess (&TargetProcess->Pcb);
04885
04886
04887
04888
04889
04890
04891
04892
04893
LOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
04894
04895 Vad =
MiLocateAddress (TebBase);
04896
04897
ASSERT (Vad != (
PMMVAD)
NULL);
04898
04899
ASSERT ((Vad->
StartingVpn ==
MI_VA_TO_VPN (TebBase)) &&
04900 (Vad->
EndingVpn ==
MI_VA_TO_VPN (EndingAddress)));
04901
04902
04903
04904
04905
04906
04907
04908
ASSERT (Vad->
u.VadFlags.NoChange == 1);
04909
if (Vad->
u2.VadFlags2.OneSecured) {
04910
Status = STATUS_SUCCESS;
04911 }
04912
else {
04913
ASSERT (Vad->
u2.VadFlags2.MultipleSecured);
04914
ASSERT (IsListEmpty (&Vad->
u3.List) == 0);
04915
04916
04917
04918
04919
04920
04921
04922
04923 Secure = CONTAINING_RECORD (Vad->
u3.List.Flink,
04924
MMSECURE_ENTRY,
04925
List);
04926
04927
if (Secure->
List.Flink == &Vad->
u3.List) {
04928
Status = STATUS_SUCCESS;
04929 }
04930
else {
04931
Status = STATUS_NOT_FOUND;
04932 }
04933 }
04934
04935
if (
NT_SUCCESS(
Status)) {
04936
04937
MiRemoveVad (Vad);
04938
ExFreePool (Vad);
04939
04940
MiDeleteFreeVm (TebBase, EndingAddress);
04941 }
04942
04943
UNLOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
04944
KeDetachProcess();
04945 }
04946
04947
VOID
04948 MmAllowWorkingSetExpansion (
04949 VOID
04950 )
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975 {
04976
04977
PEPROCESS CurrentProcess;
04978 KIRQL OldIrql;
04979
04980
04981
04982
04983
04984
04985 CurrentProcess =
PsGetCurrentProcess();
04986
04987
LOCK_EXPANSION (OldIrql);
04988
04989
if (!CurrentProcess->
Vm.
AllowWorkingSetAdjustment) {
04990 CurrentProcess->
Vm.
AllowWorkingSetAdjustment =
TRUE;
04991
04992 InsertTailList (&
MmWorkingSetExpansionHead.
ListHead,
04993 &CurrentProcess->
Vm.
WorkingSetExpansionLinks);
04994 }
04995
04996
UNLOCK_EXPANSION (OldIrql);
04997
return;
04998 }
04999
05000
#if DBG
05001
ULONG MiDeleteLocked;
05002
#endif
05003
05004
05005
VOID
05006 MiDeleteAddressesInWorkingSet (
05007 IN
PEPROCESS Process
05008 )
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031 {
05032
PMMWSLE Wsle;
05033 ULONG index;
05034 ULONG Entry;
05035 PVOID Va;
05036 KIRQL OldIrql;
05037
#if DBG
05038
PVOID SwapVa;
05039
PMMPTE PointerPte;
05040
PMMPFN Pfn1;
05041
PMMWSLE LastWsle;
05042
#endif
05043
05044
05045
05046
05047
05048
05049 index = 2;
05050 Wsle = &
MmWsle[index];
05051
05052
MmWorkingSetList->
HashTable =
NULL;
05053
05054
05055
05056
05057
05058
05059
while (index <=
MmWorkingSetList->
LastEntry) {
05060
if (Wsle->
u1.e1.Valid == 1) {
05061
05062
#if defined (_WIN64)
05063
ASSERT(
MiGetPpeAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05064
#endif
05065
ASSERT(
MiGetPdeAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05066
ASSERT(
MiGetPteAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05067
05068
if (Wsle->
u1.VirtualAddress < (PVOID)MM_HIGHEST_USER_ADDRESS) {
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
if (Wsle->
u1.e1.Direct == 0) {
05079 Process->Vm.VmWorkingSetList->NonDirectCount -= 1;
05080 }
05081
05082
05083
05084
05085
05086 Va = Wsle->
u1.VirtualAddress;
05087
05088
MiReleaseWsle (index, &Process->Vm);
05089
LOCK_PFN (OldIrql);
05090
MiDeleteValidAddress (Va, Process);
05091
UNLOCK_PFN (OldIrql);
05092
05093
if (index <
MmWorkingSetList->
FirstDynamic) {
05094
05095
05096
05097
05098
05099
MmWorkingSetList->
FirstDynamic -= 1;
05100
05101
if (index !=
MmWorkingSetList->
FirstDynamic) {
05102
05103 Entry =
MmWorkingSetList->
FirstDynamic;
05104
#if DBG
05105
MiDeleteLocked += 1;
05106 SwapVa =
MmWsle[
MmWorkingSetList->
FirstDynamic].
u1.VirtualAddress;
05107 SwapVa =
PAGE_ALIGN (SwapVa);
05108
05109 PointerPte =
MiGetPteAddress (SwapVa);
05110 Pfn1 =
MI_PFN_ELEMENT (PointerPte->
u.Hard.PageFrameNumber);
05111
05112
ASSERT (Entry ==
MiLocateWsle (SwapVa,
MmWorkingSetList, Pfn1->
u1.WsIndex));
05113
#endif
05114
MiSwapWslEntries (Entry, index, &Process->Vm);
05115 }
05116 }
05117 }
05118 }
05119 index += 1;
05120 Wsle += 1;
05121 }
05122
05123
#if DBG
05124
Wsle = &
MmWsle[2];
05125 LastWsle = &
MmWsle[
MmWorkingSetList->
LastInitializedWsle];
05126
while (Wsle <= LastWsle) {
05127
if (Wsle->
u1.e1.Valid == 1) {
05128
#if defined (_WIN64)
05129
ASSERT(
MiGetPpeAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05130
#endif
05131
ASSERT(
MiGetPdeAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05132
ASSERT(
MiGetPteAddress(Wsle->
u1.VirtualAddress)->u.Hard.Valid == 1);
05133 }
05134 Wsle += 1;
05135 }
05136
#endif
05137
05138 }
05139
05140
05141
VOID
05142 MiDeleteValidAddress (
05143 IN PVOID Va,
05144 IN
PEPROCESS CurrentProcess
05145 )
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173 {
05174
PMMPTE PointerPde;
05175
PMMPTE PointerPte;
05176
PMMPFN Pfn1;
05177
PMMCLONE_BLOCK CloneBlock;
05178
PMMCLONE_DESCRIPTOR CloneDescriptor;
05179 PFN_NUMBER PageFrameIndex;
05180
05181 PointerPte =
MiGetPteAddress (Va);
05182
05183
#if defined (_WIN64)
05184
ASSERT(
MiGetPpeAddress(Va)->u.Hard.Valid == 1);
05185
#endif
05186
ASSERT(
MiGetPdeAddress(Va)->u.Hard.Valid == 1);
05187
ASSERT (PointerPte->
u.Hard.Valid == 1);
05188
05189 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
05190 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05191 CloneDescriptor =
NULL;
05192
05193
if (Pfn1->
u3.e1.PrototypePte == 1) {
05194
05195 CloneBlock = (
PMMCLONE_BLOCK)Pfn1->
PteAddress;
05196
05197
05198
05199
05200
05201
05202
MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
05203
05204
05205
05206
05207
05208
05209 PointerPde =
MiGetPteAddress (PointerPte);
05210
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
05211
05212
05213
05214
05215
05216
MiDecrementShareCount (PageFrameIndex);
05217
05218
05219
05220
05221
05222
05223
if (Va <= MM_HIGHEST_USER_ADDRESS) {
05224
05225
05226
05227
05228
05229 CloneDescriptor =
MiLocateCloneAddress ((PVOID)CloneBlock);
05230 }
05231 }
else {
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
05242
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
05243
05244
MI_SET_PFN_DELETED (Pfn1);
05245
05246
05247
05248
05249
05250
05251
MiDecrementShareCountOnly (PageFrameIndex);
05252
05253
05254
05255
05256
05257 CurrentProcess->NumberOfPrivatePages -= 1;
05258 }
05259
05260
05261
05262
05263
05264
05265
05266
05267 PointerPte->
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
05268
05269
if (CloneDescriptor !=
NULL) {
05270
05271
05272
05273
05274
05275
05276
05277
05278
if (
MiDecrementCloneBlockReference ( CloneDescriptor,
05279 CloneBlock,
05280 CurrentProcess )) {
05281
05282 }
05283 }
05284 }
05285
05286 PFN_NUMBER
05287 MiMakeOutswappedPageResident (
05288 IN
PMMPTE ActualPteAddress,
05289 IN OUT
PMMPTE PointerTempPte,
05290 IN ULONG Global,
05291 IN PFN_NUMBER ContainingPage
05292 )
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324 {
05325
MMPTE TempPte;
05326 KIRQL OldIrql;
05327 PFN_NUMBER PageFrameIndex;
05328
PMMPFN Pfn1;
05329 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + 2];
05330
PMDL Mdl;
05331 LARGE_INTEGER StartingOffset;
05332
KEVENT Event;
05333 IO_STATUS_BLOCK IoStatus;
05334 PFN_NUMBER PageFileNumber;
05335
NTSTATUS Status;
05336 PPFN_NUMBER Page;
05337 ULONG RefaultCount;
05338 PVOID HyperVa;
05339
05340
MM_PFN_LOCK_ASSERT();
05341
05342 OldIrql =
APC_LEVEL;
05343
05344
ASSERT (PointerTempPte->u.Hard.Valid == 0);
05345
05346
if (PointerTempPte->u.Long ==
MM_KERNEL_DEMAND_ZERO_PTE) {
05347
05348
05349
05350
05351
05352
MiEnsureAvailablePageOrWait (
NULL,
NULL);
05353 PageFrameIndex =
MiRemoveAnyPage (
05354
MI_GET_PAGE_COLOR_FROM_PTE (ActualPteAddress));
05355
05356
MI_MAKE_VALID_PTE (TempPte,
05357 PageFrameIndex,
05358
MM_READWRITE,
05359 ActualPteAddress );
05360
MI_SET_PTE_DIRTY (TempPte);
05361
MI_SET_GLOBAL_STATE (TempPte, Global);
05362
05363
MI_WRITE_VALID_PTE (PointerTempPte, TempPte);
05364
MiInitializePfnForOtherProcess (PageFrameIndex,
05365 ActualPteAddress,
05366 ContainingPage);
05367
05368 }
else if (PointerTempPte->u.Soft.Transition == 1) {
05369
05370 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerTempPte);
05371 PointerTempPte->u.Trans.Protection =
MM_READWRITE;
05372 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05373
05374
05375
05376
05377
05378
if (Pfn1->
u3.e1.PageLocation !=
ActiveAndValid) {
05379
MiUnlinkPageFromList (Pfn1);
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389
05390
ASSERT ((Pfn1->
u3.e2.ReferenceCount == 0) ||
05391 (Pfn1->
u3.e1.LockCharged == 1));
05392
05393 Pfn1->
u3.e2.ReferenceCount += 1;
05394 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
05395 }
05396
05397
05398
05399
05400
05401
05402
05403 Pfn1->
u2.ShareCount += 1;
05404 Pfn1->
u3.e1.Modified = 1;
05405
if (Pfn1->
u3.e1.WriteInProgress == 0) {
05406
05407
05408
05409
05410
05411
MiReleasePageFileSpace (Pfn1->
OriginalPte);
05412 Pfn1->
OriginalPte.
u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
05413 }
05414
05415
MI_MAKE_TRANSITION_PTE_VALID (TempPte, PointerTempPte);
05416
05417
MI_SET_PTE_DIRTY (TempPte);
05418
MI_SET_GLOBAL_STATE (TempPte, Global);
05419
MI_WRITE_VALID_PTE (PointerTempPte, TempPte);
05420
05421 }
else {
05422
05423
05424
05425
05426
05427
05428 PointerTempPte->u.Soft.Protection =
MM_READWRITE;
05429
MiEnsureAvailablePageOrWait (
NULL,
NULL);
05430 PageFrameIndex =
MiRemoveAnyPage (
05431
MI_GET_PAGE_COLOR_FROM_PTE (ActualPteAddress));
05432
05433
05434
05435
05436
05437
05438
05439
MiInitializePfnForOtherProcess (PageFrameIndex,
05440 ActualPteAddress,
05441 ContainingPage);
05442
05443
KeInitializeEvent (&
Event, NotificationEvent,
FALSE);
05444
05445
05446
05447
05448
05449 TempPte = *PointerTempPte;
05450 PageFileNumber =
GET_PAGING_FILE_NUMBER (TempPte);
05451
05452 StartingOffset.QuadPart = (LONGLONG)(
GET_PAGING_FILE_OFFSET (TempPte)) <<
05453
PAGE_SHIFT;
05454
05455 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05456
05457
05458
05459
05460
05461 Mdl = (
PMDL)&MdlHack[0];
05462
MmInitializeMdl(Mdl,
05463
MiGetVirtualAddressMappedByPte (ActualPteAddress),
05464
PAGE_SIZE);
05465 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
05466
05467 Page = (PPFN_NUMBER)(Mdl + 1);
05468 *Page = PageFrameIndex;
05469
05470
UNLOCK_PFN (OldIrql);
05471
05472
#if DBG
05473
HyperVa =
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql);
05474 RtlFillMemoryUlong (HyperVa,
05475
PAGE_SIZE,
05476 0x34785690);
05477
MiUnmapPageInHyperSpace (OldIrql);
05478
#endif
05479
05480
05481
05482
05483
05484 RefaultCount =
MiIoRetryLevel;
05485
05486 Refault:
05487
Status =
IoPageRead (
MmPagingFile[PageFileNumber]->
File,
05488 Mdl,
05489 &StartingOffset,
05490 &
Event,
05491 &IoStatus
05492 );
05493
05494
if (
Status == STATUS_PENDING) {
05495
KeWaitForSingleObject( &
Event,
05496
WrPageIn,
05497
KernelMode,
05498
FALSE,
05499 (PLARGE_INTEGER)
NULL);
05500
Status = IoStatus.Status;
05501 }
05502
05503
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
05504
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
05505 }
05506
05507
if (
NT_SUCCESS(
Status)) {
05508
if (IoStatus.Information !=
PAGE_SIZE) {
05509
KeBugCheckEx (KERNEL_STACK_INPAGE_ERROR,
05510 2,
05511 IoStatus.Status,
05512 PageFileNumber,
05513 StartingOffset.LowPart);
05514 }
05515 }
05516
05517
if ((!
NT_SUCCESS(
Status)) || (!
NT_SUCCESS(IoStatus.Status))) {
05518
if (((
MmIsRetryIoStatus(
Status)) ||
05519 (
MmIsRetryIoStatus(IoStatus.Status))) &&
05520 (RefaultCount != 0)) {
05521
05522
05523
05524
05525
05526
05527
KeDelayExecutionThread (
KernelMode,
05528
FALSE,
05529 &
MmHalfSecond);
05530
KeClearEvent (&
Event);
05531 RefaultCount -= 1;
05532
goto Refault;
05533 }
05534 KdPrint((
"MMINPAGE: status %lx io-status %lx\n",
05535
Status, IoStatus.Status));
05536
KeBugCheckEx (KERNEL_STACK_INPAGE_ERROR,
05537
Status,
05538 IoStatus.Status,
05539 PageFileNumber,
05540 StartingOffset.LowPart);
05541 }
05542
05543
LOCK_PFN (OldIrql);
05544
05545
05546
05547
05548
05549
MiReleasePageFileSpace (TempPte);
05550 Pfn1->
OriginalPte.
u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
05551
05552
MI_MAKE_VALID_PTE (TempPte,
05553 PageFrameIndex,
05554
MM_READWRITE,
05555 ActualPteAddress );
05556
MI_SET_PTE_DIRTY (TempPte);
05557 Pfn1->
u3.e1.Modified = 1;
05558
MI_SET_GLOBAL_STATE (TempPte, Global);
05559
05560
MI_WRITE_VALID_PTE (PointerTempPte, TempPte);
05561 }
05562
return PageFrameIndex;
05563 }
05564
05565
05566
VOID
05567 MmSetMemoryPriorityProcess(
05568 IN
PEPROCESS Process,
05569 IN UCHAR MemoryPriority
05570 )
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590 {
05591 KIRQL OldIrql;
05592 UCHAR OldPriority;
05593
05594
if (
MmSystemSize ==
MmSmallSystem &&
MmNumberOfPhysicalPages < ((15*1024*1024)/
PAGE_SIZE)) {
05595
05596
05597
05598
05599
05600 MemoryPriority =
MEMORY_PRIORITY_BACKGROUND;
05601 }
05602
05603
LOCK_EXPANSION (OldIrql);
05604
05605 OldPriority = Process->Vm.MemoryPriority;
05606 Process->Vm.MemoryPriority = MemoryPriority;
05607
05608
UNLOCK_EXPANSION (OldIrql);
05609
05610
#ifndef _MI_USE_CLAIMS_
05611
if (OldPriority > MemoryPriority &&
MmAvailablePages <
MmMoreThanEnoughFreePages) {
05612
05613
05614
05615
05616
05617
PMMSUPPORT VmSupport;
05618 ULONG i;
05619 ULONG Trim;
05620 LOGICAL Attached;
05621
05622 VmSupport = &Process->Vm;
05623 i = VmSupport->
WorkingSetSize - VmSupport->
MaximumWorkingSetSize;
05624
if ((LONG)i > 0) {
05625 Trim = i;
05626
if (Trim >
MmWorkingSetReductionMax) {
05627 Trim =
MmWorkingSetReductionMax;
05628 }
05629
if (Process !=
PsGetCurrentProcess()) {
05630
KeAttachProcess (&Process->Pcb);
05631 Attached =
TRUE;
05632 }
05633
else {
05634 Attached =
FALSE;
05635 }
05636
LOCK_WS (Process);
05637
05638 Trim =
MiTrimWorkingSet (Trim,
05639 VmSupport,
05640
FALSE);
05641
05642
MmWorkingSetList->
Quota = VmSupport->
WorkingSetSize;
05643
if (
MmWorkingSetList->
Quota < VmSupport->
MinimumWorkingSetSize) {
05644
MmWorkingSetList->
Quota = VmSupport->
MinimumWorkingSetSize;
05645 }
05646
05647
UNLOCK_WS (Process);
05648
if (Attached ==
TRUE) {
05649
KeDetachProcess();
05650 }
05651 }
05652 }
05653
#endif
05654
return;
05655 }
05656
05657
05658
PMMVAD
05659 MiAllocateVad(
05660 IN ULONG_PTR StartingVirtualAddress,
05661 IN ULONG_PTR EndingVirtualAddress,
05662 IN LOGICAL Deletable
05663 )
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686 {
05687
PMMVAD Vad;
05688
05689
ASSERT (StartingVirtualAddress <= EndingVirtualAddress);
05690
05691 Vad = (
PMMVAD)
ExAllocatePoolWithTag (
NonPagedPool,
sizeof(
MMVAD), ' daV');
05692
05693
if (Vad ==
NULL) {
05694
return NULL;
05695 }
05696
05697
05698
05699
05700
05701 Vad->
StartingVpn =
MI_VA_TO_VPN (StartingVirtualAddress);
05702 Vad->
EndingVpn =
MI_VA_TO_VPN (EndingVirtualAddress);
05703
05704
05705
05706
05707
05708 Vad->
u.LongFlags = 0;
05709 Vad->
u.VadFlags.CommitCharge =
MM_MAX_COMMIT;
05710 Vad->
u.VadFlags.Protection =
MM_READONLY;
05711 Vad->
u.VadFlags.PrivateMemory = 1;
05712
05713 Vad->
u2.LongFlags2 = 0;
05714
05715
if (Deletable ==
TRUE) {
05716 Vad->
u.VadFlags.NoChange = 0;
05717 Vad->
u2.VadFlags2.OneSecured = 0;
05718 Vad->
u2.VadFlags2.StoredInVad = 0;
05719 Vad->
u2.VadFlags2.ReadOnly = 0;
05720 Vad->
u3.Secured.StartVpn = 0;
05721 Vad->
u3.Secured.EndVpn = 0;
05722 }
05723
else {
05724 Vad->
u.VadFlags.NoChange = 1;
05725 Vad->
u2.VadFlags2.OneSecured = 1;
05726 Vad->
u2.VadFlags2.StoredInVad = 1;
05727 Vad->
u2.VadFlags2.ReadOnly = 1;
05728 Vad->
u3.Secured.StartVpn = StartingVirtualAddress;
05729 Vad->
u3.Secured.EndVpn = EndingVirtualAddress;
05730 }
05731
05732
return Vad;
05733 }
05734
05735
#if 0
05736
VOID
05737 MiVerifyReferenceCounts (
05738 IN ULONG PdePage
05739 )
05740
05741
05742
05743
05744
05745 {
05746
PMMPFN Pfn1;
05747
PMMPFN Pfn3;
05748
PMMPTE Pte1;
05749 ULONG Share = 0;
05750 ULONG Valid = 0;
05751 ULONG i, ix, iy;
05752
PMMPTE PageDirectoryMap;
05753 KIRQL OldIrql;
05754
05755 PageDirectoryMap = (
PMMPTE)
MiMapPageInHyperSpace (PdePage, &OldIrql);
05756 Pfn1 =
MI_PFN_ELEMENT (PdePage);
05757 Pte1 = (
PMMPTE)PageDirectoryMap;
05758
05759
05760
05761
05762
05763 ix =
MiGetPdeOffset(CODE_START);
05764
05765
for (i = 0;i < ix; i += 1) {
05766
if (Pte1->
u.Hard.Valid == 1) {
05767 Valid += 1;
05768 }
else if ((Pte1->
u.Soft.Prototype == 0) &&
05769 (Pte1->
u.Soft.Transition == 1)) {
05770 Pfn3 =
MI_PFN_ELEMENT (Pte1->
u.Trans.PageFrameNumber);
05771
if (Pfn3->
u3.e1.PageLocation ==
ActiveAndValid) {
05772
ASSERT (Pfn1->
u2.ShareCount > 1);
05773 Valid += 1;
05774 }
else {
05775 Share += 1;
05776 }
05777 }
05778 Pte1 += 1;
05779 }
05780
05781 iy =
MiGetPdeOffset(PTE_BASE);
05782 Pte1 = &PageDirectoryMap[iy];
05783 ix =
MiGetPdeOffset(HYPER_SPACE_END) + 1;
05784
05785
for (i = iy; i < ix; i += 1) {
05786
if (Pte1->
u.Hard.Valid == 1) {
05787 Valid += 1;
05788 }
else if ((Pte1->
u.Soft.Prototype == 0) &&
05789 (Pte1->
u.Soft.Transition == 1)) {
05790 Pfn3 =
MI_PFN_ELEMENT (Pte1->
u.Trans.PageFrameNumber);
05791
if (Pfn3->
u3.e1.PageLocation ==
ActiveAndValid) {
05792
ASSERT (Pfn1->
u2.ShareCount > 1);
05793 Valid += 1;
05794 }
else {
05795 Share += 1;
05796 }
05797 }
05798 Pte1 += 1;
05799 }
05800
05801
if (Pfn1->
u2.ShareCount != (Share+Valid+1)) {
05802
DbgPrint (
"MMPROCSUP - PDE page %lx ShareCount %lx found %lx\n",
05803 PdePage, Pfn1->
u2.ShareCount, Valid+Share+1);
05804 }
05805
05806
MiUnmapPageInHyperSpace (OldIrql);
05807
ASSERT (Pfn1->
u2.ShareCount == (Share+Valid+1));
05808
return;
05809 }
05810
#endif //0
05811
05812
#if defined (_X86PAE_)
05813
05814
VOID
05815 MiPaeInitialize (
05816 VOID
05817 )
05818 {
05819 InitializeListHead (&MiFirstFreePae.PaeEntry.ListHead);
05820 }
05821
05822 ULONG
05823 MiPaeAllocate (
05824 OUT PPAE_ENTRY *Va
05825 )
05826
05827
05828
05829
05830
05831
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854 {
05855 ULONG i;
05856 PVOID Entry;
05857
PMMPFN Pfn1;
05858 KIRQL OldIrql;
05859 LOGICAL FlushedOnce;
05860 PPAE_ENTRY Pae;
05861 PPAE_ENTRY PaeBase;
05862
05863 FlushedOnce =
FALSE;
05864
05865
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
05866
05867
LOCK_PFN (OldIrql);
05868
05869
do {
05870
05871
if (MiFreePaes != 0) {
05872
05873
ASSERT (IsListEmpty (&MiFirstFreePae.PaeEntry.ListHead) == 0);
05874
05875 Pae = (PPAE_ENTRY) RemoveHeadList (&MiFirstFreePae.PaeEntry.ListHead);
05876
05877 PaeBase = (PPAE_ENTRY)
PAGE_ALIGN(Pae);
05878 PaeBase->PaeEntry.EntriesInUse += 1;
05879
#if DBG
05880
RtlZeroMemory ((PVOID)Pae,
sizeof(PAE_ENTRY));
05881
05882 Pfn1 =
MI_PFN_ELEMENT (PaeBase->PaeEntry.PageFrameNumber);
05883
ASSERT (Pfn1->
u2.ShareCount == 1);
05884
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
05885
ASSERT (Pfn1->
u3.e1.PageLocation == ActiveAndValid);
05886
#endif
05887
05888 MiFreePaes -= 1;
05889
UNLOCK_PFN (OldIrql);
05890
05891
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
05892 *Va = Pae;
05893
05894
return (PaeBase->PaeEntry.PageFrameNumber <<
PAGE_SHIFT) +
BYTE_OFFSET (Pae);
05895 }
05896
05897
UNLOCK_PFN (OldIrql);
05898
05899
if (FlushedOnce ==
TRUE) {
05900
break;
05901 }
05902
05903
05904
05905
05906
05907 Entry =
MiPaeReplenishList ();
05908
05909
if (Entry ==
NULL) {
05910
05911 InterlockedIncrement (&MiDelayPageFaults);
05912
05913
05914
05915
05916
05917
MiEmptyAllWorkingSets ();
05918
MiFlushAllPages();
05919
05920
KeDelayExecutionThread (KernelMode,
05921 FALSE,
05922 &MmHalfSecond);
05923
05924 InterlockedDecrement (&MiDelayPageFaults);
05925
05926 FlushedOnce =
TRUE;
05927
05928
LOCK_PFN (OldIrql);
05929
05930
05931
05932
05933
05934
05935
05936
if (MiFreePaes < MINIMUM_PAE_THRESHOLD) {
05937
UNLOCK_PFN (OldIrql);
05938
MiPaeReplenishList ();
05939
LOCK_PFN (OldIrql);
05940 }
05941
05942
continue;
05943 }
05944
LOCK_PFN (OldIrql);
05945
05946 }
while (
TRUE);
05947
05948
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
05949
05950
return 0;
05951 }
05952
05953 PVOID
05954 MiPaeFree (
05955 PPAE_ENTRY Pae
05956 )
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979 {
05980
PMMPTE PointerPte;
05981
PMMPFN Pfn1;
05982 KIRQL OldIrql;
05983 ULONG i;
05984 PLIST_ENTRY NextEntry;
05985 PFN_NUMBER PageFrameIndex;
05986 PPAE_ENTRY PaeBase;
05987
05988
MM_PFN_LOCK_ASSERT();
05989
05990
if (
MI_IS_PHYSICAL_ADDRESS(Pae) == 0) {
05991 PointerPte =
MiGetPteAddress (Pae);
05992 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
05993 }
05994
else {
05995 PointerPte =
NULL;
05996 PageFrameIndex =
MI_CONVERT_PHYSICAL_TO_PFN (Pae);
05997 }
05998
05999 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06000
06001
ASSERT (Pfn1->
u2.ShareCount == 1);
06002
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
06003
ASSERT (Pfn1->
u3.e1.PageLocation == ActiveAndValid);
06004
06005
06006
06007
06008
06009
ASSERT (PageFrameIndex <= MM_HIGHEST_PAE_PAGE);
06010
06011 PaeBase = (PPAE_ENTRY)
PAGE_ALIGN(Pae);
06012 PaeBase->PaeEntry.EntriesInUse -= 1;
06013
06014
if ((PaeBase->PaeEntry.EntriesInUse == 0) &&
06015 (MiFreePaes > EXCESS_PAE_THRESHOLD)) {
06016
06017
06018
06019
06020
06021 i = 1;
06022 NextEntry = MiFirstFreePae.PaeEntry.ListHead.Flink;
06023
while (NextEntry != &MiFirstFreePae.PaeEntry.ListHead) {
06024
06025 Pae = CONTAINING_RECORD (NextEntry,
06026 PAE_ENTRY,
06027 PaeEntry.ListHead);
06028
06029
if (
PAGE_ALIGN(Pae) == PaeBase) {
06030 RemoveEntryList (NextEntry);
06031 i += 1;
06032 }
06033 NextEntry = Pae->PaeEntry.ListHead.Flink;
06034 }
06035
ASSERT (i == PAES_PER_PAGE - 1);
06036 MiFreePaes -= (PAES_PER_PAGE - 1);
06037
06038
return (PVOID)PaeBase;
06039 }
06040
06041 InsertTailList (&MiFirstFreePae.PaeEntry.ListHead, &Pae->PaeEntry.ListHead);
06042 MiFreePaes += 1;
06043
06044
return NULL;
06045 }
06046
06047 PVOID
06048
MiPaeReplenishList (
06049 VOID
06050 )
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068
06069
06070
06071
06072 {
06073
PMMPFN Pfn1;
06074 KIRQL OldIrql;
06075 LONG start;
06076 ULONG i;
06077 PFN_NUMBER count;
06078 PFN_NUMBER Page;
06079 PFN_NUMBER LowPage;
06080 PFN_NUMBER HighPage;
06081
MMLISTS PageListType;
06082
PMMPTE PointerPte;
06083 PVOID BaseAddress;
06084 PPAE_ENTRY Pae;
06085 ULONG NumberOfPages;
06086
MMPTE TempPte;
06087 ULONG PageColor;
06088
06089
if (
MiNoLowMemory ==
TRUE) {
06090 BaseAddress =
MiAllocateLowMemory (PAGE_SIZE,
06091 0,
06092 0xFFFFF,
06093 0,
06094 (PVOID)0x123,
06095 'DeaP');
06096
if (BaseAddress ==
NULL) {
06097
return NULL;
06098 }
06099
06100 Page =
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress(BaseAddress));
06101
06102 Pae = (PPAE_ENTRY) BaseAddress;
06103 Pae->PaeEntry.EntriesInUse = 0;
06104 Pae->PaeEntry.PageFrameNumber = Page;
06105 Pae += 1;
06106
06107
LOCK_PFN (OldIrql);
06108
06109
for (i = 1; i < PAES_PER_PAGE; i += 1) {
06110 InsertTailList (&MiFirstFreePae.PaeEntry.ListHead,
06111 &Pae->PaeEntry.ListHead);
06112 Pae += 1;
06113 MiFreePaes += 1;
06114 }
06115
06116
UNLOCK_PFN (OldIrql);
06117
return BaseAddress;
06118 }
06119
06120 HighPage = MM_HIGHEST_PAE_PAGE;
06121 NumberOfPages = 1;
06122 TempPte =
ValidKernelPte;
06123
06124 ExAcquireFastMutex (&MmDynamicMemoryMutex);
06125 start = (LONG)
MmPhysicalMemoryBlock->
NumberOfRuns - 1;
06126
06127
LOCK_PFN (OldIrql);
06128
06129
if (
MmResidentAvailablePages <= 1) {
06130
UNLOCK_PFN (OldIrql);
06131 ExReleaseFastMutex (&MmDynamicMemoryMutex);
06132
return NULL;
06133 }
06134
06135
MmResidentAvailablePages -= 1;
06136
MM_BUMP_COUNTER(57, 1);
06137
06138
06139
06140
06141
06142
06143
06144
06145 PageListType =
FreePageList;
06146
06147
do {
06148
while (start >= 0) {
06149
06150 count =
MmPhysicalMemoryBlock->
Run[start].
PageCount;
06151 Page =
MmPhysicalMemoryBlock->
Run[start].
BasePage;
06152
06153
if (count && (Page < HighPage)) {
06154
06155 Pfn1 =
MI_PFN_ELEMENT (Page);
06156
do {
06157
06158
if ((ULONG)Pfn1->
u3.e1.PageLocation <= (ULONG)PageListType) {
06159
if ((Pfn1->
u1.Flink != 0) &&
06160 (Pfn1->
u2.Blink != 0) &&
06161 (Pfn1->
u3.e2.ReferenceCount == 0)) {
06162
06163
if (Page >=
MmKseg2Frame) {
06164
06165 PointerPte =
MiReserveSystemPtes (1,
06166 SystemPteSpace,
06167 0,
06168 0,
06169 FALSE);
06170
06171
if (PointerPte ==
NULL) {
06172
goto alldone;
06173 }
06174 BaseAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
06175 TempPte.
u.Hard.PageFrameNumber = Page;
06176
MI_WRITE_VALID_PTE (PointerPte, TempPte);
06177 }
06178
else {
06179 PointerPte =
NULL;
06180 BaseAddress = (PVOID)(
KSEG0_BASE + (Page <<
PAGE_SHIFT));
06181 }
06182
06183
MiChargeCommitmentCantExpand (1, TRUE);
06184
MM_TRACK_COMMIT (MM_DBG_COMMIT_CONTIGUOUS_PAGES, 1);
06185
06186
MmAllocatedNonPagedPool += 1;
06187
NonPagedPoolDescriptor.
TotalBigPages += 1;
06188
06189
06190
06191
06192
06193
if (Pfn1->
u3.e1.PageLocation ==
StandbyPageList) {
06194
MiUnlinkPageFromList (Pfn1);
06195
MiRestoreTransitionPte (Page);
06196 }
else {
06197
MiUnlinkFreeOrZeroedPage (Page);
06198 }
06199
06200 Pfn1->
u3.e2.ShortFlags = 0;
06201 PageColor =
MI_GET_PAGE_COLOR_FROM_VA(BaseAddress);
06202
MI_CHECK_PAGE_ALIGNMENT(Page,
06203 PageColor & MM_COLOR_MASK);
06204 Pfn1->
u3.e1.PageColor = PageColor &
MM_COLOR_MASK;
06205 PageColor += 1;
06206
06207 Pfn1->
u3.e2.ReferenceCount = 1;
06208 Pfn1->
u2.ShareCount = 1;
06209 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
06210
06211
if (PointerPte !=
NULL) {
06212 Pfn1->
PteAddress = PointerPte;
06213 Pfn1->
PteFrame =
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress(PointerPte));
06214 }
06215
else {
06216 Pfn1->
PteAddress = BaseAddress;
06217 Pfn1->
PteFrame = (PFN_NUMBER)-1;
06218 }
06219
06220 Pfn1->
u3.e1.PageLocation =
ActiveAndValid;
06221 Pfn1->
u3.e1.VerifierAllocation = 0;
06222 Pfn1->
u3.e1.LargeSessionAllocation = 0;
06223 Pfn1->
u3.e1.StartOfAllocation = 1;
06224 Pfn1->
u3.e1.EndOfAllocation = 1;
06225
06226 Pae = (PPAE_ENTRY) BaseAddress;
06227 Pae->PaeEntry.EntriesInUse = 0;
06228 Pae->PaeEntry.PageFrameNumber = Page;
06229 Pae += 1;
06230
06231
for (i = 1; i < PAES_PER_PAGE; i += 1) {
06232 InsertTailList (&MiFirstFreePae.PaeEntry.ListHead,
06233 &Pae->PaeEntry.ListHead);
06234 Pae += 1;
06235 MiFreePaes += 1;
06236 }
06237
06238
06239
06240
06241
06242
UNLOCK_PFN (OldIrql);
06243
06244 ExReleaseFastMutex (&MmDynamicMemoryMutex);
06245
06246
ExInsertPoolTag ('DeaP',
06247 BaseAddress,
06248 PAGE_SIZE,
06249 NonPagedPool);
06250
06251
return BaseAddress;
06252 }
06253 }
06254 Page += 1;
06255 Pfn1 += 1;
06256 count -= 1;
06257
06258 }
while (count && (Page < HighPage));
06259 }
06260 start -= 1;
06261 }
06262
06263 PageListType += 1;
06264 start = (LONG)
MmPhysicalMemoryBlock->
NumberOfRuns - 1;
06265
06266 }
while (PageListType <=
StandbyPageList);
06267
06268 alldone:
06269
06270
MmResidentAvailablePages += 1;
06271
MM_BUMP_COUNTER(57, -1);
06272
UNLOCK_PFN (OldIrql);
06273
06274 ExReleaseFastMutex (&MmDynamicMemoryMutex);
06275
06276
return NULL;
06277 }
06278
06279
VOID
06280
ExRemovePoolTag (
06281 ULONG Tag,
06282 PVOID Va,
06283 SIZE_T NumberOfBytes
06284 );
06285
06286
VOID
06287 MiPaeFreeEntirePage (
06288 PVOID VirtualAddress
06289 )
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313 {
06314 PFN_NUMBER PageFrameIndex;
06315
PMMPFN Pfn1;
06316
PMMPTE PointerPte;
06317 KIRQL OldIrql;
06318
06319
#if defined (_X86PAE_)
06320
if (
MiNoLowMemory ==
TRUE) {
06321
if (
MiFreeLowMemory (VirtualAddress, 'DeaP') ==
TRUE) {
06322
return;
06323 }
06324 }
06325
#endif
06326
06327
ExRemovePoolTag ('DeaP', VirtualAddress, PAGE_SIZE);
06328
06329
if (
MI_IS_PHYSICAL_ADDRESS(VirtualAddress) == 0) {
06330 PointerPte =
MiGetPteAddress (VirtualAddress);
06331 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
06332 }
06333
else {
06334 PointerPte =
NULL;
06335 PageFrameIndex =
MI_CONVERT_PHYSICAL_TO_PFN (VirtualAddress);
06336 }
06337
06338 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06339
06340
LOCK_PFN (OldIrql);
06341
06342
ASSERT (Pfn1->
u1.WsIndex == 0);
06343
ASSERT (Pfn1->
u3.e1.PageLocation == ActiveAndValid);
06344
ASSERT (Pfn1->
u3.e1.VerifierAllocation == 0);
06345
ASSERT (Pfn1->
u3.e1.LargeSessionAllocation == 0);
06346
ASSERT (Pfn1->
u3.e1.StartOfAllocation == 1);
06347
ASSERT (Pfn1->
u3.e1.EndOfAllocation == 1);
06348
ASSERT (Pfn1->
u2.ShareCount == 1);
06349
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
06350
06351 Pfn1->
u2.ShareCount = 0;
06352
MI_SET_PFN_DELETED (Pfn1);
06353
#if DBG
06354
Pfn1->
u3.e1.PageLocation =
StandbyPageList;
06355
#endif //DBG
06356
MiDecrementReferenceCount (PageFrameIndex);
06357
06358
if (PointerPte !=
NULL) {
06359
KeFlushSingleTb (VirtualAddress,
06360 TRUE,
06361 TRUE,
06362 (PHARDWARE_PTE)PointerPte,
06363
ZeroKernelPte.
u.Flush);
06364 }
06365
06366
MmResidentAvailablePages += 1;
06367
MM_BUMP_COUNTER(57, -1);
06368
06369
MmAllocatedNonPagedPool -= 1;
06370
NonPagedPoolDescriptor.
TotalBigPages -= 1;
06371
06372
UNLOCK_PFN (OldIrql);
06373
06374
if (PointerPte !=
NULL) {
06375
MiReleaseSystemPtes (PointerPte,
06376 1,
06377 SystemPteSpace);
06378 }
06379
06380
MiReturnCommitment (1);
06381 }
06382
#endif