00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "mi.h"
00023
00024 ULONG
MiSessionCount;
00025
00026 #define MM_MAXIMUM_CONCURRENT_SESSIONS 16384
00027
00028 FAST_MUTEX MiSessionIdMutex;
00029
00030 PRTL_BITMAP
MiSessionIdBitmap;
00031
00032
#if defined (_WIN64)
00033
#define MI_SESSION_COMMIT_CHARGE 3
00034
#else
00035 #define MI_SESSION_COMMIT_CHARGE 2
00036
#endif
00037
00038
VOID
00039
MiSessionAddProcess(
00040
PEPROCESS NewProcess
00041 );
00042
00043
VOID
00044
MiSessionRemoveProcess (
00045 VOID
00046 );
00047
00048
VOID
00049
MiInitializeSessionIds (
00050 VOID
00051 );
00052
00053
NTSTATUS
00054
MiSessionCreateInternal(
00055 OUT PULONG SessionId
00056 );
00057
00058
NTSTATUS
00059
MiSessionCommitPageTables(
00060 IN PVOID StartVa,
00061 IN PVOID EndVa
00062 );
00063
00064 BOOLEAN
00065
MiDereferenceSession(
00066 VOID
00067 );
00068
00069
VOID
00070
MiSessionDeletePde(
00071 IN
PMMPTE Pde,
00072 IN BOOLEAN WorkingSetInitialized,
00073 IN
PMMPTE SelfMapPde
00074 );
00075
00076
#if DBG
00077
VOID
00078 MiCheckSessionVirtualSpace(
00079 IN PVOID VirtualAddress,
00080 IN ULONG NumberOfBytes
00081 );
00082
#endif
00083
00084
#ifdef ALLOC_PRAGMA
00085
#pragma alloc_text(INIT,MiInitializeSessionIds)
00086
00087
#pragma alloc_text(PAGE, MmSessionLeader)
00088
#pragma alloc_text(PAGE, MmSessionSetUnloadAddress)
00089
00090
#pragma alloc_text(PAGEHYDRA, MiSessionAddProcess)
00091
#pragma alloc_text(PAGEHYDRA, MiSessionRemoveProcess)
00092
#pragma alloc_text(PAGEHYDRA, MiSessionCreateInternal)
00093
#pragma alloc_text(PAGEHYDRA, MmSessionCreate)
00094
#pragma alloc_text(PAGEHYDRA, MmSessionDelete)
00095
#pragma alloc_text(PAGEHYDRA, MiAttachSession)
00096
#pragma alloc_text(PAGEHYDRA, MiDetachSession)
00097
#pragma alloc_text(PAGEHYDRA, MiSessionCommitImagePages)
00098
#pragma alloc_text(PAGEHYDRA, MiSessionCommitPageTables)
00099
#pragma alloc_text(PAGEHYDRA, MiSessionOutSwapProcess)
00100
#pragma alloc_text(PAGEHYDRA, MiSessionInSwapProcess)
00101
#pragma alloc_text(PAGEHYDRA, MiSessionDeletePde)
00102
00103
#if DBG
00104
#pragma alloc_text(PAGEHYDRA, MiCheckSessionVirtualSpace)
00105
#endif
00106
#endif
00107
00108
VOID
00109 MmSessionLeader(
00110 IN
PEPROCESS Process
00111 )
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 {
00135 Process->Vm.u.Flags.SessionLeader = 1;
00136 }
00137
00138
00139
VOID
00140 MmSessionSetUnloadAddress (
00141 IN
PDRIVER_OBJECT pWin32KDevice
00142 )
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 {
00166
if (
MiHydra ==
TRUE &&
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 1) {
00167
00168
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
TRUE);
00169
00170 RtlMoveMemory (&
MmSessionSpace->
Win32KDriverObject,
00171 pWin32KDevice,
00172
sizeof(
DRIVER_OBJECT));
00173 }
00174 }
00175
00176
00177
VOID
00178 MiSessionAddProcess(
00179
PEPROCESS NewProcess
00180 )
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 {
00203 KIRQL OldIrql;
00204
PMM_SESSION_SPACE SessionGlobal;
00205
00206
00207
00208
00209
00210
00211
if (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0) {
00212
return;
00213 }
00214
00215
ASSERT (
MmIsAddressValid (
MmSessionSpace) ==
TRUE);
00216
00217 SessionGlobal =
SESSION_GLOBAL(
MmSessionSpace);
00218
00219
LOCK_SESSION (OldIrql);
00220
00221
MmSessionSpace->
ReferenceCount += 1;
00222
00223
UNLOCK_SESSION (OldIrql);
00224
00225
#if defined(_IA64_)
00226
KeAddSessionSpace(&NewProcess->
Pcb, &SessionGlobal->SessionMapInfo);
00227
#endif
00228
00229
00230
00231
00232
00233
LOCK_EXPANSION (OldIrql);
00234
00235
if (IsListEmpty(&SessionGlobal->
ProcessList)) {
00236
00237
if (
MmSessionSpace->
Vm.
AllowWorkingSetAdjustment ==
FALSE) {
00238
00239
ASSERT (
MmSessionSpace->
u.Flags.WorkingSetInserted == 0);
00240
00241
MmSessionSpace->
Vm.
AllowWorkingSetAdjustment =
TRUE;
00242
00243 InsertTailList (&
MmWorkingSetExpansionHead.
ListHead,
00244 &SessionGlobal->
Vm.
WorkingSetExpansionLinks);
00245
00246
MmSessionSpace->
u.Flags.WorkingSetInserted = 1;
00247 }
00248 }
00249
00250 InsertTailList (&SessionGlobal->
ProcessList, &NewProcess->
SessionProcessLinks);
00251
00252 NewProcess->
Vm.
u.Flags.ProcessInSession = 1;
00253
00254
UNLOCK_EXPANSION (OldIrql);
00255 }
00256
00257
00258
VOID
00259 MiSessionRemoveProcess (
00260 VOID
00261 )
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 {
00291 KIRQL OldIrql;
00292
PEPROCESS CurrentProcess;
00293
#if DBG
00294
ULONG Found;
00295
PEPROCESS Process;
00296 PLIST_ENTRY NextEntry;
00297
PMM_SESSION_SPACE SessionGlobal;
00298
#endif
00299
00300 CurrentProcess =
PsGetCurrentProcess();
00301
00302
if (CurrentProcess->
Vm.
u.Flags.ProcessInSession == 0) {
00303
return;
00304 }
00305
00306
ASSERT (
MmIsAddressValid (
MmSessionSpace) ==
TRUE);
00307
00308
00309
00310
00311
00312
LOCK_EXPANSION (OldIrql);
00313
00314
#if DBG
00315
00316 SessionGlobal =
SESSION_GLOBAL(
MmSessionSpace);
00317
00318 Found = 0;
00319 NextEntry = SessionGlobal->
ProcessList.Flink;
00320
00321
while (NextEntry != &SessionGlobal->
ProcessList) {
00322 Process = CONTAINING_RECORD (NextEntry,
EPROCESS, SessionProcessLinks);
00323
00324
if (Process == CurrentProcess) {
00325 Found = 1;
00326 }
00327
00328 NextEntry = NextEntry->Flink;
00329 }
00330
00331
ASSERT (Found == 1);
00332
00333
#endif
00334
00335 RemoveEntryList (&CurrentProcess->
SessionProcessLinks);
00336
00337
UNLOCK_EXPANSION (OldIrql);
00338
00339
00340
00341
00342
00343
00344
00345
00346
MiDereferenceSession ();
00347 }
00348
00349
VOID
00350 MiInitializeSessionIds (
00351 VOID
00352 )
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 {
00371
00372
00373
00374
00375
00376
ASSERT (
sizeof(
MM_SESSION_SPACE) <=
PAGE_SIZE);
00377
00378
ExInitializeFastMutex (&
MiSessionIdMutex);
00379
00380
MiCreateBitMap (&
MiSessionIdBitmap,
00381
MM_MAXIMUM_CONCURRENT_SESSIONS,
00382
PagedPool);
00383
00384
if (
MiSessionIdBitmap ==
NULL) {
00385
MiCreateBitMap (&
MiSessionIdBitmap,
00386
MM_MAXIMUM_CONCURRENT_SESSIONS,
00387
NonPagedPoolMustSucceed);
00388 }
00389
00390
RtlClearAllBits (
MiSessionIdBitmap);
00391 }
00392
00393
NTSTATUS
00394 MiSessionCreateInternal(
00395 OUT PULONG SessionId
00396 )
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 {
00436 KIRQL OldIrql;
00437
PMMPTE PointerPpe;
00438
PMMPTE PointerPde;
00439
PMMPTE PointerPte;
00440
NTSTATUS Status;
00441
PMM_SESSION_SPACE SessionSpace;
00442
PMM_SESSION_SPACE SessionGlobal;
00443 PFN_NUMBER ResidentPages;
00444 BOOLEAN GotCommit;
00445 BOOLEAN GotPages;
00446
PMMPFN Pfn1;
00447
MMPTE TempPte;
00448
MMPTE AliasPte;
00449
MMPTE PreviousPte;
00450 ULONG_PTR Va;
00451 PFN_NUMBER DataPage;
00452 PFN_NUMBER PageTablePage;
00453 PFN_NUMBER PageDirectoryPage;
00454 ULONG PageColor;
00455
00456 SessionSpace =
NULL;
00457 GotCommit =
FALSE;
00458 GotPages =
FALSE;
00459
00460
ASSERT (
MmIsAddressValid(SessionSpace) ==
FALSE);
00461
00462 ExAcquireFastMutex (&
MiSessionIdMutex);
00463
00464 *SessionId =
RtlFindClearBitsAndSet (
MiSessionIdBitmap, 1, 0);
00465
00466 ExReleaseFastMutex (&
MiSessionIdMutex);
00467
00468
if (*SessionId == 0xFFFFFFFF) {
00469
#if DBG
00470
DbgPrint(
"MiSessionCreateInternal: No session IDs available\n");
00471
#endif
00472
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_IDS);
00473
return STATUS_NO_MEMORY;
00474 }
00475
00476 ResidentPages =
MI_SESSION_COMMIT_CHARGE;
00477
00478
if (
MiChargeCommitment (ResidentPages,
NULL) ==
FALSE) {
00479
#if DBG
00480
if (MmDebug &
MM_DBG_SESSIONS) {
00481
DbgPrint(
"MiSessionCreateInternal: No commit for %d pages\n",
00482 ResidentPages);
00483 }
00484
#endif
00485
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_COMMIT);
00486
goto Failure;
00487 }
00488
00489 GotCommit =
TRUE;
00490
00491
MM_TRACK_COMMIT (
MM_DBG_COMMIT_SESSION_CREATE, ResidentPages);
00492
00493
LOCK_PFN (OldIrql);
00494
00495
00496
00497
00498
00499
if ((SPFN_NUMBER)(ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM) >
MI_NONPAGABLE_MEMORY_AVAILABLE()) {
00500
#if DBG
00501
if (MmDebug &
MM_DBG_SESSIONS) {
00502
DbgPrint(
"MiSessionCreateInternal: No Resident Pages %d, Need %d\n",
00503
MmResidentAvailablePages,
00504 ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00505 }
00506
#endif
00507
UNLOCK_PFN (OldIrql);
00508
00509
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_RESIDENT);
00510
goto Failure;
00511 }
00512
00513 GotPages =
TRUE;
00514
00515
MmResidentAvailablePages -= (ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00516
00517
MM_BUMP_COUNTER(40, ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00518
00519
#if defined (_WIN64)
00520
00521
00522
00523
00524
00525
MiEnsureAvailablePageOrWait (
NULL,
NULL);
00526
00527 PageColor =
MI_GET_PAGE_COLOR_FROM_VA (
NULL);
00528
00529 PageDirectoryPage =
MiRemoveZeroPageIfAny (PageColor);
00530
if (PageDirectoryPage == 0) {
00531 PageDirectoryPage =
MiRemoveAnyPage (PageColor);
00532
UNLOCK_PFN (OldIrql);
00533
MiZeroPhysicalPage (PageDirectoryPage, PageColor);
00534
LOCK_PFN (OldIrql);
00535 }
00536
00537
00538
00539
00540
00541
00542 TempPte.
u.Long =
ValidKernelPdeLocal.
u.Long;
00543 TempPte.
u.Hard.PageFrameNumber = PageDirectoryPage;
00544
00545 PointerPpe =
MiGetPpeAddress ((PVOID)
MmSessionSpace);
00546
00547
00548
00549
00550
00551
if (PointerPpe->
u.Long != 0) {
00552
00553
#if DBG
00554
ASSERT (PointerPpe->
u.Hard.Valid == 1);
00555
DbgPrint(
"MiSessionCreateInternal: Detected PPE %p race\n",
00556 PointerPpe->
u.Long);
00557 DbgBreakPoint ();
00558
#endif //DBG
00559
00560 Pfn1 =
MI_PFN_ELEMENT (PageDirectoryPage);
00561
ASSERT (Pfn1->
u2.ShareCount == 0);
00562
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
00563 Pfn1->
u3.e2.ReferenceCount = 1;
00564 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
00565
MI_SET_PFN_DELETED (Pfn1);
00566
#if DBG
00567
Pfn1->
u3.e1.PageLocation =
StandbyPageList;
00568
#endif
00569
00570
MiDecrementReferenceCount (PageDirectoryPage);
00571
00572
MmResidentAvailablePages += (ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00573
MM_BUMP_COUNTER(46, ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00574
00575
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE, 1);
00576
00577 GotPages =
FALSE;
00578
UNLOCK_PFN (OldIrql);
00579
00580
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_RACE_DETECTED);
00581
00582
goto Failure;
00583 }
00584
00585 *PointerPpe = TempPte;
00586
00587
MiInitializePfnForOtherProcess (PageDirectoryPage, PointerPpe, 0);
00588 Pfn1 =
MI_PFN_ELEMENT (PageDirectoryPage);
00589 Pfn1->
PteFrame = 0;
00590
00591
ASSERT (
MI_PFN_ELEMENT(PageDirectoryPage)->u1.WsIndex == 0);
00592
00593 KeFillEntryTb ((PHARDWARE_PTE) PointerPpe,
00594
MiGetVirtualAddressMappedByPte (PointerPpe),
00595
FALSE);
00596
#endif
00597
00598
00599
00600
00601
00602
MiEnsureAvailablePageOrWait (
NULL,
NULL);
00603
00604 PageColor =
MI_GET_PAGE_COLOR_FROM_VA (
NULL);
00605
00606 PageTablePage =
MiRemoveZeroPageIfAny (PageColor);
00607
if (PageTablePage == 0) {
00608 PageTablePage =
MiRemoveAnyPage (PageColor);
00609
UNLOCK_PFN (OldIrql);
00610
MiZeroPhysicalPage (PageTablePage, PageColor);
00611
LOCK_PFN (OldIrql);
00612 }
00613
00614
00615
00616
00617
00618
00619 TempPte.u.Long =
ValidKernelPdeLocal.
u.Long;
00620 TempPte.u.Hard.PageFrameNumber = PageTablePage;
00621
00622 PointerPde =
MiGetPdeAddress ((PVOID)
MmSessionSpace);
00623
00624
#if !defined (_WIN64)
00625
00626
00627
00628
00629
00630
if (PointerPde->
u.Long != 0) {
00631
#if DBG
00632
ASSERT (PointerPde->
u.Hard.Valid == 1);
00633
DbgPrint(
"MiSessionCreateInternal: Detected PDE %p race\n",
00634 PointerPde->
u.Long);
00635 DbgBreakPoint ();
00636
#endif //DBG
00637
00638 Pfn1 =
MI_PFN_ELEMENT (PageTablePage);
00639
ASSERT (Pfn1->
u2.ShareCount == 0);
00640
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
00641 Pfn1->
u3.e2.ReferenceCount = 1;
00642 Pfn1->
OriginalPte.
u.Long =
MM_DEMAND_ZERO_WRITE_PTE;
00643
MI_SET_PFN_DELETED (Pfn1);
00644
#if DBG
00645
Pfn1->
u3.e1.PageLocation =
StandbyPageList;
00646
#endif
00647
00648
MiDecrementReferenceCount (PageTablePage);
00649
00650
MmResidentAvailablePages += (ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00651
MM_BUMP_COUNTER(46, ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00652
00653
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE, 1);
00654
00655 GotPages =
FALSE;
00656
UNLOCK_PFN (OldIrql);
00657
00658
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_RACE_DETECTED);
00659
00660
goto Failure;
00661 }
00662
00663
#endif
00664
00665
MI_WRITE_VALID_PTE (PointerPde, TempPte);
00666
00667
00668
00669
00670
00671
00672
00673
00674
MiInitializePfnForOtherProcess (PageTablePage, PointerPde, PageTablePage);
00675
00676
00677
00678
00679
00680
00681
ASSERT (
MI_PFN_ELEMENT(PageTablePage)->u1.WsIndex == 0);
00682
00683 Va = (ULONG_PTR)
MiGetPteAddress (
MmSessionSpace);
00684
00685 KeFillEntryTb ((PHARDWARE_PTE) PointerPde, (
PMMPTE)Va,
FALSE);
00686
00687
MiEnsureAvailablePageOrWait (
NULL,
NULL);
00688
00689 PageColor =
MI_GET_PAGE_COLOR_FROM_VA (
NULL);
00690
00691 DataPage =
MiRemoveZeroPageIfAny (PageColor);
00692
if (DataPage == 0) {
00693 DataPage =
MiRemoveAnyPage (PageColor);
00694
UNLOCK_PFN (OldIrql);
00695
MiZeroPhysicalPage (DataPage, PageColor);
00696
LOCK_PFN (OldIrql);
00697 }
00698
00699
00700
00701
00702
00703
00704 TempPte.u.Long =
ValidKernelPteLocal.
u.Long;
00705 TempPte.u.Hard.PageFrameNumber = DataPage;
00706
00707 PointerPte =
MiGetPteAddress (
MmSessionSpace);
00708
00709
MI_WRITE_VALID_PTE (PointerPte, TempPte);
00710
00711
MiInitializePfn (DataPage, PointerPte, 1);
00712
00713
ASSERT (
MI_PFN_ELEMENT(DataPage)->u1.WsIndex == 0);
00714
00715
UNLOCK_PFN (OldIrql);
00716
00717 KeFillEntryTb ((PHARDWARE_PTE) PointerPte, (
PMMPTE)
MmSessionSpace,
FALSE);
00718
00719 AliasPte = *PointerPte;
00720
00721
00722
00723
00724
00725 SessionSpace =
MmSessionSpace;
00726
00727
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGETABLE_ALLOC, 1);
00728
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGE_ALLOC, 1);
00729
00730 SessionSpace->
ReferenceCount = 1;
00731 SessionSpace->
u.LongFlags = 0;
00732 SessionSpace->
SessionId = *SessionId;
00733 SessionSpace->
SessionPageDirectoryIndex = PageTablePage;
00734
00735 SessionSpace->
Color = PageColor;
00736
00737
00738
00739
00740
00741 SessionSpace->
NonPagablePages = ResidentPages;
00742 SessionSpace->
CommittedPages = ResidentPages;
00743
00744
#if defined (_WIN64)
00745
00746
00747
00748
00749
00750 PointerPpe =
MiGetPpeAddress ((PVOID)
MmSessionSpace);
00751 SessionSpace->PageDirectory = *PointerPpe;
00752
00753
#else
00754
00755
00756
00757
00758
00759
00760 SessionSpace->
PageTables[PointerPde -
MiGetPdeAddress (
MmSessionBase)] = *PointerPde;
00761
00762
#endif
00763
00764
00765
00766
00767
00768 SessionSpace->
GlobalPteEntry =
MiReserveSystemPtes (1,
00769
SystemPteSpace,
00770 0,
00771 0,
00772
FALSE
00773 );
00774
00775
if (SessionSpace->
GlobalPteEntry ==
NULL) {
00776
#if DBG
00777
if (MmDebug &
MM_DBG_SESSIONS) {
00778
DbgPrint(
"MiSessionCreateInternal: No memory for session self-map\n");
00779 }
00780
#endif
00781
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_SYSPTES);
00782
goto Failure;
00783 }
00784
00785 *(SessionSpace->
GlobalPteEntry) = AliasPte;
00786
00787 SessionSpace->
GlobalVirtualAddress =
MiGetVirtualAddressMappedByPte (SessionSpace->
GlobalPteEntry);
00788
00789 SessionGlobal =
SESSION_GLOBAL(SessionSpace);
00790
00791
00792
00793
00794
00795
00796 InitializeListHead (&SessionSpace->
ImageList);
00797
00798
00799
00800
00801
00802
Status =
MiInitializeSessionPool ();
00803
00804
if (!
NT_SUCCESS(
Status)) {
00805
#if DBG
00806
if (MmDebug &
MM_DBG_SESSIONS) {
00807
DbgPrint(
"MiSessionCreateInternal: No memory for session pool\n");
00808 }
00809
#endif
00810
goto Failure;
00811 }
00812
00813
00814
00815
00816
00817
00818
if (
MiInitializeSystemSpaceMap (&SessionGlobal->
Session) ==
FALSE) {
00819
#if DBG
00820
if (MmDebug &
MM_DBG_SESSIONS) {
00821
DbgPrint(
"MiSessionCreateInternal: No memory for view mapping\n");
00822 }
00823
#endif
00824
goto Failure;
00825 }
00826
00827
00828
00829
00830
00831
00832 InitializeListHead (&SessionGlobal->
WsListEntry);
00833
00834 InitializeListHead (&SessionGlobal->
ProcessList);
00835
00836
KeInitializeSpinLock (&SessionGlobal->
SpinLock);
00837
00838
#if defined(_IA64_)
00839
KeEnableSessionSharing(&SessionGlobal->SessionMapInfo);
00840
#endif
00841
00842
return STATUS_SUCCESS;
00843
00844 Failure:
00845
00846
if (GotCommit ==
TRUE) {
00847
MiReturnCommitment (ResidentPages);
00848
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE1,
00849 ResidentPages);
00850 }
00851
00852
if (GotPages ==
TRUE) {
00853
00854
#if defined (_WIN64)
00855
00856 PointerPpe =
MiGetPpeAddress (
MI_SESSION_POOL);
00857
00858
ASSERT (PointerPpe->u.Hard.Valid != 0);
00859
00860
#endif
00861
00862 PointerPde =
MiGetPdeAddress (
MI_SESSION_POOL);
00863
00864
ASSERT (PointerPde->u.Hard.Valid != 0);
00865
00866
00867
00868
00869
00870
00871
MiFreeSessionSpaceMap ();
00872
00873
00874
00875
00876
00877
00878
MiFreeSessionPoolBitMaps ();
00879
00880
if (SessionSpace->
GlobalPteEntry) {
00881
MiReleaseSystemPtes (SessionSpace->
GlobalPteEntry,
00882 1,
00883
SystemPteSpace);
00884 SessionSpace->
GlobalPteEntry = (
PMMPTE)0;
00885 }
00886
00887
LOCK_PFN (OldIrql);
00888
00889
00890
00891
00892
00893 Pfn1 =
MI_PFN_ELEMENT (DataPage);
00894
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
00895
MI_SET_PFN_DELETED (Pfn1);
00896
MiDecrementShareCountOnly (DataPage);
00897
00898
MI_FLUSH_SINGLE_SESSION_TB (
MmSessionSpace,
00899
TRUE,
00900
TRUE,
00901 (PHARDWARE_PTE)PointerPte,
00902
ZeroKernelPte.
u.Flush,
00903 PreviousPte);
00904
00905
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGE_FREE_FAIL1, 1);
00906
00907
00908
00909
00910
00911 Pfn1 =
MI_PFN_ELEMENT (PageTablePage);
00912
ASSERT (PageTablePage == Pfn1->
PteFrame);
00913
ASSERT (Pfn1->
u2.ShareCount == 2);
00914 Pfn1->
u2.ShareCount -= 1;
00915
MI_SET_PFN_DELETED (Pfn1);
00916
MiDecrementShareCountOnly (PageTablePage);
00917
00918
MI_FLUSH_SINGLE_SESSION_TB (
MiGetVirtualAddressMappedByPte(PointerPde),
00919
TRUE,
00920
TRUE,
00921 (PHARDWARE_PTE)PointerPde,
00922
ZeroKernelPte.
u.Flush,
00923 PreviousPte);
00924
00925
#if defined (_WIN64)
00926
00927
00928
00929
00930
00931 Pfn1 =
MI_PFN_ELEMENT (PageDirectoryPage);
00932
ASSERT (PageDirectoryPage == Pfn1->
PteFrame);
00933
ASSERT (Pfn1->
u2.ShareCount == 1);
00934
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
00935
MI_SET_PFN_DELETED (Pfn1);
00936
MiDecrementShareCountOnly (PageDirectoryPage);
00937
00938
MI_FLUSH_SINGLE_SESSION_TB (
MiGetVirtualAddressMappedByPte(PointerPpe),
00939
TRUE,
00940
TRUE,
00941 (PHARDWARE_PTE)PointerPpe,
00942
ZeroKernelPte.
u.Flush,
00943 PreviousPte);
00944
00945
#endif
00946
00947
00948
00949
00950
00951
00952
00953
MmResidentAvailablePages += (ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00954
00955
MM_BUMP_COUNTER (49, ResidentPages +
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
00956
00957
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_FAIL1, 1);
00958
00959
UNLOCK_PFN (OldIrql);
00960 }
00961
00962 ExAcquireFastMutex (&
MiSessionIdMutex);
00963
00964
ASSERT (RtlCheckBit (
MiSessionIdBitmap, *SessionId));
00965
RtlClearBits (
MiSessionIdBitmap, *SessionId, 1);
00966
00967 ExReleaseFastMutex (&
MiSessionIdMutex);
00968
00969
return STATUS_NO_MEMORY;
00970 }
00971
00972
00973
NTSTATUS
00974 MmSessionCreate(
00975 OUT PULONG SessionId
00976 )
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 {
01001 KIRQL OldIrql;
01002
NTSTATUS Status;
01003
PEPROCESS CurrentProcess;
01004
#if DBG
01005
PMMPTE StartPde;
01006
PMMPTE EndPde;
01007
#endif
01008
01009
if (
MiHydra ==
FALSE) {
01010
return STATUS_INVALID_SYSTEM_SERVICE;
01011 }
01012
01013 CurrentProcess =
PsGetCurrentProcess();
01014
01015
01016
01017
01018
01019
01020
01021
if (CurrentProcess->
Vm.
u.Flags.ProcessInSession == 1) {
01022
return STATUS_ALREADY_COMMITTED;
01023 }
01024
01025
if (CurrentProcess->
Vm.
u.Flags.SessionLeader == 0) {
01026
01027
01028
01029
01030
01031
return STATUS_INVALID_SYSTEM_SERVICE;
01032 }
01033
01034
#if DBG
01035
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
FALSE);
01036
01037
#if defined (_WIN64)
01038
ASSERT ((
MiGetPpeAddress(
MmSessionBase))->u.Long ==
ZeroKernelPte.
u.Long);
01039
#else
01040
StartPde =
MiGetPdeAddress (
MmSessionBase);
01041 EndPde =
MiGetPdeAddress (
MI_SESSION_SPACE_END);
01042
01043
while (StartPde < EndPde) {
01044
ASSERT (StartPde->
u.Long ==
ZeroKernelPte.
u.Long);
01045 StartPde += 1;
01046 }
01047
#endif
01048
01049
#endif
01050
01051
KeEnterCriticalRegion();
01052
01053
Status =
MiSessionCreateInternal (SessionId);
01054
01055
if (!
NT_SUCCESS(
Status)) {
01056
KeLeaveCriticalRegion();
01057
return Status;
01058 }
01059
01060
LOCK_EXPANSION (OldIrql);
01061
01062
MiSessionCount += 1;
01063
01064
UNLOCK_EXPANSION (OldIrql);
01065
01066
01067
01068
01069
01070
Status =
MiSessionInitializeWorkingSetList ();
01071
01072
if (!
NT_SUCCESS(
Status)) {
01073
MiDereferenceSession ();
01074
KeLeaveCriticalRegion();
01075
return Status;
01076 }
01077
01078
KeLeaveCriticalRegion();
01079
01080
MmSessionSpace->
u.Flags.Initialized = 1;
01081
01082
LOCK_EXPANSION (OldIrql);
01083
01084 CurrentProcess->
Vm.
u.Flags.ProcessInSession = 1;
01085
01086
UNLOCK_EXPANSION (OldIrql);
01087
01088
return Status;
01089 }
01090
01091
01092
NTSTATUS
01093 MmSessionDelete(
01094 ULONG SessionId
01095 )
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 {
01124
PEPROCESS CurrentProcess;
01125
01126
if (
MiHydra ==
FALSE) {
01127
return STATUS_INVALID_SYSTEM_SERVICE;
01128 }
01129
01130 CurrentProcess =
PsGetCurrentProcess();
01131
01132
01133
01134
01135
01136
01137
if (CurrentProcess->
Vm.
u.Flags.ProcessInSession == 0) {
01138
#if DBG
01139
DbgPrint (
"MmSessionDelete: Process %p not in a session\n",
01140
PsGetCurrentProcess());
01141 DbgBreakPoint();
01142
#endif
01143
return STATUS_UNABLE_TO_FREE_VM;
01144 }
01145
01146
if (CurrentProcess->
Vm.
u.Flags.SessionLeader == 0) {
01147
01148
01149
01150
01151
01152
01153
01154
01155
return STATUS_UNABLE_TO_FREE_VM;
01156 }
01157
01158
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
TRUE);
01159
01160
if (
MmSessionSpace->
SessionId != SessionId) {
01161
#if DBG
01162
DbgPrint(
"MmSessionDelete: Wrong SessionId! Own %d, Ask %d\n",
01163
MmSessionSpace->
SessionId,
01164 SessionId);
01165 DbgBreakPoint();
01166
#endif
01167
return STATUS_UNABLE_TO_FREE_VM;
01168 }
01169
01170
KeEnterCriticalRegion ();
01171
01172
MiDereferenceSession ();
01173
01174
KeLeaveCriticalRegion ();
01175
01176
return STATUS_SUCCESS;
01177 }
01178
01179
01180
VOID
01181 MiAttachSession(
01182 IN
PMM_SESSION_SPACE SessionGlobal
01183 )
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206 {
01207
PMMPTE PointerPde;
01208
#if DBG
01209
PMMPTE EndPde;
01210
01211
ASSERT (
MiHydra ==
TRUE);
01212
01213
ASSERT (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0);
01214
01215
#if defined (_WIN64)
01216
01217 PointerPde =
MiGetPpeAddress (
MmSessionBase);
01218
ASSERT (PointerPde->
u.Long ==
ZeroKernelPte.
u.Long);
01219
01220
#else
01221
PointerPde =
MiGetPdeAddress (
MmSessionBase);
01222 EndPde =
MiGetPdeAddress (
MI_SESSION_SPACE_END);
01223
01224
while (PointerPde < EndPde) {
01225
ASSERT (PointerPde->
u.Long ==
ZeroKernelPte.
u.Long);
01226 PointerPde += 1;
01227 }
01228
#endif
01229
01230
#endif
01231
01232
#if defined (_WIN64)
01233
01234 PointerPde =
MiGetPpeAddress (
MmSessionBase);
01235
MI_WRITE_VALID_PTE (PointerPde, SessionGlobal->PageDirectory);
01236
01237
#else
01238
01239 PointerPde =
MiGetPdeAddress (
MmSessionBase);
01240
01241 RtlCopyMemory (PointerPde,
01242 &SessionGlobal->PageTables[0],
01243
MI_SESSION_SPACE_PAGE_TABLES * sizeof (
MMPTE));
01244
#endif
01245
01246
#if defined(_IA64_)
01247
KeAttachSessionSpace(&SessionGlobal->SessionMapInfo);
01248
#endif
01249
}
01250
01251
01252
VOID
01253 MiDetachSession(
01254 VOID
01255 )
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 {
01279
PMMPTE PointerPde;
01280
PMMPTE EndPde;
01281 KIRQL OldIrql;
01282
01283
ASSERT (
MiHydra ==
TRUE);
01284
01285
ASSERT (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0);
01286
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
TRUE);
01287
01288
#if defined (_WIN64)
01289
PointerPde =
MiGetPpeAddress (
MmSessionBase);
01290 PointerPde->
u.Long =
ZeroKernelPte.
u.Long;
01291
#else
01292
PointerPde =
MiGetPdeAddress (
MmSessionBase);
01293
01294 EndPde =
MiGetPdeAddress (
MI_SESSION_SPACE_END);
01295
01296 RtlZeroMemory (PointerPde,
MI_SESSION_SPACE_PAGE_TABLES *
sizeof (
MMPTE));
01297
#endif
01298
01299
MI_FLUSH_SESSION_TB (OldIrql);
01300
01301
#if defined(_IA64_)
01302
KeDetachSessionSpace();
01303
#endif
01304
}
01305
01306
#if DBG
01307
01308
VOID
01309 MiCheckSessionVirtualSpace(
01310 IN PVOID VirtualAddress,
01311 IN ULONG NumberOfBytes
01312 )
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 {
01337
PMMPTE StartPde;
01338
PMMPTE EndPde;
01339
PMMPTE StartPte;
01340
PMMPTE EndPte;
01341 ULONG
Index;
01342
01343
01344
01345
01346
01347
01348
#if defined (_WIN64)
01349
ASSERT (MiGetPpeAddress (VirtualAddress)->u.Hard.Valid == 1);
01350
#endif
01351
01352 StartPde =
MiGetPdeAddress (VirtualAddress);
01353 EndPde =
MiGetPdeAddress ((PVOID)((PCHAR)VirtualAddress + NumberOfBytes - 1));
01354
01355 StartPte =
MiGetPteAddress (VirtualAddress);
01356 EndPte =
MiGetPteAddress ((PVOID)((PCHAR)VirtualAddress + NumberOfBytes - 1));
01357
01358
Index = (ULONG)(StartPde -
MiGetPdeAddress (MmSessionBase));
01359
01360
#if defined (_WIN64)
01361
while (StartPde <= EndPde && StartPde->
u.Long == 0)
01362
#else
01363
while (StartPde <= EndPde &&
MmSessionSpace->
PageTables[
Index].
u.Long == 0)
01364
#endif
01365
{
01366 StartPde += 1;
01367
Index += 1;
01368 StartPte =
MiGetVirtualAddressMappedByPte (StartPde);
01369 }
01370
01371
while (StartPte <= EndPte) {
01372
01373
if (
MiIsPteOnPdeBoundary(StartPte)) {
01374
01375 StartPde =
MiGetPteAddress (StartPte);
01376
Index = (ULONG)(StartPde -
MiGetPdeAddress (MmSessionBase));
01377
01378
#if defined (_WIN64)
01379
while (StartPde <= EndPde && StartPde->
u.Long == 0)
01380
#else
01381
while (StartPde <= EndPde &&
MmSessionSpace->
PageTables[
Index].
u.Long == 0)
01382
#endif
01383
{
01384
Index += 1;
01385 StartPde += 1;
01386 StartPte =
MiGetVirtualAddressMappedByPte (StartPde);
01387 }
01388
if (StartPde > EndPde) {
01389
break;
01390 }
01391 }
01392
01393
if (StartPte->
u.Long != 0 && StartPte->
u.Long !=
MM_KERNEL_NOACCESS_PTE) {
01394
DbgPrint(
"MiCheckSessionVirtualSpace: StartPte 0x%p is still valid! 0x%p, VA 0x%p\n",
01395 StartPte,
01396 StartPte->
u.Long,
01397
MiGetVirtualAddressMappedByPte(StartPte));
01398
01399 DbgBreakPoint();
01400 }
01401 StartPte += 1;
01402 }
01403 }
01404
#endif
01405
01406
01407
VOID
01408 MiSessionDeletePde(
01409 IN
PMMPTE Pde,
01410 IN BOOLEAN WorkingSetInitialized,
01411 IN
PMMPTE SelfMapPde
01412 )
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 {
01442
PMMPFN Pfn1;
01443
PMMPFN Pfn2;
01444 KIRQL OldIrql2;
01445 PFN_NUMBER PageFrameIndex;
01446 BOOLEAN SelfMapPage;
01447
#if DBG
01448
ULONG i;
01449
PMMPTE PointerPte;
01450
#endif
01451
01452
if (Pde->u.Long ==
ZeroKernelPte.
u.Long) {
01453
return;
01454 }
01455
01456 SelfMapPage = (Pde == SelfMapPde ?
TRUE :
FALSE);
01457
01458
ASSERT (Pde->u.Hard.Valid == 1);
01459
01460 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (Pde);
01461 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01462
01463
#if DBG
01464
01465
ASSERT (PageFrameIndex <=
MmHighestPhysicalPage);
01466
01467
if (WorkingSetInitialized ==
TRUE) {
01468
ASSERT (Pfn1->
u1.WsIndex);
01469 }
01470
01471
ASSERT (Pfn1->
u3.e1.PrototypePte == 0);
01472
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
01473
ASSERT (Pfn1->
PteFrame <=
MmHighestPhysicalPage);
01474
01475 Pfn2 =
MI_PFN_ELEMENT (Pfn1->
PteFrame);
01476
01477
01478
01479
01480
01481
01482
if (SelfMapPage ==
FALSE) {
01483
01484
01485
01486
01487
01488
ASSERT (Pfn1->
u2.ShareCount == 1);
01489
#if !defined (_WIN64)
01490
01491
01492
01493
01494
01495
01496
01497
ASSERT (Pfn1->
PteFrame ==
MI_GET_PAGE_FRAME_FROM_PTE (SelfMapPde));
01498
#endif
01499
ASSERT (Pfn2->
u2.ShareCount > 2);
01500 }
01501
else {
01502
ASSERT (Pfn1 == Pfn2);
01503
ASSERT (Pfn1->
u2.ShareCount == 2);
01504 }
01505
01506
01507
01508
01509
01510
01511 PointerPte = (
PMMPTE)
MiMapPageInHyperSpace (PageFrameIndex, &OldIrql2);
01512
01513 i = 0;
01514
while (i <
PTE_PER_PAGE) {
01515
if (PointerPte->
u.Long != 0 && PointerPte->
u.Long !=
MM_KERNEL_NOACCESS_PTE) {
01516
DbgPrint(
"MM: Deleting session page table: Index %d PTE %p is not zero! %p\n",
01517 i,
01518 PointerPte,
01519 PointerPte->
u.Long);
01520 DbgBreakPoint();
01521 }
01522 PointerPte += 1;
01523 i += 1;
01524 }
01525
01526
MiUnmapPageInHyperSpace (OldIrql2);
01527
01528
#endif // DBG
01529
01530
if (SelfMapPage ==
FALSE) {
01531
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01532 }
01533
else {
01534
ASSERT (Pfn1 == Pfn2);
01535
ASSERT (Pfn1->
u2.ShareCount == 2);
01536 Pfn1->
u2.ShareCount -= 1;
01537 }
01538
01539
MI_SET_PFN_DELETED (Pfn1);
01540
MiDecrementShareCountOnly (PageFrameIndex);
01541 }
01542
01543 BOOLEAN
01544 MiDereferenceSession(
01545 VOID
01546 )
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 {
01574 KIRQL OldIrql;
01575 ULONG
Index;
01576 ULONG CountReleased;
01577 ULONG SessionId;
01578 PFN_NUMBER PageFrameIndex;
01579 ULONG SessionDataPdeIndex;
01580
KEVENT Event;
01581
MMPTE PreviousPte;
01582
PMMPFN Pfn1;
01583
PMMPTE PointerPpe;
01584
PMMPTE PointerPte;
01585
PMMPTE EndPte;
01586
PMMPTE GlobalPteEntrySave;
01587
PMMPTE StartPde;
01588
PMMPTE EndPde;
01589
PMM_SESSION_SPACE SessionGlobal;
01590
MMPTE SavePageTables[
MI_SESSION_SPACE_PAGE_TABLES];
01591 BOOLEAN WorkingSetWasInitialized;
01592 ULONG AttachCount;
01593
PEPROCESS Process;
01594
01595
ASSERT ((
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 1) ||
01596 ((
MmSessionSpace->
u.Flags.Initialized == 0) && (
PsGetCurrentProcess()->Vm.u.Flags.SessionLeader == 1) && (
MmSessionSpace->
ReferenceCount == 1)));
01597
01598 SessionId =
MmSessionSpace->
SessionId;
01599
01600
ASSERT (RtlCheckBit (
MiSessionIdBitmap, SessionId));
01601
01602
LOCK_SESSION (OldIrql);
01603
01604
if (
MmSessionSpace->
ReferenceCount > 1) {
01605
01606
MmSessionSpace->
ReferenceCount -= 1;
01607
01608
UNLOCK_SESSION (OldIrql);
01609
01610 Process =
PsGetCurrentProcess();
01611
01612
LOCK_EXPANSION (OldIrql);
01613
01614 Process->
Vm.
u.Flags.ProcessInSession = 0;
01615
01616
UNLOCK_EXPANSION (OldIrql);
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
if (Process->
Vm.
u.Flags.SessionLeader == 1) {
01635
01636
#if defined (_WIN64)
01637
StartPde =
MiGetPpeAddress (
MmSessionBase);
01638 StartPde->
u.Long =
ZeroKernelPte.
u.Long;
01639
#else
01640
StartPde =
MiGetPdeAddress (
MmSessionBase);
01641 EndPde =
MiGetPdeAddress (
MI_SESSION_SPACE_END);
01642 RtlZeroMemory (StartPde, (EndPde - StartPde) *
sizeof(
MMPTE));
01643
#endif
01644
01645
01646
01647
01648
01649
MI_FLUSH_SESSION_TB (OldIrql);
01650 }
01651
01652
#if defined(_IA64_)
01653
KeDetachSessionSpace();
01654
#endif
01655
01656
return FALSE;
01657 }
01658
01659
01660
01661
01662
01663
MmSessionSpace->
u.Flags.BeingDeleted = 1;
01664
01665
01666
01667
01668
01669
01670
01671
UNLOCK_SESSION (OldIrql);
01672
01673 SessionGlobal =
SESSION_GLOBAL (
MmSessionSpace);
01674
01675
LOCK_EXPANSION (OldIrql);
01676
01677
01678
01679
01680
01681
01682
01683
ASSERT (
MmSessionSpace->
u.Flags.DeletePending == 0);
01684
01685
MmSessionSpace->
u.Flags.DeletePending = 1;
01686
01687 AttachCount =
MmSessionSpace->
AttachCount;
01688
01689
if (AttachCount) {
01690
01691
KeInitializeEvent (&
MmSessionSpace->
AttachEvent,
01692 NotificationEvent,
01693
FALSE);
01694
01695
UNLOCK_EXPANSION (OldIrql);
01696
01697
KeWaitForSingleObject( &
MmSessionSpace->
AttachEvent,
01698
WrVirtualMemory,
01699
KernelMode,
01700
FALSE,
01701 (PLARGE_INTEGER)
NULL);
01702
01703
LOCK_EXPANSION (OldIrql);
01704
01705
ASSERT (
MmSessionSpace->
u.Flags.DeletePending == 1);
01706
ASSERT (
MmSessionSpace->
AttachCount == 0);
01707 }
01708
01709
if (
MmSessionSpace->
Vm.
u.Flags.BeingTrimmed) {
01710
01711
01712
01713
01714
01715
01716
01717
KeInitializeEvent(&
Event, NotificationEvent,
FALSE);
01718
01719
MmSessionSpace->
Vm.
WorkingSetExpansionLinks.Blink = (PLIST_ENTRY)&
Event;
01720
01721
01722
01723
01724
01725
KeEnterCriticalRegion();
01726
UNLOCK_EXPANSION_AND_THEN_WAIT (OldIrql);
01727
01728
KeWaitForSingleObject(&
Event,
01729
WrVirtualMemory,
01730
KernelMode,
01731
FALSE,
01732 (PLARGE_INTEGER)
NULL);
01733
KeLeaveCriticalRegion();
01734
01735
LOCK_EXPANSION (OldIrql);
01736 }
01737
else if (
MmSessionSpace->
u.Flags.WorkingSetInserted == 1) {
01738
01739
01740
01741
01742
01743
01744 RemoveEntryList (&SessionGlobal->
Vm.
WorkingSetExpansionLinks);
01745
01746
MmSessionSpace->
u.Flags.WorkingSetInserted = 0;
01747 }
01748
01749
if (
MmSessionSpace->
u.Flags.SessionListInserted == 1) {
01750
01751 RemoveEntryList (&SessionGlobal->
WsListEntry);
01752
01753
MmSessionSpace->
u.Flags.SessionListInserted = 0;
01754 }
01755
01756
MiSessionCount -= 1;
01757
01758
UNLOCK_EXPANSION (OldIrql);
01759
01760
#if DBG
01761
if (
PsGetCurrentProcess()->Vm.u.Flags.SessionLeader == 0) {
01762
ASSERT (
MmSessionSpace->
ProcessOutSwapCount == 0);
01763
ASSERT (
MmSessionSpace->
ReferenceCount == 1);
01764 }
01765
#endif
01766
01767
MM_SNAP_SESS_MEMORY_COUNTERS(0);
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
if (
MmSessionSpace->
Win32KDriverObject.
DriverUnload ) {
01778
MmSessionSpace->
Win32KDriverObject.
DriverUnload (&
MmSessionSpace->
Win32KDriverObject);
01779 }
01780
01781
01782
01783
01784
01785
01786
MiCheckSessionPoolAllocations ();
01787
01788
ASSERT (
MmSessionSpace->
ReferenceCount == 1);
01789
01790
MM_SNAP_SESS_MEMORY_COUNTERS(1);
01791
01792
01793
01794
01795
01796
MiFreeSessionSpaceMap ();
01797
01798
MM_SNAP_SESS_MEMORY_COUNTERS(2);
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
MiSessionUnloadAllImages ();
01809
01810
MM_SNAP_SESS_MEMORY_COUNTERS(3);
01811
01812
01813
01814
01815
01816
MiFreeSessionPoolBitMaps ();
01817
01818
MM_SNAP_SESS_MEMORY_COUNTERS(4);
01819
01820
01821
01822
01823
01824
01825
01826 GlobalPteEntrySave =
MmSessionSpace->
GlobalPteEntry;
01827
01828
01829
01830
01831
01832
#if DBG
01833
01834
01835
01836
01837
01838
01839 MiCheckSessionVirtualSpace ((PVOID)
MI_SESSION_IMAGE_START,
01840
MI_SESSION_IMAGE_SIZE);
01841
#endif
01842
01843
MM_SNAP_SESS_MEMORY_COUNTERS(5);
01844
01845
#if DBG
01846
01847
01848
01849
01850
01851 MiCheckSessionVirtualSpace ((PVOID)
MI_SESSION_VIEW_START,
01852
MI_SESSION_VIEW_SIZE);
01853
#endif
01854
01855
01856
01857
01858
01859
01860
#if defined (_WIN64)
01861
RtlCopyMemory (SavePageTables,
01862
MiGetPdeAddress (
MmSessionBase),
01863
MI_SESSION_SPACE_PAGE_TABLES *
sizeof (
MMPTE));
01864
#else
01865
RtlCopyMemory (SavePageTables,
01866
MmSessionSpace->
PageTables,
01867
MI_SESSION_SPACE_PAGE_TABLES * sizeof (
MMPTE));
01868
#endif
01869
01870
MM_SNAP_SESS_MEMORY_COUNTERS(6);
01871
01872
#if DBG
01873
01874
01875
01876
01877
01878
01879 Pfn1 =
MI_PFN_ELEMENT (
MmSessionSpace->
SessionPageDirectoryIndex);
01880
01881
01882
01883
01884
01885
01886
ASSERT (Pfn1->
u2.ShareCount > 1);
01887
#endif
01888
01889 CountReleased = 0;
01890
01891
if (
MmSessionSpace->
u.Flags.HasWsLock == 1) {
01892
01893 PointerPte =
MiGetPteAddress (
MI_SESSION_SPACE_WS);
01894 EndPte =
MiGetPteAddress (
MmSessionSpace->
Vm.
VmWorkingSetList->
HighestPermittedHashAddress);
01895
01896
for ( ; PointerPte < EndPte; PointerPte += 1) {
01897
01898
if (PointerPte->
u.Long) {
01899
01900
ASSERT (PointerPte->
u.Hard.Valid == 1);
01901
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_WS_PAGE_FREE, 1);
01902
01903
MmSessionSpace->
CommittedPages -= 1;
01904
MmSessionSpace->
NonPagablePages -= 1;
01905 CountReleased += 1;
01906 }
01907 }
01908 WorkingSetWasInitialized =
TRUE;
01909
MmSessionSpace->
u.Flags.HasWsLock = 0;
01910 }
01911
else {
01912 WorkingSetWasInitialized =
FALSE;
01913 }
01914
01915
01916
01917
01918
01919
01920
#if defined (_WIN64)
01921
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGE_FREE, 2);
01922
MmSessionSpace->
CommittedPages -= 2;
01923
MmSessionSpace->
NonPagablePages -= 2;
01924 CountReleased += 2;
01925
#else
01926
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_INITIAL_PAGE_FREE, 1);
01927
MmSessionSpace->
CommittedPages -= 1;
01928
MmSessionSpace->
NonPagablePages -= 1;
01929 CountReleased += 1;
01930
#endif
01931
01932
01933
01934
01935
01936
for (
Index = 0;
Index <
MI_SESSION_SPACE_PAGE_TABLES;
Index += 1) {
01937
01938 StartPde = &SavePageTables[
Index];
01939
01940
if (StartPde->
u.Long !=
ZeroKernelPte.
u.Long) {
01941
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_PAGETABLE_FREE, 1);
01942
MmSessionSpace->
CommittedPages -= 1;
01943
MmSessionSpace->
NonPagablePages -= 1;
01944 CountReleased += 1;
01945 }
01946 }
01947
01948
ASSERT (
MmSessionSpace->
NonPagablePages == 0);
01949
01950
01951
01952
01953
01954
01955
ASSERT (
MmSessionSpace->
CommittedPages == 0);
01956
01957
MiReturnCommitment (CountReleased);
01958
01959
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE, CountReleased);
01960
01961
01962
01963
01964
01965
01966
if (WorkingSetWasInitialized ==
TRUE) {
01967
ExDeleteResource (&SessionGlobal->
WsLock);
01968
01969 PointerPte =
MiGetPteAddress (
MI_SESSION_SPACE_WS);
01970 EndPte =
MiGetPteAddress (
MmSessionSpace->
Vm.
VmWorkingSetList->
HighestPermittedHashAddress);
01971
01972
for ( ; PointerPte < EndPte; PointerPte += 1) {
01973
01974
if (PointerPte->
u.Long) {
01975
01976
ASSERT (PointerPte->
u.Hard.Valid == 1);
01977
01978
01979
01980
01981
01982 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
01983
01984 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
01985
01986
01987
01988
01989
01990
LOCK_PFN (OldIrql);
01991
01992
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
01993
01994
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
01995
MI_SET_PFN_DELETED (Pfn1);
01996
MiDecrementShareCountOnly (PageFrameIndex);
01997
MI_WRITE_INVALID_PTE (PointerPte,
ZeroKernelPte);
01998
01999
MmResidentAvailablePages += 1;
02000
MM_BUMP_COUNTER(52, 1);
02001
02002
UNLOCK_PFN (OldIrql);
02003 }
02004 }
02005 }
02006
02007
#if defined(_IA64_)
02008
KeDisableSessionSharing(&SessionGlobal->SessionMapInfo);
02009
#endif
02010
02011
02012
02013
02014
02015
02016 PointerPte =
MiGetPteAddress (
MmSessionSpace);
02017
02018
02019
02020
02021
02022 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
02023
02024 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02025
02026
02027
02028
02029
02030
ASSERT (Pfn1->
u1.WsIndex == 0);
02031
02032
LOCK_PFN (OldIrql);
02033
02034
ASSERT (Pfn1->
u3.e2.ReferenceCount == 1);
02035
02036
ASSERT (Pfn1->
PteFrame ==
MmSessionSpace->
SessionPageDirectoryIndex);
02037
02038
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
02039
MI_SET_PFN_DELETED (Pfn1);
02040
MiDecrementShareCountOnly (PageFrameIndex);
02041
MI_WRITE_INVALID_PTE (PointerPte,
ZeroKernelPte);
02042
02043
MmResidentAvailablePages += CountReleased;
02044
02045
MM_BUMP_COUNTER(53, CountReleased);
02046
02047
MmResidentAvailablePages +=
MI_SESSION_SPACE_WORKING_SET_MINIMUM;
02048
02049
MM_BUMP_COUNTER(56,
MI_SESSION_SPACE_WORKING_SET_MINIMUM);
02050
02051
UNLOCK_PFN (OldIrql);
02052
02053 StartPde =
MiGetPdeAddress (
MmSessionBase);
02054
02055 EndPde =
MiGetPdeAddress (
MI_SESSION_SPACE_END);
02056
02057 RtlZeroMemory (StartPde, (EndPde - StartPde) *
sizeof(
MMPTE));
02058
02059
02060
02061
02062
02063
MI_FLUSH_SESSION_TB (OldIrql);
02064
02065
02066
02067
02068
02069
MiReleaseSystemPtes (GlobalPteEntrySave, 1,
SystemPteSpace);
02070
02071
02072
02073
02074
02075
02076
02077 SessionDataPdeIndex =
MiGetPdeSessionIndex (
MmSessionSpace);
02078
02079
LOCK_PFN (OldIrql);
02080
02081
for (
Index = 0;
Index <
MI_SESSION_SPACE_PAGE_TABLES;
Index += 1) {
02082
02083
if (
Index == SessionDataPdeIndex) {
02084
02085
02086
02087
02088
02089
continue;
02090 }
02091
02092
MiSessionDeletePde (&SavePageTables[
Index],
02093 WorkingSetWasInitialized,
02094 &SavePageTables[SessionDataPdeIndex]);
02095 }
02096
02097
MiSessionDeletePde (&SavePageTables[SessionDataPdeIndex],
02098 WorkingSetWasInitialized,
02099 &SavePageTables[SessionDataPdeIndex]);
02100
02101
#if defined (_WIN64)
02102
02103
02104
02105
02106
02107 PointerPpe =
MiGetPpeAddress (
MmSessionSpace);
02108 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe);
02109 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02110
MI_SET_PFN_DELETED (Pfn1);
02111
MiDecrementShareCountOnly (PageFrameIndex);
02112
02113
MI_FLUSH_SINGLE_SESSION_TB (
MiGetPdeAddress (
MmSessionSpace),
02114
TRUE,
02115
TRUE,
02116 (PHARDWARE_PTE)PointerPpe,
02117
ZeroKernelPte.
u.Flush,
02118 PreviousPte);
02119
#endif
02120
02121
UNLOCK_PFN (OldIrql);
02122
02123 ExAcquireFastMutex (&
MiSessionIdMutex);
02124
02125
ASSERT (RtlCheckBit (
MiSessionIdBitmap, SessionId));
02126
RtlClearBits (
MiSessionIdBitmap, SessionId, 1);
02127
02128 ExReleaseFastMutex (&
MiSessionIdMutex);
02129
02130
LOCK_EXPANSION (OldIrql);
02131
02132
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession = 0;
02133
02134
UNLOCK_EXPANSION (OldIrql);
02135
02136
02137
02138
02139
02140
return TRUE;
02141 }
02142
02143
NTSTATUS
02144 MiSessionCommitImagePages(
02145 IN PVOID VirtualAddress,
02146 IN SIZE_T NumberOfBytes
02147 )
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175 {
02176 KIRQL WsIrql;
02177 KIRQL OldIrql;
02178 ULONG Color;
02179 PFN_NUMBER SizeInPages;
02180
PMMPFN Pfn1;
02181 ULONG_PTR AllocationStart;
02182 PFN_NUMBER PageFrameIndex;
02183
NTSTATUS Status;
02184
PMMPTE StartPte, EndPte;
02185
MMPTE TempPte;
02186
02187
SYSLOAD_LOCK_OWNED_BY_ME ();
02188
02189
if (NumberOfBytes == 0) {
02190
return STATUS_SUCCESS;
02191 }
02192
02193
if (
MmIsAddressValid(
MmSessionSpace) ==
FALSE) {
02194
#if DBG
02195
DbgPrint (
"MiSessionCommitImagePages: No session space!\n");
02196
#endif
02197
return STATUS_NO_MEMORY;
02198 }
02199
02200
ASSERT (((ULONG_PTR)VirtualAddress %
PAGE_SIZE) == 0);
02201
ASSERT ((NumberOfBytes %
PAGE_SIZE) == 0);
02202
02203 SizeInPages = (PFN_NUMBER)(NumberOfBytes >>
PAGE_SHIFT);
02204
02205
02206
02207
02208
02209 AllocationStart = (ULONG_PTR)VirtualAddress;
02210
02211
02212
02213
02214
02215
LOCK_SESSION_SPACE_WS(WsIrql);
02216
02217
02218
02219
02220
02221
02222
Status =
MiSessionCommitPageTables ((PVOID)AllocationStart,
02223 (PVOID)(AllocationStart + NumberOfBytes));
02224
02225
if (!
NT_SUCCESS(
Status)) {
02226
#if DBG
02227
if (MmDebug &
MM_DBG_SESSIONS) {
02228
DbgPrint(
"MiSessionCommitImagePages: Could not commit pagetables, Not enough memory! MmResidentAvailablePages %d, SizeInPages %d\n",
02229
MmResidentAvailablePages,
02230 SizeInPages);
02231 }
02232
#endif
02233
UNLOCK_SESSION_SPACE_WS(WsIrql);
02234
return STATUS_NO_MEMORY;
02235 }
02236
02237
02238
02239
02240
02241
02242 StartPte =
MiGetPteAddress (AllocationStart);
02243 EndPte =
MiGetPteAddress (AllocationStart + NumberOfBytes);
02244
02245
if (
MiChargeCommitment (SizeInPages,
NULL) ==
FALSE) {
02246
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_COMMIT);
02247
UNLOCK_SESSION_SPACE_WS(WsIrql);
02248
return STATUS_NO_MEMORY;
02249 }
02250
02251
MM_TRACK_COMMIT (
MM_DBG_COMMIT_SESSION_IMAGE_PAGES, SizeInPages);
02252
02253 TempPte =
ValidKernelPteLocal;
02254
02255
LOCK_PFN (OldIrql);
02256
02257
02258
02259
02260
02261
if ((SPFN_NUMBER)SizeInPages >
MI_NONPAGABLE_MEMORY_AVAILABLE() - 20) {
02262
UNLOCK_PFN (OldIrql);
02263
MiReturnCommitment (SizeInPages);
02264
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SESSION_IMAGE_FAILURE1, SizeInPages);
02265
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_RESIDENT);
02266
UNLOCK_SESSION_SPACE_WS(WsIrql);
02267
return STATUS_NO_MEMORY;
02268 }
02269
02270
MmResidentAvailablePages -= SizeInPages;
02271
02272
MM_BUMP_COUNTER(45, SizeInPages);
02273
02274
while (StartPte < EndPte) {
02275
02276
ASSERT (StartPte->
u.Long ==
ZeroKernelPte.
u.Long);
02277
02278
MiEnsureAvailablePageOrWait (
NULL,
NULL);
02279
02280 Color =
MI_GET_PAGE_COLOR_FROM_SESSION (
MmSessionSpace);
02281
02282 PageFrameIndex =
MiRemoveZeroPageIfAny (Color);
02283
if (PageFrameIndex == 0) {
02284 PageFrameIndex =
MiRemoveAnyPage (Color);
02285
UNLOCK_PFN (OldIrql);
02286
MiZeroPhysicalPage (PageFrameIndex, Color);
02287
LOCK_PFN (OldIrql);
02288 }
02289
02290 TempPte.
u.Hard.PageFrameNumber = PageFrameIndex;
02291
MI_WRITE_VALID_PTE (StartPte, TempPte);
02292
02293 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02294
02295
ASSERT (Pfn1->
u1.WsIndex == 0);
02296
02297
MiInitializePfn (PageFrameIndex, StartPte, 1);
02298
02299 KeFillEntryTb ((PHARDWARE_PTE) StartPte, (
PMMPTE)AllocationStart,
FALSE);
02300
02301 StartPte += 1;
02302 AllocationStart +=
PAGE_SIZE;
02303 }
02304
02305
UNLOCK_PFN (OldIrql);
02306
02307
MmSessionSpace->
CommittedPages += SizeInPages;
02308
MmSessionSpace->
NonPagablePages += SizeInPages;
02309
02310
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_DRIVER_PAGES_LOCKED, SizeInPages);
02311
02312
UNLOCK_SESSION_SPACE_WS(WsIrql);
02313
02314
return STATUS_SUCCESS;
02315 }
02316
02317
NTSTATUS
02318 MiSessionCommitPageTables(
02319 IN PVOID StartVa,
02320 IN PVOID EndVa
02321 )
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345 {
02346 KIRQL OldIrql;
02347 ULONG Color;
02348 ULONG
Index;
02349
PMMPTE StartPde, EndPde;
02350
MMPTE TempPte;
02351
PMMPFN Pfn1;
02352 ULONG Entry;
02353 ULONG SwapEntry;
02354 PFN_NUMBER SizeInPages;
02355 PFN_NUMBER PageTablePage;
02356 PVOID SessionPte;
02357
PMMWSL WorkingSetList;
02358
CHAR SavePageTables[
MI_SESSION_SPACE_PAGE_TABLES];
02359
02360
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
TRUE);
02361
02362
MM_SESSION_SPACE_WS_LOCK_ASSERT();
02363
02364
ASSERT (StartVa >= (PVOID)
MmSessionBase);
02365
ASSERT (EndVa < (PVOID)
MI_SESSION_SPACE_END);
02366
02367
02368
02369
02370
02371
02372 StartPde =
MiGetPdeAddress (StartVa);
02373 EndPde =
MiGetPdeAddress (EndVa);
02374
Index =
MiGetPdeSessionIndex (StartVa);
02375
02376 SizeInPages = 0;
02377
02378
while (StartPde <= EndPde) {
02379
#if defined (_WIN64)
02380
if (StartPde->
u.Long ==
ZeroKernelPte.
u.Long)
02381
#else
02382
if (
MmSessionSpace->
PageTables[
Index].
u.Long ==
ZeroKernelPte.
u.Long)
02383
#endif
02384
{
02385 SizeInPages += 1;
02386 }
02387 StartPde += 1;
02388
Index += 1;
02389 }
02390
02391
if (SizeInPages == 0) {
02392
return STATUS_SUCCESS;
02393 }
02394
02395
if (
MiChargeCommitment (SizeInPages,
NULL) ==
FALSE) {
02396
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_COMMIT);
02397
return STATUS_NO_MEMORY;
02398 }
02399
02400
MM_TRACK_COMMIT (
MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES, SizeInPages);
02401
02402 StartPde =
MiGetPdeAddress (StartVa);
02403
Index =
MiGetPdeSessionIndex (StartVa);
02404
02405 TempPte =
ValidKernelPdeLocal;
02406
02407
LOCK_PFN (OldIrql);
02408
02409
02410
02411
02412
02413
if ((SPFN_NUMBER)SizeInPages >
MI_NONPAGABLE_MEMORY_AVAILABLE() - 20) {
02414
UNLOCK_PFN (OldIrql);
02415
MiReturnCommitment (SizeInPages);
02416
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SESSION_PAGETABLE_PAGES, SizeInPages);
02417
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_RESIDENT);
02418
return STATUS_NO_MEMORY;
02419 }
02420
02421
MmResidentAvailablePages -= SizeInPages;
02422
02423
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_PAGETABLE_ALLOC, SizeInPages);
02424
02425
MM_BUMP_COUNTER(44, SizeInPages);
02426
02427 WorkingSetList =
MmSessionSpace->
Vm.
VmWorkingSetList;
02428
02429 RtlZeroMemory (SavePageTables,
sizeof (SavePageTables));
02430
02431
while (StartPde <= EndPde) {
02432
02433
#if defined (_WIN64)
02434
if (StartPde->
u.Long ==
ZeroKernelPte.
u.Long)
02435
#else
02436
if (
MmSessionSpace->
PageTables[
Index].
u.Long ==
ZeroKernelPte.
u.Long)
02437
#endif
02438
{
02439
02440
ASSERT (StartPde->
u.Hard.Valid == 0);
02441
02442 SavePageTables[
Index] = 1;
02443
02444
MiEnsureAvailablePageOrWait (
NULL,
NULL);
02445
02446 Color =
MI_GET_PAGE_COLOR_FROM_SESSION (
MmSessionSpace);
02447
02448 PageTablePage =
MiRemoveZeroPageIfAny (Color);
02449
if (PageTablePage == 0) {
02450 PageTablePage =
MiRemoveAnyPage (Color);
02451
UNLOCK_PFN (OldIrql);
02452
MiZeroPhysicalPage (PageTablePage, Color);
02453
LOCK_PFN (OldIrql);
02454 }
02455
02456 TempPte.
u.Hard.PageFrameNumber = PageTablePage;
02457
MI_WRITE_VALID_PTE (StartPde, TempPte);
02458
02459
#if !defined (_WIN64)
02460
MmSessionSpace->
PageTables[
Index] = TempPte;
02461
#endif
02462
MmSessionSpace->
NonPagablePages += 1;
02463
MmSessionSpace->
CommittedPages += 1;
02464
02465
MiInitializePfnForOtherProcess (PageTablePage,
02466 StartPde,
02467
MmSessionSpace->
SessionPageDirectoryIndex);
02468 }
02469
02470 StartPde += 1;
02471
Index += 1;
02472 }
02473
02474
UNLOCK_PFN (OldIrql);
02475
02476 StartPde =
MiGetPdeAddress (StartVa);
02477
Index =
MiGetPdeSessionIndex (StartVa);
02478
02479
while (StartPde <= EndPde) {
02480
02481
if (SavePageTables[
Index] == 1) {
02482
02483
ASSERT (StartPde->
u.Hard.Valid == 1);
02484
02485 PageTablePage =
MI_GET_PAGE_FRAME_FROM_PTE (StartPde);
02486
02487 Pfn1 =
MI_PFN_ELEMENT (PageTablePage);
02488
02489
ASSERT (Pfn1->
u1.Event ==
NULL);
02490 Pfn1->
u1.Event = (PVOID)
PsGetCurrentThread ();
02491
02492 SessionPte =
MiGetVirtualAddressMappedByPte (StartPde);
02493
02494
MiAddValidPageToWorkingSet (SessionPte,
02495 StartPde,
02496 Pfn1,
02497 0);
02498
02499 Entry =
MiLocateWsle (SessionPte,
02500
MmSessionSpace->
Vm.
VmWorkingSetList,
02501 Pfn1->
u1.WsIndex);
02502
02503
if (Entry >= WorkingSetList->
FirstDynamic) {
02504
02505 SwapEntry = WorkingSetList->
FirstDynamic;
02506
02507
if (Entry != WorkingSetList->
FirstDynamic) {
02508
02509
02510
02511
02512
02513
MiSwapWslEntries (Entry, SwapEntry, &
MmSessionSpace->
Vm);
02514 }
02515
02516 WorkingSetList->
FirstDynamic += 1;
02517 }
02518
else {
02519 SwapEntry = Entry;
02520 }
02521
02522
02523
02524
02525
02526
MmSessionSpace->
Wsle[SwapEntry].
u1.e1.LockedInWs = 1;
02527 }
02528
02529 StartPde += 1;
02530
Index += 1;
02531 }
02532
02533
return STATUS_SUCCESS;
02534 }
02535
02536
#if DBG
02537
typedef struct _MISWAP {
02538 ULONG Flag;
02539
PEPROCESS Process;
02540
PMM_SESSION_SPACE Session;
02541 ULONG OutSwapCount;
02542 } MISWAP, *PMISWAP;
02543
02544 ULONG MiSessionInfo[4];
02545 MISWAP MiSessionSwap[0x100];
02546 ULONG MiSwapIndex;
02547
#endif
02548
02549
02550
VOID
02551 MiSessionOutSwapProcess (
02552 IN
PEPROCESS Process
02553 )
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578 {
02579
MMPTE TempPte;
02580 PFN_NUMBER PdePage;
02581
PMMPTE PageDirectoryMap;
02582 KIRQL OldIrql;
02583 PFN_NUMBER SessionPage;
02584
PMM_SESSION_SPACE SessionGlobal;
02585
#if DBG
02586
ULONG InCount;
02587 ULONG OutCount;
02588 PLIST_ENTRY NextEntry;
02589
#endif
02590
#if defined (_X86PAE_)
02591
ULONG i;
02592 PPAE_ENTRY PaeVa;
02593
#endif
02594
02595
ASSERT (
MiHydra ==
TRUE && Process->Vm.u.Flags.ProcessInSession == 1);
02596
02597
02598
02599
02600
02601
02602
if (Process->Vm.u.Flags.SessionLeader == 1) {
02603
return;
02604 }
02605
02606
#if defined (_X86PAE_)
02607
PaeVa = Process->PaeTop;
02608
02609
#if DBG
02610
for (i = 0; i < PD_PER_SYSTEM; i += 1) {
02611
ASSERT (PaeVa->PteEntry[i].u.Hard.Valid == 1);
02612 }
02613
#endif
02614
02615 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&PaeVa->PteEntry[MiGetPdPteOffset(
MmSessionSpace)]);
02616
02617
#else
02618
02619 PdePage =
MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process);
02620
02621
#endif
02622
02623 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02624
02625
#if defined (_WIN64)
02626
TempPte = PageDirectoryMap[
MiGetPpeOffset(
MmSessionSpace)];
02627
02628
MiUnmapPageInHyperSpace (OldIrql);
02629
02630 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02631
02632 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02633
#endif
02634
02635 TempPte = PageDirectoryMap[
MiGetPdeOffset(
MmSessionSpace)];
02636
02637
MiUnmapPageInHyperSpace (OldIrql);
02638
02639 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02640
02641 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02642
02643 TempPte = PageDirectoryMap[
MiGetPteOffset(
MmSessionSpace)];
02644
02645
MiUnmapPageInHyperSpace (OldIrql);
02646
02647 SessionPage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02648
02649 SessionGlobal = (
PMM_SESSION_SPACE)
MiMapPageInHyperSpace ( SessionPage,
02650 &OldIrql);
02651
02652
ASSERT (
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress(SessionGlobal->
GlobalVirtualAddress)) == SessionPage);
02653
02654 SessionGlobal = SessionGlobal->
GlobalVirtualAddress;
02655
02656
MiUnmapPageInHyperSpace (OldIrql);
02657
02658
LOCK_EXPANSION (OldIrql);
02659
02660 SessionGlobal->
ProcessOutSwapCount += 1;
02661
02662
#if DBG
02663
ASSERT ((LONG)SessionGlobal->
ProcessOutSwapCount > 0);
02664
02665 InCount = 0;
02666 OutCount = 0;
02667 NextEntry = SessionGlobal->
ProcessList.Flink;
02668
02669
while (NextEntry != &SessionGlobal->
ProcessList) {
02670 Process = CONTAINING_RECORD (NextEntry,
EPROCESS, SessionProcessLinks);
02671
02672
if (Process->ProcessOutswapEnabled ==
TRUE) {
02673 OutCount += 1;
02674 }
02675
else {
02676 InCount += 1;
02677 }
02678
02679 NextEntry = NextEntry->Flink;
02680 }
02681
02682
if (InCount + OutCount > SessionGlobal->
ReferenceCount) {
02683
DbgPrint (
"MiSessionOutSwapProcess : process count mismatch %p %x %x %x\n",
02684 SessionGlobal,
02685 SessionGlobal->
ReferenceCount,
02686 InCount,
02687 OutCount);
02688 DbgBreakPoint ();
02689 }
02690
02691
if (SessionGlobal->
ProcessOutSwapCount != OutCount) {
02692
DbgPrint (
"MiSessionOutSwapProcess : out count mismatch %p %x %x %x %x\n",
02693 SessionGlobal,
02694 SessionGlobal->
ReferenceCount,
02695 SessionGlobal->
ProcessOutSwapCount,
02696 InCount,
02697 OutCount);
02698 DbgBreakPoint ();
02699 }
02700
02701
ASSERT (SessionGlobal->
ProcessOutSwapCount <= SessionGlobal->
ReferenceCount);
02702
02703 MiSessionSwap[MiSwapIndex].Flag = 1;
02704 MiSessionSwap[MiSwapIndex].Process = Process;
02705 MiSessionSwap[MiSwapIndex].Session = SessionGlobal;
02706 MiSessionSwap[MiSwapIndex].OutSwapCount = SessionGlobal->
ProcessOutSwapCount;
02707 MiSwapIndex += 1;
02708
if (MiSwapIndex == 0x100) {
02709 MiSwapIndex = 0;
02710 }
02711
#endif
02712
02713
if (SessionGlobal->
ProcessOutSwapCount == SessionGlobal->
ReferenceCount) {
02714 SessionGlobal->
Vm.
u.Flags.TrimHard = 1;
02715
#if DBG
02716
if (MmDebug &
MM_DBG_SESSIONS) {
02717
DbgPrint (
"Mm: Last process (%d total) just swapped out for session %d, %d pages\n",
02718 SessionGlobal->
ProcessOutSwapCount,
02719 SessionGlobal->
SessionId,
02720 SessionGlobal->
Vm.
WorkingSetSize);
02721 }
02722 MiSessionInfo[0] += 1;
02723
#endif
02724
KeQuerySystemTime (&SessionGlobal->
LastProcessSwappedOutTime);
02725 }
02726
#if DBG
02727
else {
02728 MiSessionInfo[1] += 1;
02729 }
02730
#endif
02731
02732
UNLOCK_EXPANSION (OldIrql);
02733 }
02734
02735
02736
VOID
02737 MiSessionInSwapProcess (
02738 IN
PEPROCESS Process
02739 )
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763 {
02764
MMPTE TempPte;
02765 PFN_NUMBER PdePage;
02766
PMMPTE PageDirectoryMap;
02767 KIRQL OldIrql;
02768 PFN_NUMBER SessionPage;
02769
PMM_SESSION_SPACE SessionGlobal;
02770
#if DBG
02771
ULONG InCount;
02772 ULONG OutCount;
02773 PLIST_ENTRY NextEntry;
02774
#endif
02775
#if defined (_X86PAE_)
02776
ULONG i;
02777 PPAE_ENTRY PaeVa;
02778
#endif
02779
02780
ASSERT (
MiHydra ==
TRUE && Process->Vm.u.Flags.ProcessInSession == 1);
02781
02782
02783
02784
02785
02786
02787
if (Process->Vm.u.Flags.SessionLeader == 1) {
02788
return;
02789 }
02790
02791
ASSERT (
MiHydra ==
TRUE && Process->Vm.u.Flags.ProcessInSession == 1);
02792
02793
02794
02795
02796
02797
02798
if (Process->Vm.u.Flags.SessionLeader == 1) {
02799
return;
02800 }
02801
02802
#if defined (_X86PAE_)
02803
PaeVa = Process->PaeTop;
02804
02805
#if DBG
02806
for (i = 0; i < PD_PER_SYSTEM; i += 1) {
02807
ASSERT (PaeVa->PteEntry[i].u.Hard.Valid == 1);
02808 }
02809
#endif
02810
02811 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&PaeVa->PteEntry[MiGetPdPteOffset(
MmSessionSpace)]);
02812
02813
#else
02814
PdePage =
MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process);
02815
#endif
02816
02817 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02818
02819
#if defined (_WIN64)
02820
TempPte = PageDirectoryMap[
MiGetPpeOffset(
MmSessionSpace)];
02821
02822
MiUnmapPageInHyperSpace (OldIrql);
02823
02824 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02825
02826 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02827
#endif
02828
02829 TempPte = PageDirectoryMap[
MiGetPdeOffset(
MmSessionSpace)];
02830
02831
MiUnmapPageInHyperSpace (OldIrql);
02832
02833 PdePage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02834
02835 PageDirectoryMap =
MiMapPageInHyperSpace (PdePage, &OldIrql);
02836
02837 TempPte = PageDirectoryMap[
MiGetPteOffset(
MmSessionSpace)];
02838
02839
MiUnmapPageInHyperSpace (OldIrql);
02840
02841 SessionPage =
MI_GET_PAGE_FRAME_FROM_PTE (&TempPte);
02842
02843 SessionGlobal = (
PMM_SESSION_SPACE)
MiMapPageInHyperSpace (SessionPage,
02844 &OldIrql);
02845
02846
ASSERT (
MI_GET_PAGE_FRAME_FROM_PTE (
MiGetPteAddress(SessionGlobal->
GlobalVirtualAddress)) == SessionPage);
02847
02848 SessionGlobal = SessionGlobal->
GlobalVirtualAddress;
02849
02850
MiUnmapPageInHyperSpace (OldIrql);
02851
02852
LOCK_EXPANSION (OldIrql);
02853
02854
#if DBG
02855
ASSERT ((LONG)SessionGlobal->
ProcessOutSwapCount > 0);
02856
02857 InCount = 0;
02858 OutCount = 0;
02859 NextEntry = SessionGlobal->
ProcessList.Flink;
02860
02861
while (NextEntry != &SessionGlobal->
ProcessList) {
02862 Process = CONTAINING_RECORD (NextEntry,
EPROCESS, SessionProcessLinks);
02863
02864
if (Process->ProcessOutswapEnabled ==
TRUE) {
02865 OutCount += 1;
02866 }
02867
else {
02868 InCount += 1;
02869 }
02870
02871 NextEntry = NextEntry->Flink;
02872 }
02873
02874
if (InCount + OutCount > SessionGlobal->
ReferenceCount) {
02875
DbgPrint (
"MiSessionInSwapProcess : count mismatch %p %x %x %x\n",
02876 SessionGlobal,
02877 SessionGlobal->
ReferenceCount,
02878 InCount,
02879 OutCount);
02880 DbgBreakPoint ();
02881 }
02882
02883
if (SessionGlobal->
ProcessOutSwapCount != OutCount) {
02884
DbgPrint (
"MiSessionInSwapProcess : out count mismatch %p %x %x %x %x\n",
02885 SessionGlobal,
02886 SessionGlobal->
ReferenceCount,
02887 SessionGlobal->
ProcessOutSwapCount,
02888 InCount,
02889 OutCount);
02890 DbgBreakPoint ();
02891 }
02892
02893
ASSERT (SessionGlobal->
ProcessOutSwapCount <= SessionGlobal->
ReferenceCount);
02894
02895 MiSessionSwap[MiSwapIndex].Flag = 2;
02896 MiSessionSwap[MiSwapIndex].Process = Process;
02897 MiSessionSwap[MiSwapIndex].Session = SessionGlobal;
02898 MiSessionSwap[MiSwapIndex].OutSwapCount = SessionGlobal->
ProcessOutSwapCount;
02899 MiSwapIndex += 1;
02900
if (MiSwapIndex == 0x100) {
02901 MiSwapIndex = 0;
02902 }
02903
#endif
02904
02905
if (SessionGlobal->
ProcessOutSwapCount == SessionGlobal->
ReferenceCount) {
02906
#if DBG
02907
MiSessionInfo[2] += 1;
02908
if (MmDebug &
MM_DBG_SESSIONS) {
02909
DbgPrint (
"Mm: First process (%d total) just swapped back in for session %d, %d pages\n",
02910 SessionGlobal->
ProcessOutSwapCount,
02911 SessionGlobal->
SessionId,
02912 SessionGlobal->
Vm.
WorkingSetSize);
02913 }
02914
#endif
02915
SessionGlobal->
Vm.
u.Flags.TrimHard = 0;
02916 }
02917
#if DBG
02918
else {
02919 MiSessionInfo[3] += 1;
02920 }
02921
#endif
02922
02923 SessionGlobal->
ProcessOutSwapCount -= 1;
02924
02925
ASSERT ((LONG)SessionGlobal->
ProcessOutSwapCount >= 0);
02926
02927
UNLOCK_EXPANSION (OldIrql);
02928 }