mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[NTOSKRNL/MM]
- create a page op when changing page protection attribute - properly handle PAGE_NOACCESS protection change in NtProtectVirtualMemory - Round down the address we're given when creating a page op, so we're sure there is o,ly one page op for running for one page - Add a small hack Now ReatOS boots with DPH enabled on low memory conditions svn path=/trunk/; revision=54477
This commit is contained in:
parent
397bb2c11e
commit
27d513df6e
3 changed files with 80 additions and 26 deletions
|
@ -420,16 +420,42 @@ MmModifyAttributes(PMMSUPPORT AddressSpace,
|
|||
OldProtect != NewProtect)
|
||||
{
|
||||
ULONG i;
|
||||
PMM_PAGEOP PageOp;
|
||||
PMEMORY_AREA MArea;
|
||||
char* addr = (char*)BaseAddress;
|
||||
|
||||
for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++)
|
||||
{
|
||||
if (MmIsPagePresent(Process,
|
||||
(char*)BaseAddress + (i*PAGE_SIZE)))
|
||||
MArea = MmLocateMemoryAreaByAddress(AddressSpace, addr);
|
||||
do
|
||||
{
|
||||
MmSetPageProtect(Process,
|
||||
(char*)BaseAddress + (i*PAGE_SIZE),
|
||||
NewProtect);
|
||||
PageOp = MmGetPageOp(MArea, Process->UniqueProcessId, addr,
|
||||
NULL, 0, MM_PAGEOP_CHANGEPROTECT, TRUE);
|
||||
} while(PageOp == NULL);
|
||||
|
||||
/* Should we enable/disable virtual mapping? */
|
||||
if((NewProtect & PAGE_NOACCESS) &&
|
||||
!(OldProtect & PAGE_NOACCESS) &&
|
||||
(MmIsPagePresent(Process, addr)))
|
||||
{
|
||||
/* Set other flags if any */
|
||||
if(NewProtect != PAGE_NOACCESS)
|
||||
MmSetPageProtect(Process, addr, NewProtect & ~PAGE_NOACCESS);
|
||||
MmDisableVirtualMapping(Process, addr, NULL, NULL);
|
||||
}
|
||||
else if((OldProtect & PAGE_NOACCESS) && !(NewProtect & PAGE_NOACCESS))
|
||||
{
|
||||
MmEnableVirtualMapping(Process, addr);
|
||||
}
|
||||
|
||||
/* Set new protection flags */
|
||||
if(MmIsPagePresent(Process, addr))
|
||||
{
|
||||
MmSetPageProtect(Process, addr, NewProtect);
|
||||
}
|
||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||
MmReleasePageOp(PageOp);
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,21 +304,17 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
|||
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
||||
}
|
||||
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
||||
/* Flush it before accessing it */
|
||||
KeInvalidateTlbEntry(MiPteToAddress(PageDir));
|
||||
RtlZeroMemory(MiPteToAddress(PageDir), PAGE_SIZE);
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
}
|
||||
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
||||
/* Flush it before accessing it */
|
||||
KeInvalidateTlbEntry(MiPteToAddress(PageDir));
|
||||
}
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
}
|
||||
|
||||
BOOLEAN MmUnmapPageTable(PULONG Pt)
|
||||
{
|
||||
if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
|
||||
if (!IS_HYPERSPACE(Pt))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -383,7 +379,10 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPF
|
|||
Pte = *Pt;
|
||||
} while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_PRESENT, Pte));
|
||||
|
||||
MiFlushTlb(Pt, Address);
|
||||
if(Pte & PA_PRESENT)
|
||||
MiFlushTlb(Pt, Address);
|
||||
else
|
||||
MmUnmapPageTable(Pt);
|
||||
|
||||
WasValid = (PAGE_MASK(Pte) != 0);
|
||||
if (!WasValid)
|
||||
|
@ -457,16 +456,17 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
|
|||
*/
|
||||
Pte = InterlockedExchangePte(Pt, 0);
|
||||
|
||||
MiFlushTlb(Pt, Address);
|
||||
|
||||
WasValid = (PAGE_MASK(Pte) != 0);
|
||||
if (WasValid)
|
||||
{
|
||||
Pfn = PTE_TO_PFN(Pte);
|
||||
MiFlushTlb(Pt, Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pfn = 0;
|
||||
MmUnmapPageTable(Pt);
|
||||
}
|
||||
|
||||
if (FreePage && WasValid)
|
||||
|
@ -523,7 +523,13 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
|
|||
*/
|
||||
Pte = InterlockedExchangePte(Pt, 0);
|
||||
|
||||
MiFlushTlb(Pt, Address);
|
||||
//MiFlushTlb(Pt, Address);
|
||||
MmUnmapPageTable(Pt);
|
||||
|
||||
if(!(Pte & 0x800))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return some information to the caller
|
||||
|
@ -632,9 +638,15 @@ MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
|
|||
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
||||
if (Pt == NULL)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
//HACK to get DPH working, waiting for MM rewrite :-/
|
||||
//KeBugCheck(MEMORY_MANAGEMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do not mark a 0 page as present */
|
||||
if(0 == InterlockedCompareExchangePte(Pt, 0, 0))
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Pte = *Pt;
|
||||
|
@ -695,9 +707,13 @@ MmCreatePageFileMapping(PEPROCESS Process,
|
|||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
Pte = *Pt;
|
||||
InterlockedExchangePte(Pt, SwapEntry << 1);
|
||||
MiFlushTlb(Pt, Address);
|
||||
Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
|
||||
if(PAGE_MASK(Pte))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
//MiFlushTlb(Pt, Address);
|
||||
MmUnmapPageTable(Pt);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -792,19 +808,19 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
|
|||
}
|
||||
oldPdeOffset = PdeOffset;
|
||||
|
||||
Pte = *Pt;
|
||||
Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes);;
|
||||
/* There should not be anything valid here */
|
||||
if ((Pte & PA_PRESENT) || (Pte & 0x800))
|
||||
if (PAGE_MASK(Pte) != 0)
|
||||
{
|
||||
PMMPFN Pfn1 = MiGetPfnEntry(PTE_TO_PFN(Pte));
|
||||
(void)Pfn1;
|
||||
DPRINT1("Bad PTE %lx\n", Pte);
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
|
||||
/* flush if currently mapped, just continue editing if hyperspace
|
||||
* NOTE : Do not call MiFlushTlb, as it will unmap the page table,
|
||||
* and we might need it afterwards */
|
||||
if (Address >= MmSystemRangeStart ||
|
||||
(Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024))
|
||||
* NOTE : This check is similar to what is done in MiFlushTlb, but we
|
||||
* don't use it because it would unmap the page table */
|
||||
if (Addr >= MmSystemRangeStart || (!IS_HYPERSPACE(Pt)))
|
||||
{
|
||||
KeInvalidateTlbEntry(Addr);
|
||||
}
|
||||
|
@ -889,6 +905,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
|
|||
{
|
||||
ULONG Attributes = 0;
|
||||
PULONG Pt;
|
||||
ULONG Pte;
|
||||
|
||||
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
|
||||
Process, Address, flProtect);
|
||||
|
@ -910,8 +927,17 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
|
|||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
|
||||
MiFlushTlb(Pt, Address);
|
||||
Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
|
||||
|
||||
if(!PAGE_MASK(Pte))
|
||||
{
|
||||
DPRINT1("Invalid Pte %lx\n", Pte);
|
||||
__debugbreak();
|
||||
}
|
||||
if((Pte & Attributes) != Attributes)
|
||||
MiFlushTlb(Pt, Address);
|
||||
else
|
||||
MmUnmapPageTable(Pt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -145,6 +145,8 @@ MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address,
|
|||
ULONG_PTR Hash;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PageOp;
|
||||
|
||||
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||
|
||||
/*
|
||||
* Calcuate the hash value for pageop structure
|
||||
|
|
Loading…
Reference in a new issue