extern PVOID MmPagedPoolBase;
extern ULONG MmPagedPoolSize;
+extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
+extern MEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptorOrg;
+extern ULONG MmHighestPhysicalPage;
+
struct _KTRAP_FRAME;
struct _EPROCESS;
struct _MM_RMAP_ENTRY;
typedef ULONG SWAPENTRY;
typedef ULONG PFN_TYPE, *PPFN_TYPE;
+#define MI_STATIC_MEMORY_AREAS (8)
+
#define MEMORY_AREA_INVALID (0)
#define MEMORY_AREA_SECTION_VIEW (1)
#define MEMORY_AREA_CONTINUOUS_MEMORY (2)
#define MEMORY_AREA_PAGED_POOL (12)
#define MEMORY_AREA_NO_ACCESS (13)
#define MEMORY_AREA_PEB_OR_TEB (14)
+#define MEMORY_AREA_STATIC (0x80000000)
#define MM_PHYSICAL_PAGE_MPW_PENDING (0x8)
#define MM_PAGEOP_PAGESYNCH (3)
#define MM_PAGEOP_ACCESSFAULT (4)
+/* Number of list heads to use */
+#define MI_FREE_POOL_LISTS 4
+
+#define MI_HYPERSPACE_PTES (256 - 1)
+#define MI_ZERO_PTES (32)
+#define MI_MAPPING_RANGE_START (ULONG)HYPER_SPACE
+#define MI_MAPPING_RANGE_END (MI_MAPPING_RANGE_START + \
+ MI_HYPERSPACE_PTES * PAGE_SIZE)
+#define MI_ZERO_PTE (PMMPTE)(MI_MAPPING_RANGE_END + \
+ PAGE_SIZE)
+
+/* Signature of free pool blocks */
+#define MM_FREE_POOL_TAG TAG('F', 'r', 'p', 'l')
+
#define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \
((x) / (4*1024*1024))
#define MC_USER (1)
#define MC_PPOOL (2)
#define MC_NPPOOL (3)
-#define MC_MAXIMUM (4)
+#define MC_SYSTEM (4)
+#define MC_MAXIMUM (5)
#define PAGED_POOL_MASK 1
#define MUST_SUCCEED_POOL_MASK 2
PAGE_NOACCESS | \
PAGE_NOCACHE)
+#define PAGE_FLAGS_VALID_FOR_SECTION \
+ (PAGE_READONLY | \
+ PAGE_READWRITE | \
+ PAGE_WRITECOPY | \
+ PAGE_EXECUTE | \
+ PAGE_EXECUTE_READ | \
+ PAGE_EXECUTE_READWRITE | \
+ PAGE_EXECUTE_WRITECOPY | \
+ PAGE_NOACCESS)
+
#define PAGE_IS_READABLE \
(PAGE_READONLY | \
PAGE_READWRITE | \
(PAGE_WRITECOPY | \
PAGE_EXECUTE_WRITECOPY)
+
+#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
+ InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
+
+#define InterlockedExchangePte(PointerPte, Value) \
+ InterlockedExchange((PLONG)(PointerPte), Value)
+
typedef struct
{
ULONG Entry[NR_SECTION_PAGE_ENTRIES];
} Data;
} MEMORY_AREA, *PMEMORY_AREA;
-typedef struct _MADDRESS_SPACE
-{
- PMEMORY_AREA MemoryAreaRoot;
- PVOID LowestAddress;
- struct _EPROCESS* Process;
- PUSHORT PageTableRefCountTable;
- ULONG PageTableRefCountTableSize;
-} MADDRESS_SPACE, *PMADDRESS_SPACE;
-
typedef struct
{
ULONG NrTotalPages;
ULONG NrSystemPages;
- ULONG NrReservedPages;
ULONG NrUserPages;
ULONG NrFreePages;
ULONG NrDirtyPages;
ULONG PagingRequestsInLastFifteenMinutes;
} MM_STATS;
+//
+// These two mappings are actually used by Windows itself, based on the ASSERTS
+//
+#define StartOfAllocation ReadInProgress
+#define EndOfAllocation WriteInProgress
+
+typedef struct _MMPFNENTRY
+{
+ USHORT Modified:1;
+ USHORT ReadInProgress:1; // StartOfAllocation
+ USHORT WriteInProgress:1; // EndOfAllocation
+ USHORT PrototypePte:1; // Zero
+ USHORT PageColor:4; // LockCount
+ USHORT PageLocation:3; // Consumer
+ USHORT RemovalRequested:1;
+ USHORT CacheAttribute:2; // Type
+ USHORT Rom:1;
+ USHORT ParityError:1;
+} MMPFNENTRY;
+
+typedef struct _MMPFN
+{
+ union
+ {
+ PFN_NUMBER Flink; // ListEntry.Flink
+ ULONG WsIndex;
+ PKEVENT Event;
+ NTSTATUS ReadStatus;
+ SINGLE_LIST_ENTRY NextStackPfn;
+ } u1;
+ PMMPTE PteAddress; // ListEntry.Blink
+ union
+ {
+ PFN_NUMBER Blink;
+ ULONG_PTR ShareCount; // MapCount
+ } u2;
+ union
+ {
+ struct
+ {
+ USHORT ReferenceCount; // ReferenceCount
+ MMPFNENTRY e1;
+ };
+ struct
+ {
+ USHORT ReferenceCount;
+ USHORT ShortFlags;
+ } e2;
+ } u3;
+ union
+ {
+ MMPTE OriginalPte;
+ LONG AweReferenceCount; // RmapListHead
+ };
+ union
+ {
+ ULONG_PTR EntireFrame; // SavedSwapEntry
+ struct
+ {
+ ULONG_PTR PteFrame:25;
+ ULONG_PTR InPageError:1;
+ ULONG_PTR VerifierAllocation:1;
+ ULONG_PTR AweAllocation:1;
+ ULONG_PTR Priority:3;
+ ULONG_PTR MustBeCached:1;
+ };
+ } u4;
+} MMPFN, *PMMPFN;
+
+extern PMMPFN MmPfnDatabase;
extern MM_STATS MmStats;
typedef struct _MM_PAGEOP
LIST_ENTRY RegionListEntry;
} MM_REGION, *PMM_REGION;
+/* Entry describing free pool memory */
+typedef struct _MMFREE_POOL_ENTRY
+{
+ LIST_ENTRY List;
+ PFN_NUMBER Size;
+ ULONG Signature;
+ struct _MMFREE_POOL_ENTRY *Owner;
+} MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY;
+
+/* Paged pool information */
+typedef struct _MM_PAGED_POOL_INFO
+{
+ PRTL_BITMAP PagedPoolAllocationMap;
+ PRTL_BITMAP EndOfPagedPoolBitmap;
+ PMMPTE FirstPteForPagedPool;
+ PMMPTE LastPteForPagedPool;
+ PMMPTE NextPdeForPagedPoolExpansion;
+ ULONG PagedPoolHint;
+ SIZE_T PagedPoolCommit;
+ SIZE_T AllocatedPagedPool;
+} MM_PAGED_POOL_INFO, *PMM_PAGED_POOL_INFO;
+
extern MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
typedef VOID
(*PMM_ALTER_REGION_FUNC)(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID BaseAddress,
ULONG Length,
ULONG OldType,
BOOLEAN Dirty
);
-/* aspace.c ******************************************************************/
-
-VOID
-NTAPI
-MmLockAddressSpace(PMADDRESS_SPACE AddressSpace);
-
-VOID
-NTAPI
-MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace);
-
-VOID
-NTAPI
-MmInitializeKernelAddressSpace(VOID);
-
-PMADDRESS_SPACE
-NTAPI
-MmGetCurrentAddressSpace(VOID);
-
-PMADDRESS_SPACE
-NTAPI
-MmGetKernelAddressSpace(VOID);
-
-NTSTATUS
-NTAPI
-MmInitializeAddressSpace(
- struct _EPROCESS* Process,
- PMADDRESS_SPACE AddressSpace);
-
-NTSTATUS
-NTAPI
-MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace);
-
/* marea.c *******************************************************************/
-NTSTATUS
-NTAPI
-MmInitMemoryAreas(VOID);
-
NTSTATUS
NTAPI
MmCreateMemoryArea(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
ULONG Type,
PVOID *BaseAddress,
ULONG_PTR Length,
PMEMORY_AREA
NTAPI
MmLocateMemoryAreaByAddress(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID Address
);
ULONG_PTR
NTAPI
MmFindGapAtAddress(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID Address
);
NTSTATUS
NTAPI
MmFreeMemoryArea(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_FREE_PAGE_FUNC FreePage,
PVOID FreePageContext
NTSTATUS
NTAPI
MmFreeMemoryAreaByPtr(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID BaseAddress,
PMM_FREE_PAGE_FUNC FreePage,
PVOID FreePageContext
VOID
NTAPI
-MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace);
+MmDumpMemoryAreas(PMMSUPPORT AddressSpace);
PMEMORY_AREA
NTAPI
MmLocateMemoryAreaByRegion(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID Address,
ULONG_PTR Length
);
PVOID
NTAPI
MmFindGap(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
ULONG_PTR Length,
ULONG_PTR Granularity,
BOOLEAN TopDown
NTAPI
MmReleaseMemoryAreaIfDecommitted(
struct _EPROCESS *Process,
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID BaseAddress
);
+VOID
+NTAPI
+MmMapMemoryArea(PVOID BaseAddress,
+ ULONG Length,
+ ULONG Consumer,
+ ULONG Protection);
+
/* npool.c *******************************************************************/
VOID
NTAPI
MiInitializeNonPagedPool(VOID);
+PVOID
+NTAPI
+MiAllocatePoolPages(
+ IN POOL_TYPE PoolType,
+ IN SIZE_T SizeInBytes
+);
+
+POOL_TYPE
+NTAPI
+MmDeterminePoolType(
+ IN PVOID VirtualAddress
+);
+
+ULONG
+NTAPI
+MiFreePoolPages(
+ IN PVOID StartingAddress
+);
+
PVOID
NTAPI
MmGetMdlPageAddress(
NTAPI
ExFreePagedPool(IN PVOID Block);
+BOOLEAN
+NTAPI
+ExpIsPoolTagDebuggable(ULONG Tag);
+
+PVOID
+NTAPI
+ExpAllocateDebugPool(
+ POOL_TYPE Type,
+ ULONG Size,
+ ULONG Tag,
+ PVOID Caller,
+ BOOLEAN EndOfPage
+);
+
+VOID
+NTAPI
+ExpFreeDebugPool(PVOID Block, BOOLEAN PagedPool);
+
VOID
NTAPI
MmInitializePagedPool(VOID);
VOID
NTAPI
MmInit1(
- ULONG_PTR FirstKernelPhysAddress,
- ULONG_PTR LastKernelPhysAddress,
- ULONG_PTR LastKernelAddress,
- PADDRESS_RANGE BIOSMemoryMap,
- ULONG AddressRangeCount,
- ULONG MaxMemInMeg
+ VOID
);
BOOLEAN
NTSTATUS
NTAPI
MmNotPresentFaultVirtualMemory(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
BOOLEAN Locked
NTSTATUS
NTAPI
MmPageOutVirtualMemory(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
struct _MM_PAGEOP* PageOp
PMEMORY_AREA MemoryArea,
PVOID Address,
PMEMORY_BASIC_INFORMATION Info,
- PULONG ResultLength
+ PSIZE_T ResultLength
);
VOID
NTSTATUS
NTAPI
MmProtectAnonMem(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID BaseAddress,
ULONG Length,
NTSTATUS
NTAPI
MmWritePageVirtualMemory(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MArea,
PVOID Address,
PMM_PAGEOP PageOp
/* freelist.c **********************************************************/
+#define ASSERT_PFN(x) ASSERT((x)->u3.e1.CacheAttribute != 0)
+
+FORCEINLINE
+PMMPFN
+MiGetPfnEntry(IN PFN_TYPE Pfn)
+{
+ PMMPFN Page;
+ extern RTL_BITMAP MiPfnBitMap;
+
+ /* Make sure the PFN number is valid */
+ if (Pfn > MmHighestPhysicalPage) return NULL;
+
+ /* Make sure this page actually has a PFN entry */
+ if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, Pfn))) return NULL;
+
+ /* Get the entry */
+ Page = &MmPfnDatabase[Pfn];
+
+ /* Make sure it's valid */
+ ASSERT_PFN(Page);
+
+ /* Return it */
+ return Page;
+};
+
+FORCEINLINE
+PFN_NUMBER
+MiGetPfnEntryIndex(IN PMMPFN Pfn1)
+{
+ //
+ // This will return the Page Frame Number (PFN) from the MMPFN
+ //
+ return Pfn1 - MmPfnDatabase;
+}
+
PFN_TYPE
NTAPI
MmGetLRUNextUserPage(PFN_TYPE PreviousPage);
VOID
NTAPI
-MmSetLRULastPage(PFN_TYPE Page);
+MmInsertLRULastUserPage(PFN_TYPE Page);
+
+VOID
+NTAPI
+MmRemoveLRUUserPage(PFN_TYPE Page);
VOID
NTAPI
NTAPI
MmGetLockCountPage(PFN_TYPE Page);
-PVOID
+static
+__inline
+KIRQL
+NTAPI
+MmAcquirePageListLock()
+{
+ return KeAcquireQueuedSpinLock(LockQueuePfnLock);
+}
+
+FORCEINLINE
+VOID
+NTAPI
+MmReleasePageListLock(KIRQL oldIrql)
+{
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+}
+
+VOID
NTAPI
MmInitializePageList(
- ULONG_PTR FirstPhysKernelAddress,
- ULONG_PTR LastPhysKernelAddress,
- ULONG MemorySizeInPages,
- ULONG_PTR LastKernelBase,
- PADDRESS_RANGE BIOSMemoryMap,
- ULONG AddressRangeCount
+ VOID
+);
+
+VOID
+NTAPI
+MmDumpPfnDatabase(
+ VOID
);
PFN_TYPE
ULONG NumberOfBytes,
PHYSICAL_ADDRESS LowestAcceptableAddress,
PHYSICAL_ADDRESS HighestAcceptableAddress,
- PHYSICAL_ADDRESS BoundaryAddressMultiple
+ PHYSICAL_ADDRESS BoundaryAddressMultiple,
+ BOOLEAN ZeroPages
);
NTSTATUS
PVOID Context
);
-/* i386/page.c *********************************************************/
+/* hypermap.c *****************************************************************/
+
+extern PEPROCESS HyperProcess;
+extern KIRQL HyperIrql;
PVOID
NTAPI
-MmCreateHyperspaceMapping(PFN_TYPE Page);
+MiMapPageInHyperSpace(IN PEPROCESS Process,
+ IN PFN_NUMBER Page,
+ IN PKIRQL OldIrql);
-PFN_TYPE
+VOID
NTAPI
-MmChangeHyperspaceMapping(
- PVOID Address,
- PFN_TYPE Page
-);
+MiUnmapPageInHyperSpace(IN PEPROCESS Process,
+ IN PVOID Address,
+ IN KIRQL OldIrql);
-PFN_TYPE
+PVOID
+NTAPI
+MiMapPagesToZeroInHyperSpace(IN PMMPFN *Pages,
+ IN PFN_NUMBER NumberOfPages);
+
+VOID
NTAPI
-MmDeleteHyperspaceMapping(PVOID Address);
+MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
+ IN PFN_NUMBER NumberOfPages);
+
+//
+// ReactOS Compatibility Layer
+//
+FORCEINLINE
+PVOID
+MmCreateHyperspaceMapping(IN PFN_NUMBER Page)
+{
+ HyperProcess = (PEPROCESS)KeGetCurrentThread()->ApcState.Process;
+ return MiMapPageInHyperSpace(HyperProcess, Page, &HyperIrql);
+}
+
+FORCEINLINE
+PVOID
+MiMapPageToZeroInHyperSpace(IN PFN_NUMBER Page)
+{
+ PMMPFN Pfn1 = MiGetPfnEntry(Page);
+ return MiMapPagesToZeroInHyperSpace(&Pfn1, 1);
+}
+
+#define MmDeleteHyperspaceMapping(x) MiUnmapPageInHyperSpace(HyperProcess, x, HyperIrql);
+
+/* i386/page.c *********************************************************/
NTSTATUS
NTAPI
NTAPI
MmReferencePageUnsafe(PFN_TYPE Page);
-BOOLEAN
-NTAPI
-MmIsAccessedAndResetAccessPage(
- struct _EPROCESS *Process,
- PVOID Address
-);
-
ULONG
NTAPI
MmGetReferenceCountPage(PFN_TYPE Page);
BOOLEAN
NTAPI
-MmIsUsablePage(PFN_TYPE Page);
-
-VOID
-NTAPI
-MmSetFlagsPage(
- PFN_TYPE Page,
- ULONG Flags);
-
-ULONG
-NTAPI
-MmGetFlagsPage(PFN_TYPE Page);
+MmIsPageInUse(PFN_TYPE Page);
VOID
NTAPI
MmCreateProcessAddressSpace(
IN ULONG MinWs,
IN PEPROCESS Dest,
- IN PLARGE_INTEGER DirectoryTableBase
+ IN PULONG_PTR DirectoryTableBase
);
NTSTATUS
NTAPI
MmInitializeHandBuiltProcess(
IN PEPROCESS Process,
- IN PLARGE_INTEGER DirectoryTableBase
+ IN PULONG_PTR DirectoryTableBase
);
NTSTATUS
NTAPI
MmAlterRegion(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PVOID BaseAddress,
PLIST_ENTRY RegionListHead,
PVOID StartAddress,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMEMORY_BASIC_INFORMATION Info,
- PULONG ResultLength
+ PSIZE_T ResultLength
);
NTSTATUS
NTAPI
MmProtectSectionView(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID BaseAddress,
ULONG Length,
NTSTATUS
NTAPI
MmWritePageSectionView(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MArea,
PVOID Address,
PMM_PAGEOP PageOp
NTSTATUS
NTAPI
MmNotPresentFaultSectionView(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
BOOLEAN Locked
NTSTATUS
NTAPI
MmPageOutSectionView(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
struct _MM_PAGEOP *PageOp
NTSTATUS
NTAPI
MmAccessFaultSectionView(
- PMADDRESS_SPACE AddressSpace,
+ PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
BOOLEAN Locked
IN PVOID Address,
IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
OUT PVOID VirtualMemoryInformation,
- IN ULONG Length,
- OUT PULONG ResultLength
+ IN SIZE_T Length,
+ OUT PSIZE_T ResultLength
);
/* sysldr.c ******************************************************************/
IN BOOLEAN PurgeSection
);
+NTSTATUS
+NTAPI
+MmCallDllInitialize(
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ IN PLIST_ENTRY ListHead
+);
+
+/* ReactOS Mm Hacks */
+VOID
+FASTCALL
+MiSyncForProcessAttach(
+ IN PKTHREAD NextThread,
+ IN PEPROCESS Process
+);
+
+VOID
+FASTCALL
+MiSyncForContextSwitch(
+ IN PKTHREAD Thread
+);
+
+extern PMMSUPPORT MmKernelAddressSpace;
+
FORCEINLINE
VOID
-NTAPI
-MiSyncThreadProcessViews(IN PVOID Process,
- IN PVOID Address,
- IN ULONG Size)
+MmLockAddressSpace(PMMSUPPORT AddressSpace)
+{
+ KeAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
+}
+
+FORCEINLINE
+VOID
+MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
+{
+ KeReleaseGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
+}
+
+FORCEINLINE
+PEPROCESS
+MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
+{
+ if (AddressSpace == MmKernelAddressSpace) return NULL;
+ return CONTAINING_RECORD(AddressSpace, EPROCESS, Vm);
+}
+
+FORCEINLINE
+PMMSUPPORT
+MmGetCurrentAddressSpace(VOID)
+{
+ return &((PEPROCESS)KeGetCurrentThread()->ApcState.Process)->Vm;
+}
+
+FORCEINLINE
+PMMSUPPORT
+MmGetKernelAddressSpace(VOID)
{
- MmUpdatePageDir((PEPROCESS)Process, Address, Size);
+ return MmKernelAddressSpace;
}
#endif