[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)

svn path=/trunk/; revision=54392
This commit is contained in:
Jérôme Gardou 2011-11-15 23:50:04 +00:00
parent a9801fa996
commit 50632f02d1
2 changed files with 58 additions and 56 deletions

View file

@ -284,37 +284,34 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
PageDir = (PULONG)MiAddressToPde(Address);
if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
{
if (Address >= MmSystemRangeStart)
if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
{
if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
if (Create == FALSE)
{
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);
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]);
/* Flush it before accessing it */
KeInvalidateTlbEntry(MiPteToAddress(PageDir));
RtlZeroMemory(MiPteToAddress(PageDir), PAGE_SIZE);
return (PULONG)MiAddressToPte(Address);
}
else
{
}
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
/* Flush it before accessing it */
KeInvalidateTlbEntry(MiPteToAddress(PageDir));
}
return (PULONG)MiAddressToPte(Address);
}
@ -700,15 +697,8 @@ MmCreatePageFileMapping(PEPROCESS Process,
}
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 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
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 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
}
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 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
if (oldPdeOffset != PdeOffset)
{
if(Pt) MmUnmapPageTable(Pt);
Pt = MmGetPageTableForProcess(Process, Addr, TRUE);
if (Pt == NULL)
{
@ -805,9 +800,19 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
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);
}

View file

@ -1314,7 +1314,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
ULONG Offset;
PFN_NUMBER Page;
NTSTATUS Status;
PVOID PAddress;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
ULONG_PTR Entry;
@ -1343,8 +1342,8 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
return(STATUS_SUCCESS);
}
HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
if (HasSwapEntry)
{
/*
@ -1488,7 +1487,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
}
MmUnlockSectionSegment(Segment);
MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry);
MmDeletePageFileMapping(Process, Address, &SwapEntry);
MmUnlockAddressSpace(AddressSpace);
MI_SET_USAGE(MI_USAGE_SECTION);
@ -1527,8 +1526,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/*
* 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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
KeBugCheck(MEMORY_MANAGEMENT);
return(Status);
}
MmInsertRmap(Page, Process, (PVOID)PAddress);
MmInsertRmap(Page, Process, Address);
/*
* Cleanup and release locks
@ -1699,7 +1697,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
PFN_NUMBER OldPage;
PFN_NUMBER NewPage;
NTSTATUS Status;
PVOID PAddress;
ULONG Offset;
PMM_PAGEOP PageOp;
PMM_REGION Region;
@ -1840,8 +1837,8 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/*
* 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 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
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 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Copy the old page
*/
MiCopyFromUserPage(NewPage, PAddress);
MiCopyFromUserPage(NewPage, Address);
MmLockAddressSpace(AddressSpace);
/*
@ -1969,8 +1966,8 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/*
* 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);