mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
- 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:
parent
e33dc625bc
commit
e4007ae73a
|
@ -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 */
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -100,6 +100,3 @@ RtlZeroMemory:
|
|||
mr 5,4
|
||||
xor 4,4,4
|
||||
b memset
|
||||
|
||||
RtlPrefetchMemoryNonTemporal:
|
||||
blr
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue