Author: arty
Date: Fri Jun 1 09:01:41 2012
New Revision: 56682
URL:
http://svn.reactos.org/svn/reactos?rev=56682&view=rev
Log:
[NTOSKRNL]
- Allow placement of a wait entry in virgin address space prior to mapping a page.
- Add a wait entry in the address space when paging in section view.
- Correct a problem that previously prevented us from evicting or querying pages that
had been protected into PAGE_NOACCESS protection by adding a query for disabled
mappings and handling disabled mappings in a few places (this may be controversial).
Modified:
trunk/reactos/ntoskrnl/cache/section/newmm.h
trunk/reactos/ntoskrnl/include/internal/mm.h
trunk/reactos/ntoskrnl/mm/i386/page.c
trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/new…
==============================================================================
--- trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] Fri Jun 1 09:01:41 2012
@@ -4,7 +4,6 @@
/* TYPES *********************************************************************/
-#define MM_WAIT_ENTRY 0x7ffffc00
#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT))
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
#define MM_IS_WAIT_PTE(E) \
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Fri Jun 1 09:01:41 2012
@@ -179,6 +179,10 @@
(PAGE_WRITECOPY | \
PAGE_EXECUTE_WRITECOPY)
+//
+// Wait entry for marking pages that are being serviced
+//
+#define MM_WAIT_ENTRY 0x7ffffc00
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
@@ -1263,6 +1267,13 @@
PVOID Address
);
+BOOLEAN
+NTAPI
+MmIsDisabledPage(
+ struct _EPROCESS* Process,
+ PVOID Address
+);
+
VOID
NTAPI
MmInitGlobalKernelPageDirectory(VOID);
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Fri Jun 1 09:01:41 2012
@@ -467,7 +467,9 @@
*/
Pte = InterlockedExchangePte(Pt, 0);
- WasValid = (Pte & PA_PRESENT);
+ /* We count a mapping as valid if it's a present page, or it's a nonzero pfn
with
+ * the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. */
+ WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte
& 0x800));
if (WasValid)
{
/* Flush the TLB since we transitioned this PTE
@@ -702,6 +704,14 @@
BOOLEAN
NTAPI
+MmIsDisabledPage(PEPROCESS Process, PVOID Address)
+{
+ ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address);
+ return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry
>> PAGE_SHIFT);
+}
+
+BOOLEAN
+NTAPI
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
ULONG Entry;
@@ -738,12 +748,17 @@
if (Pt == NULL)
{
/* Nobody should page out an address that hasn't even been mapped */
- KeBugCheck(MEMORY_MANAGEMENT);
+ /* But we might place a wait entry first, requiring the page table */
+ if (SwapEntry != MM_WAIT_ENTRY)
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ Pt = MmGetPageTableForProcess(Process, Address, TRUE);
}
Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
if (Pte != 0)
{
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process,
(ULONG_PTR)Address, 0);
}
if (Address < MmSystemRangeStart)
@@ -975,7 +990,8 @@
}
Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt &
(PA_ACCESSED|PA_DIRTY)));
- if (!(Pte & PA_PRESENT))
+ // We should be able to bring a page back from PAGE_NOACCESS
+ if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT))
{
DPRINT1("Invalid Pte %lx\n", Pte);
KeBugCheck(MEMORY_MANAGEMENT);
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Fri Jun 1 09:01:41 2012
@@ -1223,6 +1223,11 @@
return(STATUS_SUCCESS);
}
+ if (MmIsDisabledPage(Process, Address))
+ {
+ return(STATUS_ACCESS_VIOLATION);
+ }
+
/*
* Check for the virtual memory area being deleted.
*/
@@ -1438,6 +1443,8 @@
if (Entry == 0)
{
+ SWAPENTRY FakeSwapEntry;
+
/*
* If the entry is zero (and it can't change because we have
* locked the segment) then we need to load the page.
@@ -1448,6 +1455,7 @@
*/
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
+ MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
MmUnlockAddressSpace(AddressSpace);
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
@@ -1496,6 +1504,9 @@
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
+ MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
+ DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes
%x\n",
+ Page, Process, PAddress, Attributes);
Status = MmCreateVirtualMapping(Process,
PAddress,
Attributes,
@@ -1506,6 +1517,7 @@
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
+ ASSERT(MmIsPagePresent(Process, PAddress));
MmInsertRmap(Page, Process, Address);
MiSetPageEvent(Process, Address);
@@ -2441,7 +2453,7 @@
}
}
- if (MmIsPagePresent(Process, Address))
+ if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
{
MmSetPageProtect(Process, Address,
Protect);