- Implement super-simple KeSweepICache that always flushes the entire instruction...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Tue, 1 Sep 2015 23:45:48 +0000 (23:45 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Tue, 1 Sep 2015 23:45:48 +0000 (23:45 +0000)
- 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

16 files changed:
reactos/dll/win32/kernel32/client/proc.c
reactos/include/ndk/kefuncs.h
reactos/include/ndk/mmfuncs.h
reactos/lib/rtl/mem.c
reactos/lib/rtl/powerpc/rtlmem.s
reactos/ntoskrnl/ex/sysinfo.c
reactos/ntoskrnl/include/internal/amd64/ke.h
reactos/ntoskrnl/include/internal/arm/ke.h
reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/include/internal/i386/trap_x.h
reactos/ntoskrnl/include/internal/powerpc/ke.h
reactos/ntoskrnl/include/ntoskrnl.h
reactos/ntoskrnl/kd64/kdapi.c
reactos/ntoskrnl/ke/i386/traphdlr.c
reactos/ntoskrnl/mm/ARM3/virtual.c
reactos/ntoskrnl/rtl/misc.c

index 809457c..0f57b7b 100644 (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 */
index a1e379f..bf8463e 100644 (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(
index 0d3782f..9872ecb 100644 (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
index 0704f52..6927f54 100644 (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
index 12c98c6..8d08ed0 100644 (file)
@@ -100,6 +100,3 @@ RtlZeroMemory:
         mr 5,4
         xor 4,4,4
         b memset
-
-RtlPrefetchMemoryNonTemporal:
-        blr
index 3f5bf6f..570bf91 100644 (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();
 }
index 1701fe6..c5af042 100644 (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)
index 32ac28d..2d39c58 100644 (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)
index 4dbdb2d..7c9cce3 100644 (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)
index 99e7cba..444696f 100644 (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 */
index 4edfbf4..87c72a2 100644 (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)
index 1b51ebc..5e5c9b4 100644 (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"
index 1c42792..5f14240 100644 (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
index 908a35e..d3b041e 100644 (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
 
index ee94465..95c1571 100644 (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,
index 1b88549..5d0861d 100644 (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 */