- Implement super-simple KeSweepICache that always flushes the entire instruction cache. Use it in KD64 after modifying memory to make sure CPU gets the correct code to execute, and in NtFlushInstructionCache. May improve breakpoints somewhat.

- Move NtFlushInstructionCache from sysinfo.c to virtual.c where it fits better. Likewise, move it from kefuncs to mmfuncs in NDK, and fix function arguments (ULONG -> SIZE_T).
- Re-enable TRAP_DEBUG, adding back critical checks in the trap code. Checks can be improved but it is better than potentially silently messing up system state.
- Move remaining RtlPrefetchMemoryNonTemporal code into kernel. Stubbed for non-x86.
- By Hermes suggestion, override ASSERT to NT_ASSERT only for MSVC builds as that is where the main benefit is.

svn path=/trunk/; revision=68907
This commit is contained in:
Stefan Ginsberg 2015-09-01 23:45:48 +00:00
parent e33dc625bc
commit e4007ae73a
16 changed files with 160 additions and 117 deletions

View file

@ -1507,12 +1507,12 @@ BOOL
WINAPI
FlushInstructionCache(IN HANDLE hProcess,
IN LPCVOID lpBaseAddress,
IN SIZE_T dwSize)
IN SIZE_T nSize)
{
NTSTATUS Status;
/* Call the native function */
Status = NtFlushInstructionCache(hProcess, (PVOID)lpBaseAddress, dwSize);
Status = NtFlushInstructionCache(hProcess, (PVOID)lpBaseAddress, nSize);
if (!NT_SUCCESS(Status))
{
/* Handle failure case */

View file

@ -398,15 +398,6 @@ NtDelayExecution(
_In_ LARGE_INTEGER *Interval
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFlushInstructionCache(
_In_ HANDLE ProcessHandle,
_In_ PVOID BaseAddress,
_In_ ULONG NumberOfBytesToFlush
);
ULONG
NTAPI
NtGetCurrentProcessorNumber(

View file

@ -134,6 +134,15 @@ NtExtendSection(
_In_ PLARGE_INTEGER NewMaximumSize
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtFlushInstructionCache(
_In_ HANDLE ProcessHandle,
_In_ PVOID BaseAddress,
_In_ SIZE_T NumberOfBytesToFlush
);
NTSYSCALLAPI
NTSTATUS
NTAPI

View file

@ -146,21 +146,6 @@ RtlMoveMemory(PVOID Destination,
memmove(Destination, Source, Length);
}
/*
* @implemented
*/
VOID
FASTCALL
RtlPrefetchMemoryNonTemporal(IN PVOID Source,
IN SIZE_T Length)
{
/* By nature of prefetch, this is non-portable. */
(void)Source;
(void)Length;
}
#undef RtlZeroMemory
/*
* @implemented

View file

@ -100,6 +100,3 @@ RtlZeroMemory:
mr 5,4
xor 4,4,4
b memset
RtlPrefetchMemoryNonTemporal:
blr

View file

@ -2533,99 +2533,19 @@ NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
return Status;
}
NTSTATUS
NTAPI
NtFlushInstructionCache(
_In_ HANDLE ProcessHandle,
_In_opt_ PVOID BaseAddress,
_In_ ULONG FlushSize)
{
KAPC_STATE ApcState;
PKPROCESS Process;
NTSTATUS Status;
PAGED_CODE();
/* Is a base address given? */
if (BaseAddress != NULL)
{
/* If the requested size is 0, there is nothing to do */
if (FlushSize == 0)
{
return STATUS_SUCCESS;
}
/* Is this a user mode call? */
if (KeGetPreviousMode() != KernelMode)
{
/* Make sure the base address is in user space */
if (BaseAddress > MmHighestUserAddress)
{
DPRINT1("Invalid BaseAddress 0x%p\n", BaseAddress);
return STATUS_ACCESS_VIOLATION;
}
}
}
/* Is another process requested? */
if (ProcessHandle != NtCurrentProcess())
{
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
PsProcessType,
KeGetPreviousMode(),
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the process %p\n", ProcessHandle);
return Status;
}
/* Attach to the process */
KeStackAttachProcess(Process, &ApcState);
}
/* FIXME: don't flush everything if a range is requested */
#if defined(_M_IX86) || defined(_M_AMD64)
__wbinvd();
#elif defined(_M_PPC)
__asm__ __volatile__("tlbsync");
#elif defined(_M_MIPS)
DPRINT1("NtFlushInstructionCache() is not implemented\n");
DbgBreakPoint();
#elif defined(_M_ARM)
_MoveToCoprocessor(0, CP15_ICIALLU);
#else
#error Unknown architecture
#endif
/* Check if we attached */
if (ProcessHandle != NtCurrentProcess())
{
/* Detach from the process */
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
}
return STATUS_SUCCESS;
}
ULONG
NTAPI
NtGetCurrentProcessorNumber(VOID)
{
/* Just return the CPU */
/* Just use Ke */
return KeGetCurrentProcessorNumber();
}
/*
* @implemented
*/
#undef ExGetPreviousMode
KPROCESSOR_MODE
NTAPI
ExGetPreviousMode (VOID)
ExGetPreviousMode(VOID)
{
/* Just use Ke */
return KeGetPreviousMode();
}

View file

@ -188,6 +188,19 @@ KeFlushProcessTb(VOID)
__writecr3(__readcr3());
}
FORCEINLINE
VOID
KeSweepICache(IN PVOID BaseAddress,
IN SIZE_T FlushSize)
{
//
// Always sweep the whole cache
//
UNREFERENCED_PARAMETER(BaseAddress);
UNREFERENCED_PARAMETER(FlushSize);
__wbinvd();
}
FORCEINLINE
VOID
KiRundownThread(IN PKTHREAD Thread)

View file

@ -116,6 +116,19 @@ KeFlushProcessTb(VOID)
KeArmFlushTlb();
}
FORCEINLINE
VOID
KeSweepICache(IN PVOID BaseAddress,
IN SIZE_T FlushSize)
{
//
// Always sweep the whole cache
//
UNREFERENCED_PARAMETER(BaseAddress);
UNREFERENCED_PARAMETER(FlushSize);
_MoveToCoprocessor(0, CP15_ICIALLU);
}
FORCEINLINE
VOID
KiRundownThread(IN PKTHREAD Thread)

View file

@ -266,6 +266,19 @@ KeFlushProcessTb(VOID)
__writecr3(__readcr3());
}
FORCEINLINE
VOID
KeSweepICache(IN PVOID BaseAddress,
IN SIZE_T FlushSize)
{
//
// Always sweep the whole cache
//
UNREFERENCED_PARAMETER(BaseAddress);
UNREFERENCED_PARAMETER(FlushSize);
__wbinvd();
}
FORCEINLINE
PRKTHREAD
KeGetCurrentThread(VOID)

View file

@ -8,8 +8,6 @@
#pragma once
#define TRAP_DEBUG 0
#define UNREACHABLE __assume(0)
#if _MSC_VER
@ -72,9 +70,9 @@ KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs);
}
#if TRAP_DEBUG
VOID
#if DBG
FORCEINLINE
VOID
KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
{
/* Set the debug information */

View file

@ -89,6 +89,19 @@ KeFlushProcessTb(VOID)
__asm__("sync\n\tisync\n\t");
}
FORCEINLINE
VOID
KeSweepICache(IN PVOID BaseAddress,
IN SIZE_T FlushSize)
{
//
// Always sweep the whole cache
//
UNREFERENCED_PARAMETER(BaseAddress);
UNREFERENCED_PARAMETER(FlushSize);
__asm__ __volatile__("tlbsync");
}
FORCEINLINE
PRKTHREAD
KeGetCurrentThread(VOID)

View file

@ -98,8 +98,10 @@ extern UCHAR _KeNumberProcessors;
//
// NT_ASSERT Best Assert
//
#if defined(_MSC_VER)
#undef ASSERT
#define ASSERT NT_ASSERT
#endif
/* Internal Headers */
#include "internal/ntoskrnl.h"

View file

@ -84,6 +84,11 @@ KdpCopyMemoryChunks(IN ULONG64 Address,
RemainingLength = RemainingLength - CopyChunk;
}
/*
* We may have modified executable code, flush the instruction cache
*/
KeSweepICache((PVOID)Address, TotalSize);
/*
* Return the size we managed to copy
* and return success if we could copy the whole range

View file

@ -56,7 +56,7 @@ PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
#endif
#if TRAP_DEBUG
#if DBG
BOOLEAN StopChecking = FALSE;
#endif

View file

@ -2914,6 +2914,73 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
return Status;
}
NTSTATUS
NTAPI
NtFlushInstructionCache(_In_ HANDLE ProcessHandle,
_In_opt_ PVOID BaseAddress,
_In_ SIZE_T FlushSize)
{
KAPC_STATE ApcState;
PKPROCESS Process;
NTSTATUS Status;
PAGED_CODE();
/* Is a base address given? */
if (BaseAddress != NULL)
{
/* If the requested size is 0, there is nothing to do */
if (FlushSize == 0)
{
return STATUS_SUCCESS;
}
/* Is this a user mode call? */
if (ExGetPreviousMode() != KernelMode)
{
/* Make sure the base address is in user space */
if (BaseAddress > MmHighestUserAddress)
{
DPRINT1("Invalid BaseAddress 0x%p\n", BaseAddress);
return STATUS_ACCESS_VIOLATION;
}
}
}
/* Is another process requested? */
if (ProcessHandle != NtCurrentProcess())
{
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
PsProcessType,
ExGetPreviousMode(),
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the process %p\n", ProcessHandle);
return Status;
}
/* Attach to the process */
KeStackAttachProcess(Process, &ApcState);
}
/* Forward to Ke */
KeSweepICache(BaseAddress, FlushSize);
/* Check if we attached */
if (ProcessHandle != NtCurrentProcess())
{
/* Detach from the process and dereference it */
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
}
/* All done, return to caller */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
NtProtectVirtualMemory(IN HANDLE ProcessHandle,

View file

@ -62,4 +62,21 @@ RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
return STATUS_SUCCESS;
}
#if !defined(_M_IX86)
//
// Stub for architectures which don't have this implemented
//
VOID
FASTCALL
RtlPrefetchMemoryNonTemporal(IN PVOID Source,
IN SIZE_T Length)
{
//
// Do nothing
//
UNREFERENCED_PARAMETER(Source);
UNREFERENCED_PARAMETER(Length);
}
#endif
/* EOF */