2008-02-13 05:16:14 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
2008-06-29 02:58:05 +00:00
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
2008-02-13 05:16:14 +00:00
|
|
|
* FILE: ntoskrnl/mm/arm/stubs.c
|
|
|
|
* PURPOSE: ARM Memory Manager
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2008-03-11 04:42:54 +00:00
|
|
|
|
2008-02-13 05:16:14 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
ULONG MmGlobalKernelPageDirectory[1024];
|
|
|
|
MMPTE MiArmTemplatePte, MiArmTemplatePde;
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2008-02-13 05:16:14 +00:00
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
BOOLEAN
|
2008-02-13 05:16:14 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MiUnmapPageTable(IN PMMPTE PointerPde)
|
2008-02-13 05:16:14 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Check if this address belongs to the kernel
|
2008-02-13 05:16:14 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
if (((ULONG_PTR)PointerPde > PDE_BASE) ||
|
|
|
|
((ULONG_PTR)PointerPde < (PDE_BASE + 1024*1024)))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Nothing to do
|
|
|
|
//
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// FIXME-USER: Shouldn't get here yet
|
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return FALSE;
|
2008-02-13 05:16:14 +00:00
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
VOID
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MiFlushTlb(IN PMMPTE PointerPte,
|
|
|
|
IN PVOID Address)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Make sure the PTE is valid, and unmap the pagetable if user-mode
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
if (((PointerPte) && (MiUnmapPageTable(PointerPte))) ||
|
|
|
|
(Address >= MmSystemRangeStart))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Invalidate this page
|
|
|
|
//
|
|
|
|
KeArmInvalidateTlbEntry(Address);
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
PMMPTE
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MiGetPageTableForProcess(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN BOOLEAN Create)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-07-27 19:52:41 +00:00
|
|
|
ULONG PdeOffset;
|
|
|
|
PMMPTE PointerPde;
|
|
|
|
MMPTE Pte;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFN_NUMBER Pfn;
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Check if this is a user-mode, non-kernel or non-current address
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
if ((Address < MmSystemRangeStart) &&
|
|
|
|
(Process) &&
|
|
|
|
(Process != PsGetCurrentProcess()))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME-USER: No user-mode memory support
|
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Get the PDE
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
PointerPde = MiGetPdeAddress(Address);
|
|
|
|
if (PointerPde->u.Hard.L1.Fault.Type == FaultPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Invalid PDE, is this a kernel address?
|
|
|
|
//
|
|
|
|
if (Address >= MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Does it exist in the kernel page directory?
|
|
|
|
//
|
|
|
|
PdeOffset = MiGetPdeOffset(Address);
|
|
|
|
if (MmGlobalKernelPageDirectory[PdeOffset] == 0)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// It doesn't. Is this a create operation? If not, fail
|
|
|
|
//
|
|
|
|
if (Create == FALSE) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// THIS WHOLE PATH IS TODO
|
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate a non paged pool page for the PDE
|
|
|
|
//
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status)) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make the entry valid
|
|
|
|
//
|
|
|
|
Pte.u.Hard.AsUlong = 0xDEADBEEF;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save it
|
|
|
|
//
|
|
|
|
MmGlobalKernelPageDirectory[PdeOffset] = Pte.u.Hard.AsUlong;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now set the actual PDE
|
|
|
|
//
|
|
|
|
PointerPde = (PMMPTE)&MmGlobalKernelPageDirectory[PdeOffset];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Is this a create operation? If not, fail
|
|
|
|
//
|
|
|
|
if (Create == FALSE) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// THIS WHOLE PATH IS TODO
|
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate a non paged pool page for the PDE
|
|
|
|
//
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status)) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make the entry valid
|
|
|
|
//
|
|
|
|
Pte.u.Hard.AsUlong = 0xDEADBEEF;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set it
|
|
|
|
//
|
|
|
|
*PointerPde = Pte;
|
|
|
|
}
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Return the PTE
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
return MiGetPteAddress(Address);
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
MMPTE
|
|
|
|
NTAPI
|
|
|
|
MiGetPageEntryForProcess(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-07-27 19:52:41 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
MMPTE Pte;
|
|
|
|
Pte.u.Hard.AsUlong = 0;
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Get the PTE
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
PointerPte = MiGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (PointerPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Capture the PTE value and unmap the page table
|
|
|
|
//
|
|
|
|
Pte = *PointerPte;
|
|
|
|
MiUnmapPageTable(PointerPte);
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Return the PTE value
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
return Pte;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmDeletePageTable(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
PMMPTE PointerPde;
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Not valid for kernel addresses
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-06-29 02:58:05 +00:00
|
|
|
DPRINT("MmDeletePageTable(%p, %p)\n", Process, Address);
|
2008-03-10 17:27:14 +00:00
|
|
|
ASSERT(Address < MmSystemRangeStart);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if this is for a different process
|
|
|
|
//
|
|
|
|
if ((Process) && (Process != PsGetCurrentProcess()))
|
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// FIXME-USER: Need to attach to the process
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
ASSERT(FALSE);
|
2008-03-10 17:27:14 +00:00
|
|
|
}
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Get the PDE
|
|
|
|
//
|
|
|
|
PointerPde = MiGetPdeAddress(Address);
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// On ARM, we use a section mapping for the original low-memory mapping
|
|
|
|
//
|
|
|
|
if ((Address) || (PointerPde->u.Hard.L1.Section.Type != SectionPte))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Make sure it's valid
|
|
|
|
//
|
|
|
|
ASSERT(PointerPde->u.Hard.L1.Coarse.Type == CoarsePte);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Clear the PDE
|
|
|
|
//
|
|
|
|
PointerPde->u.Hard.AsUlong = 0;
|
|
|
|
ASSERT(PointerPde->u.Hard.L1.Fault.Type == FaultPte);
|
|
|
|
|
|
|
|
//
|
2008-06-24 14:16:06 +00:00
|
|
|
// Invalidate the TLB entry
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
MiFlushTlb(PointerPde, MiAddressToPte(Address));
|
2008-06-24 14:16:06 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
BOOLEAN
|
2008-06-24 14:16:06 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
IN PLARGE_INTEGER DirectoryTableBase)
|
2008-06-24 14:16:06 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// FIXME-USER: Need to create address space
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return 0;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmUpdatePageDir(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN ULONG Size)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Nothing to do
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
return;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
NTSTATUS
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
Mmi386ReleaseMmInfo(IN PEPROCESS Process)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-07-22 07:11:33 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// FIXME-USER: Need to delete address space
|
2008-07-22 07:11:33 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return 0;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
NTSTATUS
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
|
|
|
|
IN PLARGE_INTEGER DirectoryTableBase)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Share the directory base with the idle process
|
2008-06-30 08:40:54 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
*DirectoryTableBase = PsGetCurrentProcess()->Pcb.DirectoryTableBase;
|
2008-06-30 08:40:54 +00:00
|
|
|
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Initialize the Addresss Space
|
2008-06-30 08:40:54 +00:00
|
|
|
//
|
2008-07-28 02:13:56 +00:00
|
|
|
KeInitializeGuardedMutex(&Process->AddressCreationLock);
|
|
|
|
Process->VadRoot.BalancedRoot.u1.Parent = NULL;
|
2008-06-30 08:40:54 +00:00
|
|
|
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// The process now has an address space
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
Process->HasAddressSpace = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
PULONG
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmGetPageDirectory(VOID)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Return the TTB
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
return (PULONG)KeArmTranslationTableRegisterGet().AsUlong;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmDisableVirtualMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
OUT PBOOLEAN WasDirty,
|
|
|
|
OUT PPFN_TYPE Page)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
2008-07-27 19:52:41 +00:00
|
|
|
while (TRUE);
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmEnableVirtualMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
2008-07-27 19:52:41 +00:00
|
|
|
while (TRUE);
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2008-07-22 09:31:13 +00:00
|
|
|
MmCreateVirtualMappingInternal(IN PVOID Address,
|
|
|
|
IN ULONG Protection,
|
|
|
|
IN PPFN_NUMBER Pages,
|
|
|
|
IN ULONG PageCount,
|
|
|
|
IN BOOLEAN MarkAsMapped)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
PMMPTE PointerPte, LastPte, PointerPde, LastPde;
|
|
|
|
MMPTE TempPte, TempPde;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFN_NUMBER Pfn;
|
2008-06-29 02:58:05 +00:00
|
|
|
DPRINT("[KMAP]: %p %d\n", Address, PageCount);
|
2008-06-24 14:16:06 +00:00
|
|
|
//ASSERT(Address >= MmSystemRangeStart);
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Get our templates
|
|
|
|
//
|
|
|
|
TempPte = MiArmTemplatePte;
|
|
|
|
TempPde = MiArmTemplatePde;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Check if we have PDEs for this region
|
|
|
|
//
|
|
|
|
PointerPde = MiGetPdeAddress(Address);
|
|
|
|
LastPde = PointerPde + (PageCount / 256);
|
|
|
|
while (PointerPde <= LastPde)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if we need to allocate the PDE
|
|
|
|
//
|
|
|
|
if (PointerPde->u.Hard.L1.Fault.Type == FaultPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Request a page
|
|
|
|
//
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Setup the PFN
|
|
|
|
//
|
|
|
|
TempPde.u.Hard.L1.Coarse.BaseAddress = (Pfn << PAGE_SHIFT) >> CPT_SHIFT;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write the PDE
|
|
|
|
//
|
|
|
|
ASSERT(PointerPde->u.Hard.L1.Fault.Type == FaultPte);
|
|
|
|
ASSERT(TempPde.u.Hard.L1.Coarse.Type == CoarsePte);
|
|
|
|
*PointerPde = TempPde;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PTE for this 1MB region
|
|
|
|
//
|
|
|
|
PointerPte = MiGetPteAddress(MiGetPteAddress(Address));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write the PFN of the PDE
|
|
|
|
//
|
|
|
|
TempPte.u.Hard.L2.Small.BaseAddress = Pfn;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Write the PTE
|
|
|
|
//
|
|
|
|
ASSERT(PointerPte->u.Hard.L2.Fault.Type == FaultPte);
|
|
|
|
ASSERT(TempPte.u.Hard.L2.Small.Type == SmallPte);
|
|
|
|
*PointerPte = TempPte;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Next
|
|
|
|
//
|
|
|
|
PointerPde++;
|
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Get start and end address and loop each PTE
|
|
|
|
//
|
|
|
|
PointerPte = MiGetPteAddress(Address);
|
|
|
|
LastPte = PointerPte + PageCount - 1;
|
|
|
|
while (PointerPte <= LastPte)
|
|
|
|
{
|
2008-07-22 09:31:13 +00:00
|
|
|
//
|
|
|
|
// Mark it as mapped
|
|
|
|
//
|
|
|
|
if (MarkAsMapped) MmMarkPageMapped(*Pages);
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Set the PFN
|
|
|
|
//
|
|
|
|
TempPte.u.Hard.L2.Small.BaseAddress = *Pages++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write the PTE
|
|
|
|
//
|
|
|
|
ASSERT(PointerPte->u.Hard.L2.Fault.Type == FaultPte);
|
|
|
|
ASSERT(TempPte.u.Hard.L2.Small.Type == SmallPte);
|
|
|
|
*PointerPte = TempPte;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Next
|
|
|
|
//
|
|
|
|
PointerPte++;
|
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// All done
|
|
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-22 09:31:13 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreateVirtualMappingForKernel(IN PVOID Address,
|
|
|
|
IN ULONG Protection,
|
|
|
|
IN PPFN_NUMBER Pages,
|
|
|
|
IN ULONG PageCount)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Call the internal version
|
|
|
|
//
|
|
|
|
return MmCreateVirtualMappingInternal(Address,
|
|
|
|
Protection,
|
|
|
|
Pages,
|
|
|
|
PageCount,
|
|
|
|
FALSE);
|
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreateVirtualMappingUnsafe(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
2008-03-10 17:27:14 +00:00
|
|
|
IN ULONG Protection,
|
2008-02-13 06:43:36 +00:00
|
|
|
IN PPFN_TYPE Pages,
|
|
|
|
IN ULONG PageCount)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Are we only handling the kernel?
|
|
|
|
//
|
2008-06-24 14:16:06 +00:00
|
|
|
if (!(Process) || (Process == PsGetCurrentProcess()))
|
2008-03-10 17:27:14 +00:00
|
|
|
{
|
|
|
|
//
|
2008-07-22 09:31:13 +00:00
|
|
|
// Call the internal version
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
2008-07-22 09:31:13 +00:00
|
|
|
return MmCreateVirtualMappingInternal(Address,
|
|
|
|
Protection,
|
|
|
|
Pages,
|
|
|
|
PageCount,
|
|
|
|
TRUE);
|
2008-03-10 17:27:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// FIXME-USER: Support user-mode mappings
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
ASSERT(FALSE);
|
2008-02-13 06:43:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreateVirtualMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
2008-03-10 17:27:14 +00:00
|
|
|
IN ULONG Protection,
|
2008-02-13 06:43:36 +00:00
|
|
|
IN PPFN_TYPE Pages,
|
|
|
|
IN ULONG PageCount)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
ULONG i;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Loop each page
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
for (i = 0; i < PageCount; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Make sure the page is marked as in use
|
|
|
|
//
|
|
|
|
ASSERT(MmIsPageInUse(Pages[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Call the unsafe version
|
|
|
|
//
|
|
|
|
return MmCreateVirtualMappingUnsafe(Process,
|
|
|
|
Address,
|
|
|
|
Protection,
|
|
|
|
Pages,
|
|
|
|
PageCount);
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
VOID
|
2008-02-13 06:43:36 +00:00
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmRawDeleteVirtualMapping(IN PVOID Address)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-07-27 19:52:41 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Get the PTE
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
|
|
|
|
if ((PointerPte) && (PointerPte->u.Hard.L2.Fault.Type != FaultPte))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Destroy it
|
|
|
|
//
|
|
|
|
PointerPte->u.Hard.AsUlong = 0;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Flush the TLB
|
|
|
|
//
|
|
|
|
MiFlushTlb(PointerPte, Address);
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2008-07-27 19:52:41 +00:00
|
|
|
MmDeleteVirtualMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN BOOLEAN FreePage,
|
|
|
|
OUT PBOOLEAN WasDirty,
|
|
|
|
OUT PPFN_TYPE Page)
|
2008-02-13 06:43:36 +00:00
|
|
|
{
|
2008-07-27 19:52:41 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
MMPTE Pte;
|
2008-07-27 20:58:23 +00:00
|
|
|
PFN_NUMBER Pfn = 0;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PTE
|
|
|
|
//
|
|
|
|
PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
|
2008-07-27 20:58:23 +00:00
|
|
|
if (PointerPte)
|
|
|
|
{
|
2008-07-27 19:52:41 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
// Save and destroy the PTE
|
2008-07-27 19:52:41 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
Pte = *PointerPte;
|
|
|
|
PointerPte->u.Hard.AsUlong = 0;
|
|
|
|
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
// Flush the TLB
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
MiFlushTlb(PointerPte, Address);
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
// Unmap the PFN
|
2008-07-27 19:52:41 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
Pfn = Pte.u.Hard.L2.Small.BaseAddress;
|
|
|
|
if (Pfn) MmMarkPageUnmapped(Pfn);
|
|
|
|
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
// Release the PFN if it was ours
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
if ((FreePage) && (Pfn)) MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
2008-03-11 04:42:54 +00:00
|
|
|
}
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
// Return if the page was dirty
|
2008-03-11 04:42:54 +00:00
|
|
|
//
|
2008-07-27 20:58:23 +00:00
|
|
|
if (WasDirty) *WasDirty = FALSE; // LIE!!!
|
|
|
|
if (Page) *Page = Pfn;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
MmCreateHyperspaceMapping(IN PFN_TYPE Page)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
PMMPTE PointerPte, FirstPte, LastPte;
|
|
|
|
MMPTE TempPte;
|
|
|
|
PVOID Address;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Loop hyperspace PTEs (1MB)
|
|
|
|
//
|
2008-07-28 03:07:03 +00:00
|
|
|
FirstPte = PointerPte = MiGetPteAddress((PVOID)HYPER_SPACE);
|
2008-03-10 17:27:14 +00:00
|
|
|
LastPte = PointerPte + 256;
|
|
|
|
while (PointerPte <= LastPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Find a free slot
|
|
|
|
//
|
|
|
|
if (PointerPte->u.Hard.L2.Fault.Type == FaultPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Use this entry
|
|
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Try the next one
|
|
|
|
//
|
|
|
|
PointerPte++;
|
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Check if we didn't find anything
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
if (PointerPte > LastPte) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create the mapping
|
|
|
|
//
|
|
|
|
TempPte = MiArmTemplatePte;
|
|
|
|
TempPte.u.Hard.L2.Small.BaseAddress = Page;
|
|
|
|
ASSERT(PointerPte->u.Hard.L2.Fault.Type == FaultPte);
|
|
|
|
ASSERT(TempPte.u.Hard.L2.Small.Type == SmallPte);
|
|
|
|
*PointerPte = TempPte;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Return the address
|
|
|
|
//
|
2008-07-28 03:07:03 +00:00
|
|
|
Address = (PVOID)(HYPER_SPACE + ((PointerPte - FirstPte) * PAGE_SIZE));
|
2008-07-27 19:52:41 +00:00
|
|
|
KeArmInvalidateTlbEntry(Address);
|
2008-06-29 02:58:05 +00:00
|
|
|
DPRINT("[HMAP]: %p %lx\n", Address, Page);
|
2008-03-10 17:27:14 +00:00
|
|
|
return Address;
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PFN_TYPE
|
|
|
|
NTAPI
|
|
|
|
MmDeleteHyperspaceMapping(IN PVOID Address)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
PFN_TYPE Pfn;
|
|
|
|
PMMPTE PointerPte;
|
2008-06-29 02:58:05 +00:00
|
|
|
DPRINT("[HUNMAP]: %p\n", Address);
|
2008-03-10 17:27:14 +00:00
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Get the PTE
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
PointerPte = MiGetPteAddress(Address);
|
|
|
|
ASSERT(PointerPte->u.Hard.L2.Small.Type == SmallPte);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save the PFN
|
|
|
|
//
|
|
|
|
Pfn = PointerPte->u.Hard.L2.Small.BaseAddress;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Destroy the PTE
|
|
|
|
//
|
|
|
|
PointerPte->u.Hard.AsUlong = 0;
|
|
|
|
ASSERT(PointerPte->u.Hard.L2.Fault.Type == FaultPte);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Flush the TLB entry and return the PFN
|
|
|
|
//
|
2008-07-27 19:52:41 +00:00
|
|
|
KeArmInvalidateTlbEntry(Address);
|
2008-02-13 06:43:36 +00:00
|
|
|
return Pfn;
|
|
|
|
}
|
|
|
|
|
2008-07-27 19:52:41 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmDeletePageFileMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN SWAPENTRY *SwapEntry)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreatePageFileMapping(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN SWAPENTRY SwapEntry)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PFN_TYPE
|
|
|
|
NTAPI
|
|
|
|
MmGetPfnForProcess(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
MMPTE Pte;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PTE
|
|
|
|
//
|
|
|
|
Pte = MiGetPageEntryForProcess(Process, Address);
|
|
|
|
if (Pte.u.Hard.L2.Fault.Type == FaultPte) return 0;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return PFN
|
|
|
|
//
|
|
|
|
return Pte.u.Hard.L2.Small.BaseAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MmIsDirtyPage(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmSetCleanPage(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmSetDirtyPage(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MmIsPagePresent(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fault PTEs are 0, which is FALSE (non-present)
|
|
|
|
//
|
|
|
|
return MiGetPageEntryForProcess(Process, Address).u.Hard.L2.Fault.Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MmIsPageSwapEntry(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
MMPTE Pte;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PTE
|
|
|
|
//
|
|
|
|
Pte = MiGetPageEntryForProcess(Process, Address);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make sure it's valid, but faulting
|
|
|
|
//
|
|
|
|
return (Pte.u.Hard.L2.Fault.Type == FaultPte) && (Pte.u.Hard.AsUlong);
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
MmGetPageProtect(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We don't enforce any protection on the pages -- they are all RWX
|
|
|
|
//
|
|
|
|
return PAGE_READWRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmSetPageProtect(IN PEPROCESS Process,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN ULONG Protection)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We don't enforce any protection on the pages -- they are all RWX
|
|
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmInitGlobalKernelPageDirectory(VOID)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
ULONG i;
|
|
|
|
PULONG CurrentPageDirectory = (PULONG)PDE_BASE;
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// Good place to setup template PTE/PDEs.
|
|
|
|
// We are lazy and pick a known-good PTE
|
|
|
|
//
|
|
|
|
MiArmTemplatePte = *MiGetPteAddress(0x80000000);
|
|
|
|
MiArmTemplatePde = *MiGetPdeAddress(0x80000000);
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Loop the 2GB of address space which belong to the kernel
|
|
|
|
//
|
|
|
|
for (i = MiGetPdeOffset(MmSystemRangeStart); i < 1024; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if we have an entry for this already
|
|
|
|
//
|
|
|
|
if ((i != MiGetPdeOffset(PTE_BASE)) &&
|
|
|
|
(i != MiGetPdeOffset(HYPER_SPACE)) &&
|
|
|
|
(!MmGlobalKernelPageDirectory[i]) &&
|
|
|
|
(CurrentPageDirectory[i]))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We don't, link it in our global page directory
|
|
|
|
//
|
|
|
|
MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
|
|
|
|
}
|
|
|
|
}
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitPageDirectoryMap(VOID)
|
|
|
|
{
|
2008-03-10 17:27:14 +00:00
|
|
|
MEMORY_AREA* MemoryArea = NULL;
|
|
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Create memory area for the PTE area
|
|
|
|
//
|
|
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
BaseAddress = (PVOID)PTE_BASE;
|
|
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&BaseAddress,
|
|
|
|
0x1000000,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
&MemoryArea,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
BoundaryAddressMultiple);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
2008-07-27 19:52:41 +00:00
|
|
|
|
2008-03-10 17:27:14 +00:00
|
|
|
//
|
|
|
|
// Create memory area for the PDE area
|
|
|
|
//
|
|
|
|
BaseAddress = (PVOID)PDE_BASE;
|
|
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&BaseAddress,
|
|
|
|
0x100000,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
&MemoryArea,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
BoundaryAddressMultiple);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
2008-02-13 06:43:36 +00:00
|
|
|
//
|
2008-03-10 17:27:14 +00:00
|
|
|
// And finally, hyperspace
|
|
|
|
//
|
|
|
|
BaseAddress = (PVOID)HYPER_SPACE;
|
|
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&BaseAddress,
|
|
|
|
PAGE_SIZE,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
&MemoryArea,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
BoundaryAddressMultiple);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
2008-02-13 06:43:36 +00:00
|
|
|
}
|
2008-07-27 19:52:41 +00:00
|
|
|
|
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PHYSICAL_ADDRESS
|
|
|
|
NTAPI
|
|
|
|
MmGetPhysicalAddress(IN PVOID Address)
|
|
|
|
{
|
|
|
|
PHYSICAL_ADDRESS PhysicalAddress;
|
|
|
|
MMPTE Pte;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Early boot PCR check
|
|
|
|
//
|
|
|
|
if (Address == PCR)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// ARM Hack while we still use a section PTE
|
|
|
|
//
|
|
|
|
PMMPTE PointerPte;
|
|
|
|
PointerPte = MiGetPdeAddress(PCR);
|
|
|
|
ASSERT(PointerPte->u.Hard.L1.Section.Type == SectionPte);
|
|
|
|
PhysicalAddress.QuadPart = PointerPte->u.Hard.L1.Section.BaseAddress;
|
|
|
|
PhysicalAddress.QuadPart <<= CPT_SHIFT;
|
|
|
|
PhysicalAddress.LowPart += BYTE_OFFSET(Address);
|
|
|
|
return PhysicalAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the PTE
|
|
|
|
//
|
|
|
|
Pte = MiGetPageEntryForProcess(NULL, Address);
|
|
|
|
if ((Pte.u.Hard.AsUlong) && (Pte.u.Hard.L2.Fault.Type != FaultPte))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Return the information
|
|
|
|
//
|
|
|
|
ASSERT(Pte.u.Hard.L2.Small.Type == SmallPte);
|
|
|
|
PhysicalAddress.QuadPart = Pte.u.Hard.L2.Small.BaseAddress;
|
|
|
|
PhysicalAddress.QuadPart <<= PAGE_SHIFT;
|
|
|
|
PhysicalAddress.LowPart += BYTE_OFFSET(Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Invalid or unmapped
|
|
|
|
//
|
|
|
|
PhysicalAddress.QuadPart = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return the physical address
|
|
|
|
//
|
|
|
|
return PhysicalAddress;
|
|
|
|
}
|