diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 2cb6cce9aa7..c1509c7f848 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1155,7 +1155,13 @@ MiUnmapPageInHyperSpace(IN PEPROCESS Process, PVOID NTAPI -MiMapPageToZeroInHyperSpace(IN PFN_NUMBER Page); +MiMapPagesToZeroInHyperSpace(IN PMMPFN *Pages, + IN PFN_NUMBER NumberOfPages); + +VOID +NTAPI +MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress, + IN PFN_NUMBER NumberOfPages); // // ReactOS Compatibility Layer @@ -1168,6 +1174,14 @@ MmCreateHyperspaceMapping(IN PFN_NUMBER Page) return MiMapPageInHyperSpace(HyperProcess, Page, &HyperIrql); } +PVOID +FORCEINLINE +MiMapPageToZeroInHyperSpace(IN PFN_NUMBER Page) +{ + PMMPFN Pfn1 = MiGetPfnEntry(Page); + return MiMapPagesToZeroInHyperSpace(&Pfn1, 1); +} + #define MmDeleteHyperspaceMapping(x) MiUnmapPageInHyperSpace(HyperProcess, x, HyperIrql); /* i386/page.c *********************************************************/ diff --git a/reactos/ntoskrnl/mm/ARM3/hypermap.c b/reactos/ntoskrnl/mm/ARM3/hypermap.c index 60d73fcf640..cb59ddec543 100644 --- a/reactos/ntoskrnl/mm/ARM3/hypermap.c +++ b/reactos/ntoskrnl/mm/ARM3/hypermap.c @@ -109,42 +109,101 @@ MiUnmapPageInHyperSpace(IN PEPROCESS Process, PVOID NTAPI -MiMapPageToZeroInHyperSpace(IN PFN_NUMBER Page) +MiMapPagesToZeroInHyperSpace(IN PMMPFN *Pages, + IN PFN_NUMBER NumberOfPages) { MMPTE TempPte; PMMPTE PointerPte; - PVOID Address; + PFN_NUMBER Offset, PageFrameIndex; + PMMPFN Page; // - // Never accept page 0 + // Sanity checks // - ASSERT(Page != 0); + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + ASSERT(NumberOfPages != 0); + ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1)); + + // + // Pick the first zeroing PTE + // + PointerPte = MiFirstReservedZeroingPte; // - // Build the PTE + // Now get the first free PTE // - TempPte = HyperTemplatePte; - TempPte.u.Hard.PageFrameNumber = Page; - + Offset = PFN_FROM_PTE(PointerPte); + if (NumberOfPages > Offset) + { + // + // Reset the PTEs + // + Offset = MI_ZERO_PTES - 1; + PointerPte->u.Hard.PageFrameNumber = Offset; + KeFlushProcessTb(); + } + // - // Get the Zero PTE and its address + // Prepare the next PTE // - PointerPte = MiAddressToPte(MI_ZERO_PTE); - Address = (PVOID)((ULONG_PTR)PointerPte << 10); - - // - // Invalidate the old address - // - __invlpg(Address); - + PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages; + // // Write the current PTE // - TempPte.u.Hard.PageFrameNumber = Page; - *PointerPte = TempPte; - + PointerPte += (Offset + 1); + TempPte = HyperTemplatePte; + TempPte.u.Hard.Global = FALSE; // Hyperspace is local! + do + { + // + // Get the first page entry and its PFN + // + Page = *Pages++; + PageFrameIndex = MiGetPfnEntryIndex(Page); + + // + // Write the PFN + // + TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + + // + // Set the correct PTE to write to, and set its new value + // + PointerPte--; + ASSERT(PointerPte->u.Hard.Valid == 0); + ASSERT(TempPte.u.Hard.Valid == 1); + *PointerPte = TempPte; + } while (--NumberOfPages); + // // Return the address // - return Address; + return MiPteToAddress(PointerPte); } + +VOID +NTAPI +MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress, + IN PFN_NUMBER NumberOfPages) +{ + PMMPTE PointerPte; + + // + // Sanity checks + // + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + ASSERT (NumberOfPages != 0); + ASSERT (NumberOfPages <= (MI_ZERO_PTES - 1)); + + // + // Get the first PTE for the mapped zero VA + // + PointerPte = MiAddressToPte(VirtualAddress); + + // + // Blow away the mapped zero PTEs + // + RtlZeroMemory(PointerPte, NumberOfPages * sizeof(MMPTE)); +} + diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 600a3079e41..45f0307c577 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -938,21 +938,6 @@ MmAllocPagesSpecifyRange(ULONG Consumer, return NumberOfPagesFound; } -static -NTSTATUS -MiZeroPageInternal(PFN_TYPE Page) -{ - PVOID TempAddress; - - TempAddress = MiMapPageToZeroInHyperSpace(Page); - if (TempAddress == NULL) - { - return(STATUS_NO_MEMORY); - } - memset(TempAddress, 0, PAGE_SIZE); - return(STATUS_SUCCESS); -} - NTSTATUS NTAPI MmZeroPageThreadMain(PVOID Ignored) @@ -1000,7 +985,7 @@ MmZeroPageThreadMain(PVOID Ignored) PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); Pfn = PageDescriptor - MmPfnDatabase; - Status = MiZeroPageInternal(Pfn); + Status = MiZeroPage(Pfn); oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); if (PageDescriptor->MapCount != 0) diff --git a/reactos/ntoskrnl/mm/kmap.c b/reactos/ntoskrnl/mm/kmap.c index 0a442803f5e..e671088b26c 100644 --- a/reactos/ntoskrnl/mm/kmap.c +++ b/reactos/ntoskrnl/mm/kmap.c @@ -21,18 +21,18 @@ NTSTATUS NTAPI MiZeroPage(PFN_TYPE Page) { - PEPROCESS Process; KIRQL Irql; PVOID TempAddress; - Process = PsGetCurrentProcess(); - TempAddress = MiMapPageInHyperSpace(Process, Page, &Irql); + Irql = KeRaiseIrqlToDpcLevel(); + TempAddress = MiMapPageToZeroInHyperSpace(Page); if (TempAddress == NULL) { return(STATUS_NO_MEMORY); } memset(TempAddress, 0, PAGE_SIZE); - MiUnmapPageInHyperSpace(Process, TempAddress, Irql); + MiUnmapPagesInZeroSpace(TempAddress, 1); + KeLowerIrql(Irql); return(STATUS_SUCCESS); }