Author: jgardou Date: Tue Nov 15 23:50:04 2011 New Revision: 54392
URL: http://svn.reactos.org/svn/reactos?rev=54392&view=rev Log: [NTOSKRNL/MM] - Some more cleanup. - Work with page rounded down addresses in SectionView page faults. - You should not create a virtual mapping on a non page-aligned address range : ASSERT about that. - Flush Tlb each time we change it - Fix logic I broke in MmCreateVirtualMapping (thanks to Thomas Faber)
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c trunk/reactos/ntoskrnl/mm/section.c
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 15 23:50:04 2011 @@ -284,37 +284,34 @@ PageDir = (PULONG)MiAddressToPde(Address); if (0 == InterlockedCompareExchangePte(PageDir, 0, 0)) { - if (Address >= MmSystemRangeStart) - { - if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0)) - { - if (Create == FALSE) - { - return NULL; - } - MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY); - if (Process) MI_SET_PROCESS2(Process->ImageFileName); - if (!Process) MI_SET_PROCESS2("Kernel Legacy"); - Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn); - if (!NT_SUCCESS(Status) || Pfn == 0) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE; - if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0)) - { - MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn); - } - InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]); - RtlZeroMemory(MiPteToAddress(PageDir), PAGE_SIZE); - return (PULONG)MiAddressToPte(Address); + if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0)) + { + if (Create == FALSE) + { + return NULL; + } + MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Legacy"); + Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn); + if (!NT_SUCCESS(Status) || Pfn == 0) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE; + if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0)) + { + MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn); } InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]); - } - else - { - - } + /* 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); } @@ -700,15 +697,8 @@ } Pte = *Pt; InterlockedExchangePte(Pt, SwapEntry << 1); - if (Pte != 0) - { - MiFlushTlb(Pt, Address); - } - else - { - MmUnmapPageTable(Pt); - } - + MiFlushTlb(Pt, Address); + return(STATUS_SUCCESS); }
@@ -729,6 +719,8 @@ ULONG Pte; DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n", Process, Address, flProtect, Pages, *Pages, PageCount); + + ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0);
if (Process == NULL) { @@ -772,6 +764,8 @@ }
Addr = Address; + /* MmGetPageTableForProcess should be called on the first run, so + * let this trigger it */ oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1; for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE)) { @@ -785,6 +779,7 @@ PdeOffset = ADDR_TO_PDE_OFFSET(Addr); if (oldPdeOffset != PdeOffset) { + if(Pt) MmUnmapPageTable(Pt); Pt = MmGetPageTableForProcess(Process, Addr, TRUE); if (Pt == NULL) { @@ -805,8 +800,18 @@ KeBugCheck(MEMORY_MANAGEMENT); } InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes); - MiFlushTlb(Pt, Addr); - } + /* 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)) + { + KeInvalidateTlbEntry(Addr); + } + } + + ASSERT(Addr > Address); + MmUnmapPageTable(Pt);
return(STATUS_SUCCESS); }
Modified: trunk/reactos/ntoskrnl/mm/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Tue Nov 15 23:50:04 2011 @@ -1314,7 +1314,6 @@ ULONG Offset; PFN_NUMBER Page; NTSTATUS Status; - PVOID PAddress; PROS_SECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; ULONG_PTR Entry; @@ -1343,8 +1342,8 @@ return(STATUS_UNSUCCESSFUL); }
- PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); - Offset = (ULONG)((ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + Address = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + MemoryArea->Data.SectionData.ViewOffset);
Segment = MemoryArea->Data.SectionData.Segment; @@ -1432,7 +1431,7 @@ if (!MmIsPagePresent(Process, Address)) { Entry = MmGetPageEntrySectionSegment(Segment, Offset); - HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress); + HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)Address);
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry) { @@ -1461,7 +1460,7 @@ DPRINT1("Unable to create virtual mapping\n"); KeBugCheck(MEMORY_MANAGEMENT); } - MmInsertRmap(Page, Process, (PVOID)PAddress); + MmInsertRmap(Page, Process, Address); } MmUnlockSectionSegment(Segment); PageOp->Status = STATUS_SUCCESS; @@ -1470,7 +1469,7 @@ return(STATUS_SUCCESS); }
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress); + HasSwapEntry = MmIsPageSwapEntry(Process, Address); if (HasSwapEntry) { /* @@ -1488,7 +1487,7 @@ }
MmUnlockSectionSegment(Segment); - MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry); + MmDeletePageFileMapping(Process, Address, &SwapEntry);
MmUnlockAddressSpace(AddressSpace); MI_SET_USAGE(MI_USAGE_SECTION); @@ -1527,8 +1526,7 @@ /* * Add the page to the process's working set */ - MmInsertRmap(Page, Process, (PVOID)PAddress); - + MmInsertRmap(Page, Process, Address); /* * Finish the operation */ @@ -1600,7 +1598,7 @@ KeBugCheck(MEMORY_MANAGEMENT); return(Status); } - MmInsertRmap(Page, Process, (PVOID)PAddress); + MmInsertRmap(Page, Process, Address);
/* * Cleanup and release locks @@ -1699,7 +1697,7 @@ DPRINT1("Unable to create virtual mapping\n"); KeBugCheck(MEMORY_MANAGEMENT); } - MmInsertRmap(Page, Process, (PVOID)PAddress); + MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS; MmspCompleteAndReleasePageOp(PageOp); @@ -1772,7 +1770,7 @@ DPRINT1("Unable to create virtual mapping\n"); KeBugCheck(MEMORY_MANAGEMENT); } - MmInsertRmap(Page, Process, (PVOID)PAddress); + MmInsertRmap(Page, Process, Address); PageOp->Status = STATUS_SUCCESS; MmspCompleteAndReleasePageOp(PageOp); DPRINT("Address 0x%.8X\n", Address); @@ -1800,7 +1798,7 @@ DPRINT1("Unable to create virtual mapping\n"); KeBugCheck(MEMORY_MANAGEMENT); } - MmInsertRmap(Page, Process, (PVOID)PAddress); + MmInsertRmap(Page, Process, Address); PageOp->Status = STATUS_SUCCESS; MmspCompleteAndReleasePageOp(PageOp); DPRINT("Address 0x%.8X\n", Address); @@ -1819,7 +1817,6 @@ PFN_NUMBER OldPage; PFN_NUMBER NewPage; NTSTATUS Status; - PVOID PAddress; ULONG Offset; PMM_PAGEOP PageOp; PMM_REGION Region; @@ -1840,8 +1837,8 @@ /* * Find the offset of the page */ - PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); - Offset = (ULONG)((ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + Address = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + MemoryArea->Data.SectionData.ViewOffset);
Segment = MemoryArea->Data.SectionData.Segment; @@ -1874,7 +1871,7 @@ PFN_FROM_SSE(Entry) != OldPage) { /* This is a private page. We must only change the page protection. */ - MmSetPageProtect(Process, PAddress, Region->Protect); + MmSetPageProtect(Process, Address, Region->Protect); return(STATUS_SUCCESS); }
@@ -1938,7 +1935,7 @@ /* * Copy the old page */ - MiCopyFromUserPage(NewPage, PAddress); + MiCopyFromUserPage(NewPage, Address);
MmLockAddressSpace(AddressSpace); /* @@ -1969,8 +1966,8 @@ /* * Unshare the old page. */ - MmDeleteRmap(OldPage, Process, PAddress); - MmInsertRmap(NewPage, Process, PAddress); + MmDeleteRmap(OldPage, Process, Address); + MmInsertRmap(NewPage, Process, Address); MmLockSectionSegment(Segment); MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE); MmUnlockSectionSegment(Segment);