reactos/ntoskrnl/mm/ARM3/mmdbg.c
Amine Khaldi 527f2f9057 [SHELL/EXPERIMENTS]
* Create a branch for some evul shell experiments.

svn path=/branches/shell-experiments/; revision=61927
2014-02-02 19:37:27 +00:00

326 lines
7.8 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: ntoskrnl/mm/ARM3/mmdbg.c
* PURPOSE: Memory Manager support routines for the Kernel Debugger
* PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#define MODULE_INVOLVED_IN_ARM3
#include "../ARM3/miarm.h"
#ifndef _WINKD_
#define KdpDprintf DPRINT
#elif defined(NDEBUG)
#define KdpDprintf(...)
#endif
/* GLOBALS ********************************************************************/
PVOID MiDebugMapping = MI_DEBUG_MAPPING;
PMMPTE MmDebugPte = NULL;
/* FUNCTIONS ******************************************************************/
BOOLEAN
NTAPI
MmIsSessionAddress(IN PVOID Address)
{
//
// No session space support yet
//
return FALSE;
}
PVOID
NTAPI
MiDbgTranslatePhysicalAddress(IN ULONG64 PhysicalAddress,
IN ULONG Flags)
{
PFN_NUMBER Pfn;
MMPTE TempPte;
PVOID MappingBaseAddress;
//
// Check if we are called too early
//
if (MmDebugPte == NULL)
{
//
// The structures we require aren't initialized yet, fail
//
KdpDprintf("MiDbgTranslatePhysicalAddress called too early! "
"Address: 0x%I64x\n", PhysicalAddress);
return NULL;
}
//
// FIXME: No support for cache flags yet
//
if ((Flags & (MMDBG_COPY_CACHED |
MMDBG_COPY_UNCACHED |
MMDBG_COPY_WRITE_COMBINED)) != 0)
{
//
// Fail
//
KdpDprintf("MiDbgTranslatePhysicalAddress: Cache Flags not yet supported. "
"Flags: 0x%lx\n", Flags & (MMDBG_COPY_CACHED |
MMDBG_COPY_UNCACHED |
MMDBG_COPY_WRITE_COMBINED));
return NULL;
}
//
// Save the base address of our mapping page
//
MappingBaseAddress = MiPteToAddress(MmDebugPte);
//
// Get the template
//
TempPte = ValidKernelPte;
//
// Convert physical address to PFN
//
Pfn = (PFN_NUMBER)(PhysicalAddress >> PAGE_SHIFT);
/* Check if this could be an I/O mapping */
if (!MiGetPfnEntry(Pfn))
{
//
// FIXME: We don't support this yet
//
KdpDprintf("MiDbgTranslatePhysicalAddress: I/O Space not yet supported. "
"PFN: 0x%I64x\n", (ULONG64)Pfn);
return NULL;
}
else
{
//
// Set the PFN in the PTE
//
TempPte.u.Hard.PageFrameNumber = Pfn;
}
//
// Map the PTE and invalidate its TLB entry
//
*MmDebugPte = TempPte;
KeInvalidateTlbEntry(MappingBaseAddress);
//
// Calculate and return the virtual offset into our mapping page
//
return (PVOID)((ULONG_PTR)MappingBaseAddress +
BYTE_OFFSET(PhysicalAddress));
}
VOID
NTAPI
MiDbgUnTranslatePhysicalAddress(VOID)
{
PVOID MappingBaseAddress = MiPteToAddress(MmDebugPte);
//
// The address must still be valid at this point
//
ASSERT(MmIsAddressValid(MappingBaseAddress));
//
// Clear the mapping PTE and invalidate its TLB entry
//
MmDebugPte->u.Long = 0;
KeInvalidateTlbEntry(MappingBaseAddress);
}
NTSTATUS
NTAPI
MmDbgCopyMemory(IN ULONG64 Address,
IN PVOID Buffer,
IN ULONG Size,
IN ULONG Flags)
{
NTSTATUS Status;
PVOID TargetAddress;
ULONG64 PhysicalAddress;
PMMPTE PointerPte;
//
// No local kernel debugging support yet, so don't worry about locking
//
ASSERT(Flags & MMDBG_COPY_UNSAFE);
//
// We only handle 1, 2, 4 and 8 byte requests
//
if ((Size != 1) &&
(Size != 2) &&
(Size != 4) &&
(Size != MMDBG_COPY_MAX_SIZE))
{
//
// Invalid size, fail
//
KdpDprintf("MmDbgCopyMemory: Received Illegal Size 0x%lx\n", Size);
return STATUS_INVALID_PARAMETER_3;
}
//
// The copy must be aligned
//
if ((Address & (Size - 1)) != 0)
{
//
// Fail
//
KdpDprintf("MmDbgCopyMemory: Received Unaligned Address 0x%I64x Size %lx\n",
Address, Size);
return STATUS_INVALID_PARAMETER_3;
}
//
// Check if this is physical or virtual copy
//
if (Flags & MMDBG_COPY_PHYSICAL)
{
//
// Physical: translate and map it to our mapping space
//
TargetAddress = MiDbgTranslatePhysicalAddress(Address, Flags);
//
// Check if translation failed
//
if (!TargetAddress)
{
//
// Fail
//
KdpDprintf("MmDbgCopyMemory: Failed to Translate Physical Address "
"%I64x\n", Address);
return STATUS_UNSUCCESSFUL;
}
//
// The address we received must be valid!
//
ASSERT(MmIsAddressValid(TargetAddress));
}
else
{
//
// Virtual; truncate it to avoid casts later down
//
TargetAddress = (PVOID)(ULONG_PTR)Address;
//
// Check if the address is invalid
//
if (!MmIsAddressValid(TargetAddress))
{
//
// Fail
//
KdpDprintf("MmDbgCopyMemory: Failing %s for invalid "
"Virtual Address 0x%p\n",
Flags & MMDBG_COPY_WRITE ? "write" : "read",
TargetAddress);
return STATUS_UNSUCCESSFUL;
}
//
// No session space support yet
//
ASSERT(MmIsSessionAddress(TargetAddress) == FALSE);
/* If we are going to write to the address, then check if its writable */
PointerPte = MiAddressToPte(TargetAddress);
if ((Flags & MMDBG_COPY_WRITE) && !MI_IS_PAGE_WRITEABLE(PointerPte))
{
/* Not writable, we need to do a physical copy */
Flags |= MMDBG_COPY_PHYSICAL;
/* Calculate the physical address */
PhysicalAddress = PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT;
PhysicalAddress += BYTE_OFFSET(Address);
/* Translate the physical address */
TargetAddress = MiDbgTranslatePhysicalAddress(PhysicalAddress, Flags);
/* Check if translation failed */
if (!TargetAddress)
{
/* Fail */
KdpDprintf("MmDbgCopyMemory: Failed to translate for write "
"%I64x (%I64x)\n", PhysicalAddress, Address);
return STATUS_UNSUCCESSFUL;
}
}
}
//
// Use SEH to try to catch anything else somewhat cleanly
//
_SEH2_TRY
{
//
// Check if this is read or write
//
if (Flags & MMDBG_COPY_WRITE)
{
//
// Do the write
//
RtlCopyMemory(TargetAddress,
Buffer,
Size);
}
else
{
//
// Do the read
//
RtlCopyMemory(Buffer,
TargetAddress,
Size);
}
//
// Copy succeeded
//
Status = STATUS_SUCCESS;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
//
// Get the exception code
//
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
//
// Get rid of the mapping if this was a physical copy
//
if (Flags & MMDBG_COPY_PHYSICAL)
{
//
// Unmap and flush it
//
MiDbgUnTranslatePhysicalAddress();
}
//
// Return status to caller
//
return Status;
}