Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

session.c File Reference

#include "mi.h"

Go to the source code of this file.

Defines

#define MM_MAXIMUM_CONCURRENT_SESSIONS   16384
#define MI_SESSION_COMMIT_CHARGE   2

Functions

VOID MiSessionAddProcess (PEPROCESS NewProcess)
VOID MiSessionRemoveProcess (VOID)
VOID MiInitializeSessionIds (VOID)
NTSTATUS MiSessionCreateInternal (OUT PULONG SessionId)
NTSTATUS MiSessionCommitPageTables (IN PVOID StartVa, IN PVOID EndVa)
BOOLEAN MiDereferenceSession (VOID)
VOID MiSessionDeletePde (IN PMMPTE Pde, IN BOOLEAN WorkingSetInitialized, IN PMMPTE SelfMapPde)
VOID MmSessionLeader (IN PEPROCESS Process)
VOID MmSessionSetUnloadAddress (IN PDRIVER_OBJECT pWin32KDevice)
NTSTATUS MmSessionCreate (OUT PULONG SessionId)
NTSTATUS MmSessionDelete (ULONG SessionId)
VOID MiAttachSession (IN PMM_SESSION_SPACE SessionGlobal)
VOID MiDetachSession (VOID)
NTSTATUS MiSessionCommitImagePages (IN PVOID VirtualAddress, IN SIZE_T NumberOfBytes)
VOID MiSessionOutSwapProcess (IN PEPROCESS Process)
VOID MiSessionInSwapProcess (IN PEPROCESS Process)

Variables

ULONG MiSessionCount
FAST_MUTEX MiSessionIdMutex
PRTL_BITMAP MiSessionIdBitmap


Define Documentation

#define MI_SESSION_COMMIT_CHARGE   2
 

Definition at line 35 of file session.c.

Referenced by MiSessionCreateInternal().

#define MM_MAXIMUM_CONCURRENT_SESSIONS   16384
 

Definition at line 26 of file session.c.

Referenced by MiInitializeSessionIds().


Function Documentation

VOID MiAttachSession IN PMM_SESSION_SPACE  SessionGlobal  ) 
 

Definition at line 1181 of file session.c.

References ASSERT, KeAttachSessionSpace(), MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MI_WRITE_VALID_PTE, MiGetPdeAddress, MiGetPpeAddress, MiHydra, MmSessionBase, PsGetCurrentProcess, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiEmptyAllWorkingSetsWorker(), and MmWorkingSetManager().

01187 : 01188 01189 Attaches to the specified session space. 01190 01191 Arguments: 01192 01193 SessionGlobal - Supplies a pointer to the session to attach to. 01194 01195 Return Value: 01196 01197 None. 01198 01199 Environment: 01200 01201 Kernel mode. No locks held. Current process must not have a session 01202 space - ie: the caller should be the system process or smss.exe. 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 }

BOOLEAN MiDereferenceSession VOID   ) 
 

Definition at line 1544 of file session.c.

References ASSERT, _MM_SESSION_SPACE::AttachCount, _MM_SESSION_SPACE::AttachEvent, _MM_SESSION_SPACE::CommittedPages, _DRIVER_OBJECT::DriverUnload, Event(), ExDeleteResource, FALSE, _MM_SESSION_SPACE::GlobalPteEntry, _MMWSL::HighestPermittedHashAddress, Index, KeDetachSessionSpace(), KeDisableSessionSharing(), KeEnterCriticalRegion, KeInitializeEvent, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_EXPANSION, LOCK_PFN, LOCK_SESSION, MI_FLUSH_SESSION_TB, MI_FLUSH_SINGLE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_SESSION_IMAGE_SIZE, MI_SESSION_IMAGE_START, MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MI_SESSION_SPACE_WORKING_SET_MINIMUM, MI_SESSION_SPACE_WS, MI_SESSION_VIEW_SIZE, MI_SESSION_VIEW_START, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiCheckSessionPoolAllocations(), MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiFreeSessionPoolBitMaps(), MiFreeSessionSpaceMap(), MiGetPdeAddress, MiGetPdeSessionIndex, MiGetPpeAddress, MiGetPteAddress, MiReleaseSystemPtes(), MiReturnCommitment(), MiSessionCount, MiSessionDeletePde(), MiSessionIdBitmap, MiSessionIdMutex, MiSessionUnloadAllImages(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE, MM_DBG_SESSION_INITIAL_PAGE_FREE, MM_DBG_SESSION_PAGETABLE_FREE, MM_DBG_SESSION_WS_PAGE_FREE, MM_SNAP_SESS_MEMORY_COUNTERS, MM_TRACK_COMMIT, MMPTE, MmResidentAvailablePages, MmSessionBase, MmSessionSpace, _MM_SESSION_SPACE::NonPagablePages, NULL, _MM_SESSION_SPACE::PageTables, _MM_SESSION_SPACE::ProcessOutSwapCount, PsGetCurrentProcess, _MMPFN::PteFrame, _MM_SESSION_SPACE::ReferenceCount, RtlClearBits(), SESSION_GLOBAL, _MM_SESSION_SPACE::SessionId, _MM_SESSION_SPACE::SessionPageDirectoryIndex, SystemPteSpace, TRUE, _MMPTE::u, _MMSUPPORT::u, _MM_SESSION_SPACE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_EXPANSION, UNLOCK_EXPANSION_AND_THEN_WAIT, UNLOCK_PFN, UNLOCK_SESSION, _MM_SESSION_SPACE::Vm, _EPROCESS::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Win32KDriverObject, _MMSUPPORT::WorkingSetExpansionLinks, WrVirtualMemory, _MM_SESSION_SPACE::WsListEntry, _MM_SESSION_SPACE::WsLock, and ZeroKernelPte.

Referenced by MiSessionRemoveProcess(), MmSessionCreate(), and MmSessionDelete().

01550 : 01551 01552 Decrement this process' reference count to the session, unmapping access 01553 to the session for the current process. If this is the last process 01554 reference to this session, then the entire session will be destroyed upon 01555 return. This includes unloading drivers, unmapping pools, freeing 01556 page tables, etc. 01557 01558 Arguments: 01559 01560 None. 01561 01562 Return Value: 01563 01564 TRUE if the session was deleted, FALSE if only this process' access to 01565 the session was deleted. 01566 01567 Environment: 01568 01569 Kernel mode, no mutexes held, APCs disabled. 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 // Don't delete any non-smss session space mappings here. Let them 01620 // live on through process death. This handles the case where 01621 // MmDispatchWin32Callout picks csrss - csrss has exited as it's not 01622 // the last process (smss is). smss is simultaneously detaching from 01623 // the session and since it is the last process, it's waiting on 01624 // the AttachCount below. The dispatch callout ends up in csrss but 01625 // has no way to synchronize against csrss exiting through this path 01626 // as the object reference count doesn't stop it. So leave the 01627 // session space mappings alive so the callout can execute through 01628 // the remains of csrss. 01629 // 01630 // Note that when smss detaches, the address space must get cleared 01631 // here so that subsequent session creations by smss will succeed. 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 // Flush the session space TB entries. 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 // Mark it as being deleted. 01661 // 01662 01663 MmSessionSpace->u.Flags.BeingDeleted = 1; 01664 01665 // 01666 // This is the final dereference. We could be any process 01667 // including SMSS when a session space load fails. Note also that 01668 // processes can terminate in any order as well. 01669 // 01670 01671 UNLOCK_SESSION (OldIrql); 01672 01673 SessionGlobal = SESSION_GLOBAL (MmSessionSpace); 01674 01675 LOCK_EXPANSION (OldIrql); 01676 01677 // 01678 // Wait for any cross-session process attaches to detach. Refuse 01679 // subsequent attempts to cross-session attach so the address invalidation 01680 // code doesn't surprise an ongoing or subsequent attachee. 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 // Initialize an event and put the event address 01713 // in the VmSupport. When the trimming is complete, 01714 // this event will be set. 01715 // 01716 01717 KeInitializeEvent(&Event, NotificationEvent, FALSE); 01718 01719 MmSessionSpace->Vm.WorkingSetExpansionLinks.Blink = (PLIST_ENTRY)&Event; 01720 01721 // 01722 // Release the mutex and wait for the event. 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 // Remove this session from the session list and the working 01741 // set list. 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 // If an unload function has been registered for WIN32K.SYS, 01771 // call it now before we force an unload on any modules. WIN32K.SYS 01772 // is responsible for calling any other loaded modules that have 01773 // unload routines to be run. Another option is to have the other 01774 // session drivers register a DLL initialize/uninitialize pair on load. 01775 // 01776 01777 if (MmSessionSpace->Win32KDriverObject.DriverUnload ) { 01778 MmSessionSpace->Win32KDriverObject.DriverUnload (&MmSessionSpace->Win32KDriverObject); 01779 } 01780 01781 // 01782 // Now that all modules have had their unload routine(s) 01783 // called, check for pool leaks before unloading the images. 01784 // 01785 01786 MiCheckSessionPoolAllocations (); 01787 01788 ASSERT (MmSessionSpace->ReferenceCount == 1); 01789 01790 MM_SNAP_SESS_MEMORY_COUNTERS(1); 01791 01792 // 01793 // Destroy the view mapping structures. 01794 // 01795 01796 MiFreeSessionSpaceMap (); 01797 01798 MM_SNAP_SESS_MEMORY_COUNTERS(2); 01799 01800 // 01801 // Walk down the list of modules we have loaded dereferencing them. 01802 // 01803 // This allows us to force an unload of any kernel images loaded by 01804 // the session so we do not have any virtual space and paging 01805 // file leaks. 01806 // 01807 01808 MiSessionUnloadAllImages (); 01809 01810 MM_SNAP_SESS_MEMORY_COUNTERS(3); 01811 01812 // 01813 // Destroy the session space bitmap structure 01814 // 01815 01816 MiFreeSessionPoolBitMaps (); 01817 01818 MM_SNAP_SESS_MEMORY_COUNTERS(4); 01819 01820 // 01821 // Reference the session space structure using its global 01822 // kernel PTE based address. This is to avoid deleting it out 01823 // from underneath ourselves. 01824 // 01825 01826 GlobalPteEntrySave = MmSessionSpace->GlobalPteEntry; 01827 01828 // 01829 // Sweep the individual regions in their proper order. 01830 // 01831 01832 #if DBG 01833 01834 // 01835 // Check the executable image region. All images 01836 // should have been unloaded by the image handler. 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 // Check the view region. All views should have been cleaned up already. 01849 // 01850 01851 MiCheckSessionVirtualSpace ((PVOID)MI_SESSION_VIEW_START, 01852 MI_SESSION_VIEW_SIZE); 01853 #endif 01854 01855 // 01856 // Save the page tables in the session space structure since 01857 // we are going to tear it down. 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 // Check everything possible before the remaining virtual address space 01875 // is torn down. In this way if anything is amiss, the data can be 01876 // more easily examined. 01877 // 01878 01879 Pfn1 = MI_PFN_ELEMENT (MmSessionSpace->SessionPageDirectoryIndex); 01880 01881 // 01882 // This should be greater than 1 because working set page tables are 01883 // using this as their parent as well. 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 // Account for the session data structure data page. For NT64, the page 01917 // directory page is also accounted for here. 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 // Account for any needed session space page tables. 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 // Note that whenever win32k or drivers loaded by it leak pool, the 01952 // ASSERT below will be triggered. 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 // Sweep the working set entries. 01963 // No more accesses to the working set or its lock are allowed. 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 // Delete the page. 01980 // 01981 01982 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 01983 01984 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01985 01986 // 01987 // Each page should still be locked in the session working set. 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 // Now delete the session space structure itself. 02013 // No more accesses to MmSessionSpace after this. 02014 // 02015 02016 PointerPte = MiGetPteAddress (MmSessionSpace); 02017 02018 // 02019 // Delete the page. 02020 // 02021 02022 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02023 02024 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02025 02026 // 02027 // Make sure this page is still locked. 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 // Flush the session space TB entries. 02061 // 02062 02063 MI_FLUSH_SESSION_TB (OldIrql); 02064 02065 // 02066 // Free the self-map PTE. 02067 // 02068 02069 MiReleaseSystemPtes (GlobalPteEntrySave, 1, SystemPteSpace); 02070 02071 // 02072 // Delete page table pages. Note that the page table page mapping the 02073 // session space data structure is done last so that we can apply 02074 // various ASSERTs in the DeletePde routine. 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 // The self map entry must be done last. 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 // Delete the session page directory page. 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 // The session space has been deleted and all TB flushing is complete. 02138 // 02139 02140 return TRUE; 02141 }

VOID MiDetachSession VOID   ) 
 

Definition at line 1253 of file session.c.

References ASSERT, KeDetachSessionSpace(), MI_FLUSH_SESSION_TB, MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MiGetPdeAddress, MiGetPpeAddress, MiHydra, MmIsAddressValid(), MmSessionBase, MmSessionSpace, PsGetCurrentProcess, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiEmptyAllWorkingSetsWorker(), and MmWorkingSetManager().

01259 : 01260 01261 Detaches from the specified session space. 01262 01263 Arguments: 01264 01265 None. 01266 01267 Return Value: 01268 01269 None. 01270 01271 Environment: 01272 01273 Kernel mode. No locks held. Current process must not have a session 01274 space to return to - ie: this should be the system process. 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 }

VOID MiInitializeSessionIds VOID   ) 
 

Referenced by MmInitSystem().

VOID MiSessionAddProcess PEPROCESS  NewProcess  ) 
 

Definition at line 178 of file session.c.

References _MMSUPPORT::AllowWorkingSetAdjustment, ASSERT, FALSE, KeAddSessionSpace(), _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_EXPANSION, LOCK_SESSION, MmIsAddressValid(), MmSessionSpace, MmWorkingSetExpansionHead, _EPROCESS::Pcb, _MM_SESSION_SPACE::ProcessList, PsGetCurrentProcess, _MM_SESSION_SPACE::ReferenceCount, SESSION_GLOBAL, _EPROCESS::SessionProcessLinks, TRUE, _MMSUPPORT::u, _MM_SESSION_SPACE::u, UNLOCK_EXPANSION, UNLOCK_SESSION, _EPROCESS::Vm, _MM_SESSION_SPACE::Vm, and _MMSUPPORT::WorkingSetExpansionLinks.

Referenced by MmCreateProcessAddressSpace().

00184 : 00185 00186 Add the new process to the current session space. 00187 00188 Arguments: 00189 00190 NewProcess - Supplies a pointer to the process being created. 00191 00192 Return Value: 00193 00194 None. 00195 00196 Environment: 00197 00198 Kernel mode, APCs disabled. 00199 00200 --*/ 00201 00202 { 00203 KIRQL OldIrql; 00204 PMM_SESSION_SPACE SessionGlobal; 00205 00206 // 00207 // If the calling process has no session, then the new process won't get 00208 // one either. 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 // Link the process entry into the session space and WSL structures. 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 }

NTSTATUS MiSessionCommitImagePages IN PVOID  VirtualAddress,
IN SIZE_T  NumberOfBytes
 

Definition at line 2144 of file session.c.

References ASSERT, _MM_SESSION_SPACE::CommittedPages, DbgPrint, FALSE, LOCK_PFN, LOCK_SESSION_SPACE_WS, MI_GET_PAGE_COLOR_FROM_SESSION, MI_NONPAGABLE_MEMORY_AVAILABLE, MI_PFN_ELEMENT, MI_WRITE_VALID_PTE, MiChargeCommitment(), MiEnsureAvailablePageOrWait(), MiGetPteAddress, MiInitializePfn(), MiRemoveAnyPage(), MiRemoveZeroPageIfAny, MiReturnCommitment(), MiSessionCommitPageTables(), MiZeroPhysicalPage(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_RETURN_SESSION_IMAGE_FAILURE1, MM_DBG_COMMIT_SESSION_IMAGE_PAGES, MM_DBG_SESSION_DRIVER_PAGES_LOCKED, MM_DBG_SESSIONS, MM_SESSION_FAILURE_NO_COMMIT, MM_SESSION_FAILURE_NO_RESIDENT, MM_TRACK_COMMIT, MmIsAddressValid(), MmResidentAvailablePages, MmSessionSpace, _MM_SESSION_SPACE::NonPagablePages, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SHIFT, PAGE_SIZE, Status, SYSLOAD_LOCK_OWNED_BY_ME, _MMPTE::u, _MMPFN::u1, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, ValidKernelPteLocal, and ZeroKernelPte.

Referenced by MiLoadImageSection().

02151 : 02152 02153 This routine commits virtual memory within the current session space with 02154 backing pages. The virtual addresses within session space are 02155 allocated with a separate facility in the image management facility. 02156 This is because images must be at a unique system wide virtual address. 02157 02158 Arguments: 02159 02160 VirtualAddress - Supplies the first virtual address to commit. 02161 02162 NumberOfBytes - Supplies the number of bytes to commit. 02163 02164 Return Value: 02165 02166 STATUS_SUCCESS if all went well, STATUS_NO_MEMORY if the current process 02167 has no session. 02168 02169 Environment: 02170 02171 Kernel mode, MmSystemLoadLock held. 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 // Calculate pages needed. 02207 // 02208 02209 AllocationStart = (ULONG_PTR)VirtualAddress; 02210 02211 // 02212 // Lock the session space working set. 02213 // 02214 02215 LOCK_SESSION_SPACE_WS(WsIrql); 02216 02217 // 02218 // Make sure we have page tables for the PTE 02219 // entries we must fill in the session space structure. 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 // go into loop allocating them and placing them into the page 02239 // tables. 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 // Check to make sure the physical pages are available. 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 }

NTSTATUS MiSessionCommitPageTables IN PVOID  StartVa,
IN PVOID  EndVa
 

Definition at line 2318 of file session.c.

References ASSERT, CHAR, _MM_SESSION_SPACE::CommittedPages, FALSE, _MMWSL::FirstDynamic, Index, LOCK_PFN, MI_GET_PAGE_COLOR_FROM_SESSION, MI_GET_PAGE_FRAME_FROM_PTE, MI_NONPAGABLE_MEMORY_AVAILABLE, MI_PFN_ELEMENT, MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MI_WRITE_VALID_PTE, MiAddValidPageToWorkingSet(), MiChargeCommitment(), MiEnsureAvailablePageOrWait(), MiGetPdeAddress, MiGetPdeSessionIndex, MiGetVirtualAddressMappedByPte, MiInitializePfnForOtherProcess(), MiLocateWsle(), MiRemoveAnyPage(), MiRemoveZeroPageIfAny, MiReturnCommitment(), MiSwapWslEntries(), MiZeroPhysicalPage(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_RETURN_SESSION_PAGETABLE_PAGES, MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES, MM_DBG_SESSION_PAGETABLE_ALLOC, MM_SESSION_FAILURE_NO_COMMIT, MM_SESSION_FAILURE_NO_RESIDENT, MM_SESSION_SPACE_WS_LOCK_ASSERT, MM_TRACK_COMMIT, MmIsAddressValid(), MmResidentAvailablePages, MmSessionBase, MmSessionSpace, _MM_SESSION_SPACE::NonPagablePages, NULL, _MM_SESSION_SPACE::PageTables, PsGetCurrentThread, _MM_SESSION_SPACE::SessionPageDirectoryIndex, TRUE, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, UNLOCK_PFN, ValidKernelPdeLocal, _MM_SESSION_SPACE::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Wsle, and ZeroKernelPte.

Referenced by MiSessionCommitImagePages(), and MiShareSessionImage().

02325 : 02326 02327 Fill in page tables covering the specified virtual address range. 02328 02329 Arguments: 02330 02331 StartVa - Supplies a starting virtual address. 02332 02333 EndVa - Supplies an ending virtual address. 02334 02335 Return Value: 02336 02337 STATUS_SUCCESS on success, STATUS_NO_MEMORY on failure. 02338 02339 Environment: 02340 02341 Kernel mode. Session space working set mutex held. 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 // Allocate the page table pages, loading them 02369 // into the current process's page directory. 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 // Check to make sure the physical pages are available. 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 // Swap this entry with the one at first dynamic. 02511 // 02512 02513 MiSwapWslEntries (Entry, SwapEntry, &MmSessionSpace->Vm); 02514 } 02515 02516 WorkingSetList->FirstDynamic += 1; 02517 } 02518 else { 02519 SwapEntry = Entry; 02520 } 02521 02522 // 02523 // Indicate that the page is locked. 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 }

NTSTATUS MiSessionCreateInternal OUT PULONG  SessionId  ) 
 

Definition at line 394 of file session.c.

References ASSERT, _MM_SESSION_SPACE::Color, _MM_SESSION_SPACE::CommittedPages, DbgPrint, FALSE, _MM_SESSION_SPACE::GlobalPteEntry, _MM_SESSION_SPACE::GlobalVirtualAddress, _MM_SESSION_SPACE::ImageList, KeEnableSessionSharing(), KeInitializeSpinLock(), LOCK_PFN, MI_FLUSH_SINGLE_SESSION_TB, MI_GET_PAGE_COLOR_FROM_VA, MI_NONPAGABLE_MEMORY_AVAILABLE, MI_PFN_ELEMENT, MI_SESSION_COMMIT_CHARGE, MI_SESSION_POOL, MI_SESSION_SPACE_WORKING_SET_MINIMUM, MI_SET_PFN_DELETED, MI_WRITE_VALID_PTE, MiChargeCommitment(), MiDecrementReferenceCount(), MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiEnsureAvailablePageOrWait(), MiFreeSessionPoolBitMaps(), MiFreeSessionSpaceMap(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializePfn(), MiInitializePfnForOtherProcess(), MiInitializeSessionPool(), MiInitializeSystemSpaceMap(), MiReleaseSystemPtes(), MiRemoveAnyPage(), MiRemoveZeroPageIfAny, MiReserveSystemPtes(), MiReturnCommitment(), MiSessionIdBitmap, MiSessionIdMutex, MiZeroPhysicalPage(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE1, MM_DBG_COMMIT_SESSION_CREATE, MM_DBG_SESSION_INITIAL_PAGE_ALLOC, MM_DBG_SESSION_INITIAL_PAGE_FREE_FAIL1, MM_DBG_SESSION_INITIAL_PAGETABLE_ALLOC, MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_FAIL1, MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE, MM_DBG_SESSIONS, MM_DEMAND_ZERO_WRITE_PTE, MM_SESSION_FAILURE_NO_COMMIT, MM_SESSION_FAILURE_NO_IDS, MM_SESSION_FAILURE_NO_RESIDENT, MM_SESSION_FAILURE_NO_SYSPTES, MM_SESSION_FAILURE_RACE_DETECTED, MM_TRACK_COMMIT, MmIsAddressValid(), MmResidentAvailablePages, MmSessionBase, MmSessionSpace, _MM_SESSION_SPACE::NonPagablePages, NT_SUCCESS, NTSTATUS(), NULL, _MMPFN::OriginalPte, _MM_SESSION_SPACE::PageTables, _MM_SESSION_SPACE::ProcessList, _MMPFN::PteFrame, _MM_SESSION_SPACE::ReferenceCount, RtlClearBits(), RtlFindClearBitsAndSet(), _MM_SESSION_SPACE::Session, SESSION_GLOBAL, _MM_SESSION_SPACE::SessionId, _MM_SESSION_SPACE::SessionPageDirectoryIndex, _MM_SESSION_SPACE::SpinLock, StandbyPageList, Status, SystemPteSpace, TRUE, _MM_SESSION_SPACE::u, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, ValidKernelPdeLocal, ValidKernelPteLocal, _MM_SESSION_SPACE::WsListEntry, and ZeroKernelPte.

Referenced by MmSessionCreate().

00400 : 00401 00402 This routine creates the data structure that describes and maintains 00403 the session space. It resides at the beginning of the session space. 00404 Carefully construct the first page mapping to bootstrap the fault 00405 handler which relies on the session space data structure being 00406 present and valid. 00407 00408 In 32-bit NT, this initial mapping for the portion of session space 00409 mapped by the first PDE will automatically be inherited by all child 00410 processes when the system copies the system portion of the page 00411 directory for new address spaces. Additional entries are faulted 00412 in by the session space fault handler, which references this structure. 00413 For 64-bit NT, everything is automatically inherited. 00414 00415 This routine commits virtual memory within the current session space with 00416 backing pages. The virtual addresses within session space are 00417 allocated with a separate facility in the image management facility. 00418 This is because images must be at a unique system wide virtual address. 00419 00420 Arguments: 00421 00422 SessionId - Supplies a pointer to place the new session ID into. 00423 00424 Return Value: 00425 00426 STATUS_SUCCESS if all went well, various failure status codes 00427 if the session was not created. 00428 00429 Environment: 00430 00431 Kernel mode, no mutexes held. 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 // Check to make sure the physical pages are available. 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 // Initialize the page directory page. 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 // The global bit is masked off since we need to make sure the TB entry 00539 // is flushed when we switch to a process in a different session space. 00540 // 00541 00542 TempPte.u.Long = ValidKernelPdeLocal.u.Long; 00543 TempPte.u.Hard.PageFrameNumber = PageDirectoryPage; 00544 00545 PointerPpe = MiGetPpeAddress ((PVOID)MmSessionSpace); 00546 00547 // 00548 // Another thread may have gotten here before us, check for that now. 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 // Initialize the page table page. 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 // The global bit is masked off since we need to make sure the TB entry 00616 // is flushed when we switch to a process in a different session space. 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 // Another thread may have gotten here before us, check for that now. 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 // This page frame references itself instead of the current (SMSS.EXE) 00669 // page directory as its PteFrame. This allows the current process to 00670 // appear more normal (at least on 32-bit NT). It just means we have 00671 // to treat this page specially during teardown. 00672 // 00673 00674 MiInitializePfnForOtherProcess (PageTablePage, PointerPde, PageTablePage); 00675 00676 // 00677 // This page is never paged, ensure that its WsIndex stays clear so the 00678 // release of the page is handled correctly. 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 // The global bit is masked off since we need to make sure the TB entry 00701 // is flushed when we switch to a process in a different session space. 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 // Initialize the new session space data structure. 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 // Track the page table page and the data page. 00739 // 00740 00741 SessionSpace->NonPagablePages = ResidentPages; 00742 SessionSpace->CommittedPages = ResidentPages; 00743 00744 #if defined (_WIN64) 00745 00746 // 00747 // Initialize the session data page directory entry so trimmers can attach. 00748 // 00749 00750 PointerPpe = MiGetPpeAddress ((PVOID)MmSessionSpace); 00751 SessionSpace->PageDirectory = *PointerPpe; 00752 00753 #else 00754 00755 // 00756 // Load the session data page table entry so that other processes 00757 // can fault in the mapping. 00758 // 00759 00760 SessionSpace->PageTables[PointerPde - MiGetPdeAddress (MmSessionBase)] = *PointerPde; 00761 00762 #endif 00763 00764 // 00765 // Reserve a global system PTE and map the data page into it. 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 // This list entry is only referenced while within the 00793 // session space and has session space (not global) addresses. 00794 // 00795 00796 InitializeListHead (&SessionSpace->ImageList); 00797 00798 // 00799 // Initialize the session space pool. 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 // Initialize the view mapping support - note this must happen after 00815 // initializing session pool. 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 // Use the global virtual address rather than the session space virtual 00829 // address to set up fields that need to be globally accessible. 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 // Note that this call will acquire the session space lock, so the 00868 // data page better be mapped. 00869 // 00870 00871 MiFreeSessionSpaceMap (); 00872 00873 // 00874 // Free the initial page table page that was allocated for the 00875 // paged pool range (if it has been allocated at this point). 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 // Free the session data structure page. 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 // Free the page table page. 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 // Free the page directory page. 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 // Now that the PDE has been zeroed, another thread in this process 00949 // could attempt a session create so be careful not to count on any 00950 // anything in this particular session. 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 }

VOID MiSessionDeletePde IN PMMPTE  Pde,
IN BOOLEAN  WorkingSetInitialized,
IN PMMPTE  SelfMapPde
 

Definition at line 1408 of file session.c.

References ASSERT, DbgPrint, FALSE, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_KERNEL_NOACCESS_PTE, MmHighestPhysicalPage, PTE_PER_PAGE, _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, and ZeroKernelPte.

Referenced by MiDereferenceSession().

01416 : 01417 01418 Used to delete a page directory entry from a session space. 01419 01420 Arguments: 01421 01422 Pde - Supplies the page directory entry to delete. 01423 01424 WorkingSetInitialized - Supplies TRUE if the working set has been 01425 initialized. 01426 01427 SelfMapPde - Supplies the page directory entry that contains the self map 01428 session page. 01429 01430 01431 Return Value: 01432 01433 None. 01434 01435 Environment: 01436 01437 Kernel mode. PFN lock held. 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 // Verify the containing page table is still the page 01479 // table page mapping the session data structure. 01480 // 01481 01482 if (SelfMapPage == FALSE) { 01483 01484 // 01485 // Note these ASSERTs will fail if win32k leaks pool. 01486 // 01487 01488 ASSERT (Pfn1->u2.ShareCount == 1); 01489 #if !defined (_WIN64) 01490 01491 // 01492 // 32-bit NT points the additional page tables at the master. 01493 // 64-bit NT doesn't need to use this trick as there is always 01494 // an additional hierarchy level. 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 // Make sure the page table page is zeroed. It should always be zero 01508 // unless win32k leaks pool or random bits get set. 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 }

VOID MiSessionInSwapProcess IN PEPROCESS  Process  ) 
 

Definition at line 2737 of file session.c.

References ASSERT, DbgPrint, _MM_SESSION_SPACE::GlobalVirtualAddress, LOCK_EXPANSION, MI_GET_DIRECTORY_FRAME_FROM_PROCESS, MI_GET_PAGE_FRAME_FROM_PTE, MiGetPdeOffset, MiGetPpeOffset, MiGetPteAddress, MiGetPteOffset, MiHydra, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_DBG_SESSIONS, MmSessionSpace, _MM_SESSION_SPACE::ProcessList, _MM_SESSION_SPACE::ProcessOutSwapCount, _MM_SESSION_SPACE::ReferenceCount, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _MM_SESSION_SPACE::Vm, and _MMSUPPORT::WorkingSetSize.

Referenced by MmInSwapProcess().

02743 : 02744 02745 This routine in swaps the specified process. 02746 02747 Arguments: 02748 02749 Process - Supplies a pointer to the process that is to be swapped 02750 into memory. 02751 02752 Return Value: 02753 02754 None. 02755 02756 Environment: 02757 02758 Kernel mode. This routine must not enter a wait state for memory resources 02759 or the system will deadlock. 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 // smss doesn't count when we catch it before it has detached from the 02784 // session it is currently creating. 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 // smss doesn't count when we swap it before it has detached from the 02795 // session it is currently creating. 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 } }

VOID MiSessionOutSwapProcess IN PEPROCESS  Process  ) 
 

Definition at line 2551 of file session.c.

References ASSERT, DbgPrint, _MM_SESSION_SPACE::GlobalVirtualAddress, KeQuerySystemTime(), _MM_SESSION_SPACE::LastProcessSwappedOutTime, LOCK_EXPANSION, MI_GET_DIRECTORY_FRAME_FROM_PROCESS, MI_GET_PAGE_FRAME_FROM_PTE, MiGetPdeOffset, MiGetPpeOffset, MiGetPteAddress, MiGetPteOffset, MiHydra, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_DBG_SESSIONS, MmSessionSpace, _MM_SESSION_SPACE::ProcessList, _MM_SESSION_SPACE::ProcessOutSwapCount, _MM_SESSION_SPACE::ReferenceCount, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _MM_SESSION_SPACE::Vm, and _MMSUPPORT::WorkingSetSize.

Referenced by MmOutSwapProcess().

02557 : 02558 02559 This routine notifies the containing session that the specified process is 02560 being outswapped. When all the processes within a session have been 02561 outswapped, the containing session undergoes a heavy trim. 02562 02563 Arguments: 02564 02565 Process - Supplies a pointer to the process that is swapped out of memory. 02566 02567 Return Value: 02568 02569 None. 02570 02571 Environment: 02572 02573 Kernel mode. This routine must not enter a wait state for memory resources 02574 or the system will deadlock. 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 // smss doesn't count when we swap it before it has detached from the 02599 // session it is currently creating. 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 }

VOID MiSessionRemoveProcess VOID   ) 
 

Referenced by MmCleanProcessAddressSpace().

NTSTATUS MmSessionCreate OUT PULONG  SessionId  ) 
 

Definition at line 974 of file session.c.

References ASSERT, FALSE, KeEnterCriticalRegion, KeLeaveCriticalRegion, LOCK_EXPANSION, MI_SESSION_SPACE_END, MiDereferenceSession(), MiGetPdeAddress, MiGetPpeAddress, MiHydra, MiSessionCount, MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmIsAddressValid(), MmSessionBase, MmSessionSpace, NT_SUCCESS, NTSTATUS(), PsGetCurrentProcess, Status, _MM_SESSION_SPACE::u, _MMPTE::u, _MMSUPPORT::u, UNLOCK_EXPANSION, _EPROCESS::Vm, and ZeroKernelPte.

Referenced by NtSetSystemInformation().

00980 : 00981 00982 Called from NtSetSystemInformation() to create a session space 00983 in the calling process with the specified SessionId. An error is returned 00984 if the calling process already has a session Space. 00985 00986 Arguments: 00987 00988 SessionId - Supplies a pointer to place the resulting session id in. 00989 00990 Return Value: 00991 00992 Various NTSTATUS error codes. 00993 00994 Environment: 00995 00996 Kernel mode, no mutexes held. 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 // A simple check to see if the calling process already has a session space. 01017 // No need to go through all this if it does. Creation races are caught 01018 // below and recovered from regardless. 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 // Only the session manager can create a session. 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 // Add the session space to the working set list. 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 }

NTSTATUS MmSessionDelete ULONG  SessionId  ) 
 

Definition at line 1093 of file session.c.

References ASSERT, DbgPrint, FALSE, KeEnterCriticalRegion, KeLeaveCriticalRegion, MiDereferenceSession(), MiHydra, MmIsAddressValid(), MmSessionSpace, PsGetCurrentProcess, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, and _EPROCESS::Vm.

Referenced by NtSetSystemInformation().

01099 : 01100 01101 Called from NtSetSystemInformation() to detach from an existing 01102 session space in the calling process. An error is returned 01103 if the calling process has no session Space. 01104 01105 Arguments: 01106 01107 SessionId - Supplies the session id to delete. 01108 01109 Return Value: 01110 01111 STATUS_SUCCESS on success, STATUS_UNABLE_TO_FREE_VM on failure. 01112 01113 This process will not be able to access session space anymore upon 01114 a successful return. If this is the last process in the session then 01115 the entire session is torn down. 01116 01117 Environment: 01118 01119 Kernel mode, no mutexes held. 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 // See if the calling process has a session space - this must be 01134 // checked since we can be called via a system service. 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 // Only the session manager can delete a session. This is because 01150 // it affects the virtual mappings for all threads within the process 01151 // when this address space is deleted. This is different from normal 01152 // VAD clearing because win32k and other drivers rely on this space. 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 }

VOID MmSessionLeader IN PEPROCESS  Process  ) 
 

Definition at line 109 of file session.c.

00115 : 00116 00117 Mark the argument process as having the ability to create or delete session 00118 spaces. This is only granted to the session manager process. 00119 00120 Arguments: 00121 00122 Process - Supplies a pointer to the privileged process. 00123 00124 Return Value: 00125 00126 None. 00127 00128 Environment: 00129 00130 Kernel mode. 00131 00132 --*/ 00133 00134 { 00135 Process->Vm.u.Flags.SessionLeader = 1; 00136 }

VOID MmSessionSetUnloadAddress IN PDRIVER_OBJECT  pWin32KDevice  ) 
 

Definition at line 140 of file session.c.

References ASSERT, MiHydra, MmIsAddressValid(), MmSessionSpace, PsGetCurrentProcess, TRUE, and _MM_SESSION_SPACE::Win32KDriverObject.

Referenced by NtSetSystemInformation().

00146 : 00147 00148 Copy the win32k.sys driver object to the session structure for use during 00149 unload. 00150 00151 Arguments: 00152 00153 NewProcess - Supplies a pointer to the win32k driver object. 00154 00155 Return Value: 00156 00157 None. 00158 00159 Environment: 00160 00161 Kernel mode. 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 }


Variable Documentation

ULONG MiSessionCount
 

Definition at line 24 of file session.c.

Referenced by MiDereferenceSession(), and MmSessionCreate().

PRTL_BITMAP MiSessionIdBitmap
 

Definition at line 30 of file session.c.

Referenced by MiDereferenceSession(), MiInitializeSessionIds(), and MiSessionCreateInternal().

FAST_MUTEX MiSessionIdMutex
 

Definition at line 28 of file session.c.

Referenced by MiDereferenceSession(), MiInitializeSessionIds(), and MiSessionCreateInternal().


Generated on Sat May 15 19:45:37 2004 for test by doxygen 1.3.7