reactos/ntoskrnl/mm/ARM3/hypermap.c

207 lines
4.5 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: ntoskrnl/mm/ARM3/hypermap.c
* PURPOSE: ARM Memory Manager Hyperspace Mapping Functionality
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#define MODULE_INVOLVED_IN_ARM3
#include <mm/ARM3/miarm.h>
/* GLOBALS ********************************************************************/
PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte;
PMMPTE MiFirstReservedZeroingPte;
MMPTE HyperTemplatePte;
PEPROCESS HyperProcess;
KIRQL HyperIrql;
/* PRIVATE FUNCTIONS **********************************************************/
PVOID
NTAPI
MiMapPageInHyperSpace(IN PEPROCESS Process,
IN PFN_NUMBER Page,
IN PKIRQL OldIrql)
{
MMPTE TempPte;
PMMPTE PointerPte;
PFN_NUMBER Offset;
//
// Never accept page 0 or non-physical pages
//
ASSERT(Page != 0);
ASSERT(MiGetPfnEntry(Page) != NULL);
//
// Build the PTE
//
TempPte = ValidKernelPteLocal;
TempPte.u.Hard.PageFrameNumber = Page;
//
// Pick the first hyperspace PTE
//
PointerPte = MmFirstReservedMappingPte;
//
// Acquire the hyperlock
//
ASSERT(Process == PsGetCurrentProcess());
KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql);
//
// Now get the first free PTE
//
Offset = PFN_FROM_PTE(PointerPte);
if (!Offset)
{
//
// Reset the PTEs
//
Offset = MI_HYPERSPACE_PTES;
KeFlushProcessTb();
}
//
// Prepare the next PTE
//
PointerPte->u.Hard.PageFrameNumber = Offset - 1;
//
// Write the current PTE
//
PointerPte += Offset;
MI_WRITE_VALID_PTE(PointerPte, TempPte);
//
// Return the address
//
return MiPteToAddress(PointerPte);
}
VOID
NTAPI
MiUnmapPageInHyperSpace(IN PEPROCESS Process,
IN PVOID Address,
IN KIRQL OldIrql)
{
ASSERT(Process == PsGetCurrentProcess());
//
// Blow away the mapping
//
MiAddressToPte(Address)->u.Long = 0;
//
// Release the hyperlock
//
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql);
}
PVOID
NTAPI
MiMapPagesInZeroSpace(IN PMMPFN Pfn1,
IN PFN_NUMBER NumberOfPages)
{
MMPTE TempPte;
PMMPTE PointerPte;
PFN_NUMBER Offset, PageFrameIndex;
//
// Sanity checks
//
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(NumberOfPages != 0);
ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1));
//
// Pick the first zeroing PTE
//
PointerPte = MiFirstReservedZeroingPte;
//
// Now get the first free PTE
//
Offset = PFN_FROM_PTE(PointerPte);
if (NumberOfPages > Offset)
{
//
// Reset the PTEs
//
Offset = MI_ZERO_PTES - 1;
PointerPte->u.Hard.PageFrameNumber = Offset;
KeFlushProcessTb();
}
//
// Prepare the next PTE
//
PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages;
/* Choose the correct PTE to use, and which template */
PointerPte += (Offset + 1);
TempPte = ValidKernelPte;
/* Make sure the list isn't empty and loop it */
ASSERT(Pfn1 != (PVOID)LIST_HEAD);
while (Pfn1 != (PVOID)LIST_HEAD)
{
/* Get the page index for this PFN */
PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
//
// Write the PFN
//
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
//
// Set the correct PTE to write to, and set its new value
//
PointerPte--;
MI_WRITE_VALID_PTE(PointerPte, TempPte);
/* Move to the next PFN */
Pfn1 = (PMMPFN)Pfn1->u1.Flink;
}
//
// Return the address
//
return MiPteToAddress(PointerPte);
}
VOID
NTAPI
MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
IN PFN_NUMBER NumberOfPages)
{
PMMPTE PointerPte;
//
// Sanity checks
//
ASSERT(KeGetCurrentIrql() == PASSIVE_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));
}