Author: jgardou Date: Tue Nov 22 22:01:06 2011 New Revision: 54477
URL: http://svn.reactos.org/svn/reactos?rev=54477&view=rev Log: [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
Modified: trunk/reactos/ntoskrnl/mm/anonmem.c trunk/reactos/ntoskrnl/mm/i386/page.c trunk/reactos/ntoskrnl/mm/pageop.c
Modified: trunk/reactos/ntoskrnl/mm/anonmem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/anonmem.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] Tue Nov 22 22:01:06 2011 @@ -420,16 +420,42 @@ 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; } } }
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Tue Nov 22 22:01:06 2011 @@ -304,21 +304,17 @@ 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 @@ 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 @@ */ 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 @@ */ 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,8 +638,14 @@ 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 { @@ -695,9 +707,13 @@ { 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 @@ } 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 @@ { ULONG Attributes = 0; PULONG Pt; + ULONG Pte;
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n", Process, Address, flProtect); @@ -910,8 +927,17 @@ { 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); }
/*
Modified: trunk/reactos/ntoskrnl/mm/pageop.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/pageop.c?rev=54... ============================================================================== --- trunk/reactos/ntoskrnl/mm/pageop.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/pageop.c [iso-8859-1] Tue Nov 22 22:01:06 2011 @@ -145,6 +145,8 @@ ULONG_PTR Hash; KIRQL oldIrql; PMM_PAGEOP PageOp; + + Address = (PVOID)PAGE_ROUND_DOWN(Address);
/* * Calcuate the hash value for pageop structure