diff --git a/ntoskrnl/kd/amd64/kdmemsup.c b/ntoskrnl/kd/amd64/kdmemsup.c deleted file mode 100644 index 75f19a1cbce..00000000000 --- a/ntoskrnl/kd/amd64/kdmemsup.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Kernel - * FILE: ntoskrnl/kd/amd64/kdmemsup.c - * PURPOSE: Kernel Debugger Safe Memory Support - * - * PROGRAMMERS: arty - */ - -#include -#define NDEBUG -#include - -#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; - } -} - -BOOLEAN -NTAPI -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 */ diff --git a/ntoskrnl/kd/i386/kdmemsup.c b/ntoskrnl/kd/i386/kdmemsup.c index 7616734ce53..20a5824deb2 100644 --- a/ntoskrnl/kd/i386/kdmemsup.c +++ b/ntoskrnl/kd/i386/kdmemsup.c @@ -1,3 +1,11 @@ +/*****************************************************************************\ + * * + * 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 @@ -44,14 +52,14 @@ KdpPhysMap(ULONG_PTR PhysAddr, LONG Len) if ((PhysAddr & (PAGE_SIZE - 1)) + Len > PAGE_SIZE) { TempPte.u.Hard.PageFrameNumber = (PhysAddr >> PAGE_SHIFT) + 1; - PointerPte = MiAddressToPte(MI_KDBG_TMP_PAGE_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(MI_KDBG_TMP_PAGE_0); + PointerPte = MiAddressToPte((PVOID)MI_KDBG_TMP_PAGE_0); *PointerPte = TempPte; VirtAddr = (ULONG_PTR)PointerPte << 10; KeInvalidateTlbEntry((PVOID)VirtAddr); @@ -112,8 +120,8 @@ KdpPhysWrite(ULONG_PTR PhysAddr, LONG Len, ULONGLONG Value) } } +static BOOLEAN -NTAPI KdpTranslateAddress(ULONG_PTR Addr, PULONG_PTR ResultAddr) { ULONG_PTR CR3Value = __readcr3(); diff --git a/ntoskrnl/kd/kdinit.c b/ntoskrnl/kd/kdinit.c index f5e1c489709..3e32b160920 100644 --- a/ntoskrnl/kd/kdinit.c +++ b/ntoskrnl/kd/kdinit.c @@ -287,9 +287,6 @@ KdInitSystem(ULONG BootPhase, } else /* BootPhase > 0 */ { -#ifdef _M_IX86 - KdpEnableSafeMem(); -#endif } /* Call the Initialization Routines of the Registered Providers */ diff --git a/ntoskrnl/kd/wrappers/gdbstub.c b/ntoskrnl/kd/wrappers/gdbstub.c index 6ca68939fc9..52497779078 100644 --- a/ntoskrnl/kd/wrappers/gdbstub.c +++ b/ntoskrnl/kd/wrappers/gdbstub.c @@ -246,19 +246,35 @@ static volatile BOOLEAN GspMemoryError = FALSE; static CHAR GspReadMemSafe(PCHAR Address) { - CHAR ch = 0; + CHAR Ch = 0; - if (!KdpSafeReadMemory((ULONG_PTR)Address, 1, &ch)) +#if 0 + if (!NT_SUCCESS(KdpCopyMemoryChunks((ULONG64)(ULONG_PTR)Address, &Ch, 1, + 0, MMDBG_COPY_UNSAFE, NULL))) +#else + if (!NT_SUCCESS(MmDbgCopyMemory((ULONG64)(ULONG_PTR)Address, &Ch, 1, + MMDBG_COPY_UNSAFE))) +#endif + { GspMemoryError = TRUE; + } - return ch; + return Ch; } static void GspWriteMemSafe(PCHAR Address, CHAR Ch) { - if (!KdpSafeWriteMemory((ULONG_PTR)Address, 1, Ch)) +#if 0 + if (!NT_SUCCESS(KdpCopyMemoryChunks((ULONG64)(ULONG_PTR)Address, &Ch, 1, + 0, MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, NULL))) +#else + if (!NT_SUCCESS(MmDbgCopyMemory((ULONG64)(ULONG_PTR)Address, &Ch, 1, + MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE))) +#endif + { GspMemoryError = TRUE; + } } /* Convert the memory pointed to by Address into hex, placing result in Buffer diff --git a/ntoskrnl/kdbg/kdb.c b/ntoskrnl/kdbg/kdb.c index 6b9d4695581..d75ab137e64 100644 --- a/ntoskrnl/kdbg/kdb.c +++ b/ntoskrnl/kdbg/kdb.c @@ -1730,40 +1730,101 @@ KdbpGetCommandLineSettings( } } +/* + * Copied from ntoskrnl/kd64/kdapi.c + */ +NTSTATUS +NTAPI +KdpCopyMemoryChunks(IN ULONG64 Address, + IN PVOID Buffer, + IN ULONG TotalSize, + IN ULONG ChunkSize, + IN ULONG Flags, + OUT PULONG ActualSize OPTIONAL) +{ + NTSTATUS Status; + ULONG RemainingLength, CopyChunk; + + /* Check if we didn't get a chunk size or if it is too big */ + if (ChunkSize == 0) + { + /* Default to 4 byte chunks */ + ChunkSize = 4; + } + else if (ChunkSize > MMDBG_COPY_MAX_SIZE) + { + /* Normalize to maximum size */ + ChunkSize = MMDBG_COPY_MAX_SIZE; + } + + /* Copy the whole range in aligned chunks */ + RemainingLength = TotalSize; + CopyChunk = 1; + while (RemainingLength > 0) + { + /* + * Determine the best chunk size for this round. + * The ideal size is aligned, isn't larger than the + * the remaining length and respects the chunk limit. + */ + while (((CopyChunk * 2) <= RemainingLength) && + (CopyChunk < ChunkSize) && + ((Address & ((CopyChunk * 2) - 1)) == 0)) + { + /* Increase it */ + CopyChunk *= 2; + } + + /* + * The chunk size can be larger than the remaining size if this + * isn't the first round, so check if we need to shrink it back. + */ + while (CopyChunk > RemainingLength) + { + /* Shrink it */ + CopyChunk /= 2; + } + + /* Do the copy */ + Status = MmDbgCopyMemory(Address, + Buffer, + CopyChunk, + Flags); + if (!NT_SUCCESS(Status)) + { + /* Copy failed, break out */ + break; + } + + /* Update pointers and length for the next run */ + Address = Address + CopyChunk; + Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk); + RemainingLength = RemainingLength - CopyChunk; + } + + /* We may have modified executable code, flush the instruction cache */ + KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize); + + /* + * Return the size we managed to copy and return + * success if we could copy the whole range. + */ + if (ActualSize) *ActualSize = TotalSize - RemainingLength; + return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; +} + NTSTATUS KdbpSafeReadMemory( OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes) { - BOOLEAN Result = TRUE; - - switch (Bytes) - { - case 1: - case 2: - case 4: - case 8: - Result = KdpSafeReadMemory((ULONG_PTR)Src, Bytes, Dest); - break; - - default: - { - ULONG_PTR Start, End, Write; - - for (Start = (ULONG_PTR)Src, - End = Start + Bytes, - Write = (ULONG_PTR)Dest; - Result && (Start < End); - Start++, Write++) - if (!KdpSafeReadMemory(Start, 1, (PVOID)Write)) - Result = FALSE; - - break; - } - } - - return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION; + return KdpCopyMemoryChunks((ULONG64)(ULONG_PTR)Src, + Dest, + Bytes, + 0, + MMDBG_COPY_UNSAFE, + NULL); } NTSTATUS @@ -1772,16 +1833,10 @@ KdbpSafeWriteMemory( IN PVOID Src, IN ULONG Bytes) { - BOOLEAN Result = TRUE; - ULONG_PTR Start, End, Write; - - for (Start = (ULONG_PTR)Src, - End = Start + Bytes, - Write = (ULONG_PTR)Dest; - Result && (Start < End); - Start++, Write++) - if (!KdpSafeWriteMemory(Write, 1, *((PCHAR)Start))) - Result = FALSE; - - return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION; + return KdpCopyMemoryChunks((ULONG64)(ULONG_PTR)Dest, + Src, + Bytes, + 0, + MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, + NULL); } diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index 38dc52aa787..9d4d6685408 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -369,7 +369,6 @@ if(NOT _WINKD_) if(ARCH STREQUAL "i386") list(APPEND SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/i386/kdbg.c - ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/i386/kdmemsup.c ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/wrappers/gdbstub.c) if(KDBG) list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/i386/kdb_help.S) @@ -377,9 +376,8 @@ if(NOT _WINKD_) endif() elseif(ARCH STREQUAL "amd64") list(APPEND SOURCE - ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/amd64/kd.c ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/i386/kdbg.c # Use the x86 file - ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/amd64/kdmemsup.c) + ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/amd64/kd.c) if(KDBG) list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/amd64/kdb_help.S) list(APPEND SOURCE