mirror of
https://github.com/reactos/reactos.git
synced 2024-07-07 21:25:05 +00:00
[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). svn path=/trunk/; revision=56682
This commit is contained in:
parent
15425106b9
commit
2bbb9b2930
1
reactos/ntoskrnl/cache/section/newmm.h
vendored
1
reactos/ntoskrnl/cache/section/newmm.h
vendored
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
/* TYPES *********************************************************************/
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
#define MM_WAIT_ENTRY 0x7ffffc00
|
|
||||||
#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT))
|
#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT))
|
||||||
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
|
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
|
||||||
#define MM_IS_WAIT_PTE(E) \
|
#define MM_IS_WAIT_PTE(E) \
|
||||||
|
|
|
@ -179,6 +179,10 @@ typedef ULONG_PTR SWAPENTRY;
|
||||||
(PAGE_WRITECOPY | \
|
(PAGE_WRITECOPY | \
|
||||||
PAGE_EXECUTE_WRITECOPY)
|
PAGE_EXECUTE_WRITECOPY)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait entry for marking pages that are being serviced
|
||||||
|
//
|
||||||
|
#define MM_WAIT_ENTRY 0x7ffffc00
|
||||||
|
|
||||||
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
|
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
|
||||||
InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
|
InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
|
||||||
|
@ -1263,6 +1267,13 @@ MmIsPagePresent(
|
||||||
PVOID Address
|
PVOID Address
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
MmIsDisabledPage(
|
||||||
|
struct _EPROCESS* Process,
|
||||||
|
PVOID Address
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitGlobalKernelPageDirectory(VOID);
|
MmInitGlobalKernelPageDirectory(VOID);
|
||||||
|
|
|
@ -467,7 +467,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
|
||||||
*/
|
*/
|
||||||
Pte = InterlockedExchangePte(Pt, 0);
|
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)
|
if (WasValid)
|
||||||
{
|
{
|
||||||
/* Flush the TLB since we transitioned this PTE
|
/* Flush the TLB since we transitioned this PTE
|
||||||
|
@ -700,6 +702,14 @@ MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
||||||
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
|
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
MmIsDisabledPage(PEPROCESS Process, PVOID Address)
|
||||||
|
{
|
||||||
|
ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address);
|
||||||
|
return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
|
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
|
||||||
|
@ -738,12 +748,17 @@ MmCreatePageFileMapping(PEPROCESS Process,
|
||||||
if (Pt == NULL)
|
if (Pt == NULL)
|
||||||
{
|
{
|
||||||
/* Nobody should page out an address that hasn't even been mapped */
|
/* 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);
|
Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
|
||||||
if (Pte != 0)
|
if (Pte != 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
|
@ -975,7 +990,8 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
|
||||||
}
|
}
|
||||||
Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
|
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);
|
DPRINT1("Invalid Pte %lx\n", Pte);
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
|
|
|
@ -1223,6 +1223,11 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MmIsDisabledPage(Process, Address))
|
||||||
|
{
|
||||||
|
return(STATUS_ACCESS_VIOLATION);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for the virtual memory area being deleted.
|
* Check for the virtual memory area being deleted.
|
||||||
*/
|
*/
|
||||||
|
@ -1438,6 +1443,8 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
|
|
||||||
if (Entry == 0)
|
if (Entry == 0)
|
||||||
{
|
{
|
||||||
|
SWAPENTRY FakeSwapEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the entry is zero (and it can't change because we have
|
* If the entry is zero (and it can't change because we have
|
||||||
* locked the segment) then we need to load the page.
|
* locked the segment) then we need to load the page.
|
||||||
|
@ -1448,6 +1455,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
*/
|
*/
|
||||||
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
|
MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
|
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
|
||||||
|
@ -1496,6 +1504,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
|
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
|
|
||||||
|
MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
|
||||||
|
DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
|
||||||
|
Page, Process, PAddress, Attributes);
|
||||||
Status = MmCreateVirtualMapping(Process,
|
Status = MmCreateVirtualMapping(Process,
|
||||||
PAddress,
|
PAddress,
|
||||||
Attributes,
|
Attributes,
|
||||||
|
@ -1506,6 +1517,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
DPRINT1("Unable to create virtual mapping\n");
|
DPRINT1("Unable to create virtual mapping\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
ASSERT(MmIsPagePresent(Process, PAddress));
|
||||||
MmInsertRmap(Page, Process, Address);
|
MmInsertRmap(Page, Process, Address);
|
||||||
|
|
||||||
MiSetPageEvent(Process, Address);
|
MiSetPageEvent(Process, Address);
|
||||||
|
@ -2441,7 +2453,7 @@ MmAlterViewAttributes(PMMSUPPORT AddressSpace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MmIsPagePresent(Process, Address))
|
if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
|
||||||
{
|
{
|
||||||
MmSetPageProtect(Process, Address,
|
MmSetPageProtect(Process, Address,
|
||||||
Protect);
|
Protect);
|
||||||
|
|
Loading…
Reference in a new issue