mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 15:18:33 +00:00
223 lines
5.2 KiB
C
223 lines
5.2 KiB
C
/*****************************************************************************\
|
|
* *
|
|
* This file is current kept ONLY for DOCUMENTATION purposes, until *
|
|
* we are sure that all the functionality (e.g. regarding the "big pages") *
|
|
* are fully present in Mm and in mm/ARM3/mmdbg.c that supersedes this file. *
|
|
* *
|
|
\*****************************************************************************/
|
|
|
|
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel
|
|
* PURPOSE: Kernel Debugger Safe Memory Support
|
|
*
|
|
* PROGRAMMERS: arty
|
|
*/
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define HIGH_PHYS_MASK 0x80000000
|
|
#define PAGE_TABLE_MASK 0x3ff
|
|
#define BIG_PAGE_SIZE (1<<22)
|
|
#define CR4_PAGE_SIZE_BIT 0x10
|
|
#define PDE_PRESENT_BIT 0x01
|
|
#define PDE_W_BIT 0x02
|
|
#define PDE_PWT_BIT 0x08
|
|
#define PDE_PCD_BIT 0x10
|
|
#define PDE_ACCESSED_BIT 0x20
|
|
#define PDE_DIRTY_BIT 0x40
|
|
#define PDE_PS_BIT 0x80
|
|
|
|
#define MI_KDBG_TMP_PAGE_1 (HYPER_SPACE + 0x400000 - PAGE_SIZE)
|
|
#define MI_KDBG_TMP_PAGE_0 (MI_KDBG_TMP_PAGE_1 - PAGE_SIZE)
|
|
|
|
/* VARIABLES ***************************************************************/
|
|
|
|
static BOOLEAN KdpPhysAccess = FALSE;
|
|
|
|
static
|
|
ULONG_PTR
|
|
KdpPhysMap(ULONG_PTR PhysAddr, LONG Len)
|
|
{
|
|
MMPTE TempPte;
|
|
PMMPTE PointerPte;
|
|
ULONG_PTR VirtAddr;
|
|
|
|
TempPte.u.Long = PDE_PRESENT_BIT | PDE_W_BIT | PDE_PWT_BIT |
|
|
PDE_PCD_BIT | PDE_ACCESSED_BIT | PDE_DIRTY_BIT;
|
|
|
|
if ((PhysAddr & (PAGE_SIZE - 1)) + Len > PAGE_SIZE)
|
|
{
|
|
TempPte.u.Hard.PageFrameNumber = (PhysAddr >> PAGE_SHIFT) + 1;
|
|
PointerPte = MiAddressToPte((PVOID)MI_KDBG_TMP_PAGE_1);
|
|
*PointerPte = TempPte;
|
|
VirtAddr = (ULONG_PTR)PointerPte << 10;
|
|
KeInvalidateTlbEntry((PVOID)VirtAddr);
|
|
}
|
|
|
|
TempPte.u.Hard.PageFrameNumber = PhysAddr >> PAGE_SHIFT;
|
|
PointerPte = MiAddressToPte((PVOID)MI_KDBG_TMP_PAGE_0);
|
|
*PointerPte = TempPte;
|
|
VirtAddr = (ULONG_PTR)PointerPte << 10;
|
|
KeInvalidateTlbEntry((PVOID)VirtAddr);
|
|
|
|
return VirtAddr + (PhysAddr & (PAGE_SIZE - 1));
|
|
}
|
|
|
|
static
|
|
ULONGLONG
|
|
KdpPhysRead(ULONG_PTR PhysAddr, LONG Len)
|
|
{
|
|
ULONG_PTR Addr;
|
|
ULONGLONG Result = 0;
|
|
|
|
Addr = KdpPhysMap(PhysAddr, Len);
|
|
|
|
switch (Len)
|
|
{
|
|
case 8:
|
|
Result = *((PULONGLONG)Addr);
|
|
break;
|
|
case 4:
|
|
Result = *((PULONG)Addr);
|
|
break;
|
|
case 2:
|
|
Result = *((PUSHORT)Addr);
|
|
break;
|
|
case 1:
|
|
Result = *((PUCHAR)Addr);
|
|
break;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
KdpPhysWrite(ULONG_PTR PhysAddr, LONG Len, ULONGLONG Value)
|
|
{
|
|
ULONG_PTR Addr;
|
|
|
|
Addr = KdpPhysMap(PhysAddr, Len);
|
|
|
|
switch (Len)
|
|
{
|
|
case 8:
|
|
*((PULONGLONG)Addr) = Value;
|
|
break;
|
|
case 4:
|
|
*((PULONG)Addr) = Value;
|
|
break;
|
|
case 2:
|
|
*((PUSHORT)Addr) = Value;
|
|
break;
|
|
case 1:
|
|
*((PUCHAR)Addr) = Value;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static
|
|
BOOLEAN
|
|
KdpTranslateAddress(ULONG_PTR Addr, PULONG_PTR ResultAddr)
|
|
{
|
|
ULONG_PTR CR3Value = __readcr3();
|
|
ULONG_PTR CR4Value = __readcr4();
|
|
ULONG_PTR PageDirectory = (CR3Value & ~(PAGE_SIZE-1)) +
|
|
((Addr >> 22) * sizeof(ULONG));
|
|
ULONG_PTR PageDirectoryEntry = KdpPhysRead(PageDirectory, sizeof(ULONG));
|
|
|
|
/* Not present -> fail */
|
|
if (!(PageDirectoryEntry & PDE_PRESENT_BIT))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Big Page? */
|
|
if ((PageDirectoryEntry & PDE_PS_BIT) && (CR4Value & CR4_PAGE_SIZE_BIT))
|
|
{
|
|
*ResultAddr = (PageDirectoryEntry & ~(BIG_PAGE_SIZE-1)) +
|
|
(Addr & (BIG_PAGE_SIZE-1));
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ULONG_PTR PageTableAddr =
|
|
(PageDirectoryEntry & ~(PAGE_SIZE-1)) +
|
|
((Addr >> PAGE_SHIFT) & PAGE_TABLE_MASK) * sizeof(ULONG);
|
|
ULONG_PTR PageTableEntry = KdpPhysRead(PageTableAddr, sizeof(ULONG));
|
|
if (PageTableEntry & PDE_PRESENT_BIT)
|
|
{
|
|
*ResultAddr = (PageTableEntry & ~(PAGE_SIZE-1)) +
|
|
(Addr & (PAGE_SIZE-1));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
KdpSafeReadMemory(ULONG_PTR Addr, LONG Len, PVOID Value)
|
|
{
|
|
ULONG_PTR ResultPhysAddr;
|
|
|
|
if (!KdpPhysAccess)
|
|
{
|
|
memcpy(Value, (PVOID)Addr, Len);
|
|
return TRUE;
|
|
}
|
|
|
|
memset(Value, 0, Len);
|
|
|
|
if (!KdpTranslateAddress(Addr, &ResultPhysAddr))
|
|
return FALSE;
|
|
|
|
switch (Len)
|
|
{
|
|
case 8:
|
|
*((PULONGLONG)Value) = KdpPhysRead(ResultPhysAddr, Len);
|
|
break;
|
|
case 4:
|
|
*((PULONG)Value) = KdpPhysRead(ResultPhysAddr, Len);
|
|
break;
|
|
case 2:
|
|
*((PUSHORT)Value) = KdpPhysRead(ResultPhysAddr, Len);
|
|
break;
|
|
case 1:
|
|
*((PUCHAR)Value) = KdpPhysRead(ResultPhysAddr, Len);
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
KdpSafeWriteMemory(ULONG_PTR Addr, LONG Len, ULONGLONG Value)
|
|
{
|
|
ULONG_PTR ResultPhysAddr;
|
|
|
|
if (!KdpPhysAccess)
|
|
{
|
|
memcpy((PVOID)Addr, &Value, Len);
|
|
return TRUE;
|
|
}
|
|
|
|
if (!KdpTranslateAddress(Addr, &ResultPhysAddr))
|
|
return FALSE;
|
|
|
|
KdpPhysWrite(ResultPhysAddr, Len, Value);
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
KdpEnableSafeMem(VOID)
|
|
{
|
|
KdpPhysAccess = TRUE;
|
|
}
|
|
|
|
/* EOF */
|