- Fix IN/OUT privileged instruction fault (we don't yet handle HLT/CLI/STI other...
authorAlex Ionescu <aionescu@gmail.com>
Sun, 21 Jan 2007 22:43:32 +0000 (22:43 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 21 Jan 2007 22:43:32 +0000 (22:43 +0000)
- Enable back proper VMWARE detection.
- Fix namepointer setup in DbgkCreateThread.
- Skip the first entry when doing fake module load messages.
- Fix which handle count is read in DbgkCloseObject.
- Set the right flags for the debug event thread instead of random flags inside the debug event itself when parsing in DbgkpSetProcessDebugPort.
- Add debug event in the temporary list to be woken, if rundown couldn't be acquired.
- Properly validate continue statues allowed in NtDebugContinue.
- Properly support timeout in NtWaitForDebugEvent.
- Properly do backout in NtWaitForDebugEvent.
- Disable LPC debug messages accidentally enabled, and add a small hack to better find the cause of the LPC shutdown bug.

svn path=/trunk/; revision=25572

reactos/base/setup/vmwinst/vmwinst.c
reactos/include/ndk/asm.h
reactos/ntoskrnl/KrnlFun.c
reactos/ntoskrnl/dbgk/dbgkutil.c
reactos/ntoskrnl/dbgk/debug.c
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/lpc/close.c
reactos/ntoskrnl/lpc/port.c

index 1438f3e..bf4e28e 100644 (file)
@@ -1010,7 +1010,7 @@ WinMain(HINSTANCE hInstance,
 {
 
   PVOID ExceptionHandler;
-  //int Version;
+  int Version;
   WCHAR *lc;
 
   hAppInstance = hInstance;
@@ -1024,9 +1024,9 @@ WinMain(HINSTANCE hInstance,
     return 1;
   }
 
-  //if(!DetectVMware(&Version))
+  if(!DetectVMware(&Version))
   {
-    //return 1;
+    return 1;
   }
 
   /* unregister the handler */
index 97d3bb0..95d2d2f 100644 (file)
@@ -499,6 +499,7 @@ Author:
 #define STATUS_ACCESS_VIOLATION                 0xC0000005
 #define STATUS_IN_PAGE_ERROR                    0xC0000006
 #define STATUS_GUARD_PAGE_VIOLATION             0x80000001
+#define STATUS_PRIVILEGED_INSTRUCTION           0xC0000096
 #define STATUS_STACK_OVERFLOW                   0xC00000FD
 #define KI_EXCEPTION_ACCESS_VIOLATION           0x10000004
 #define STATUS_INVALID_SYSTEM_SERVICE           0xC000001C
index bf01c0d..12890aa 100644 (file)
@@ -8,9 +8,6 @@
 //                     Do NOT ask when it will be fixed.
 //              Failure to respect this will *ACHIEVE NOTHING*.
 //
-// Ke1:
-//  - Implement Privileged Instruction Handler in Umode GPF.
-//
 // Ex:
 //  - Use pushlocks for handle implementation.
 //
index 10a4a2a..38d38d3 100644 (file)
@@ -238,15 +238,13 @@ DbgkCreateThread(PVOID StartAddress)
         if (Teb)
         {
             /* Copy the system library name and link to it */
-#if 0
             wcsncpy(Teb->StaticUnicodeBuffer,
                     L"ntdll.dll",
                     sizeof(Teb->StaticUnicodeBuffer) / sizeof(WCHAR));
-#endif
             Teb->Tib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer;
 
             /* Return it in the debug event as well */
-            LoadDll->NamePointer = Teb->Tib.ArbitraryUserPointer;
+            LoadDll->NamePointer = &Teb->Tib.ArbitraryUserPointer;
         }
 
         /* Get a handle */
index 6bdc068..bf99192 100644 (file)
@@ -221,13 +221,9 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message,
     PsGetCurrentProcess()->CreateReported = TRUE;
 
     /* Send the LPC command */
-#if 0
     Status = LpcRequestWaitReplyPort(Port,
                                      (PPORT_MESSAGE)Message,
                                      (PPORT_MESSAGE)&Buffer[0]);
-#else
-    Status = STATUS_UNSUCCESSFUL;
-#endif
 
     /* Flush the instruction cache */
     ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
@@ -486,6 +482,15 @@ DbgkpPostFakeModuleMessages(IN PEPROCESS Process,
     i = 0;
     while ((NextEntry != ListHead) && (i < 500))
     {
+        /* Skip the first entry */
+        if (!i)
+        {
+            /* Go to the next module */
+            NextEntry = NextEntry->Flink;
+            i++;
+            continue;
+        }
+
         /* Get the entry */
         LdrEntry = CONTAINING_RECORD(NextEntry,
                                      LDR_DATA_TABLE_ENTRY,
@@ -724,7 +729,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
         /* Get the next thread */
         ThisThread = PsGetNextProcessThread(Process, ThisThread);
         OldThread = pLastThread;
-    } while(ThisThread);
+    } while (ThisThread);
 
     /* Check the API status */
     if (!NT_SUCCESS(Status))
@@ -1075,7 +1080,7 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL,
               OwnerProcess, DebugObject);
 
     /* If this isn't the last handle, do nothing */
-    if (HandleCount > 1) return;
+    if (SystemHandleCount > 1) return;
 
     /* Otherwise, lock the debug object */
     ExAcquireFastMutex(&DebugObject->Mutex);
@@ -1293,8 +1298,12 @@ ThreadScan:
                 /* Check if we couldn't acquire rundown for it */
                 if (DebugEvent->Flags & 0x10)
                 {
-                    /* Set busy flag */
-                    InterlockedOr((PLONG)&DebugEvent->Flags, 0x100);
+                    /* Set the skip termination flag */
+                    PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
+
+                    /* Insert it into the temp list */
+                    RemoveEntryList(&DebugEvent->EventList);
+                    InsertTailList(&TempList, &DebugEvent->EventList);
                 }
                 else
                 {
@@ -1312,15 +1321,15 @@ ThreadScan:
                     /* Clear the backout thread */
                     DebugEvent->BackoutThread = NULL;
 
-                    /* Set flag */
-                    InterlockedOr((PLONG)&DebugEvent->Flags, 0x80);
+                    /* Set skip flag */
+                    PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
                 }
             }
             else
             {
-                /* FIXME: TODO */
-                DPRINT1("Unhandled dbgk path!\n");
-                KEBUGCHECK(0);
+                /* Insert it into the temp list */
+                RemoveEntryList(&DebugEvent->EventList);
+                InsertTailList(&TempList, &DebugEvent->EventList);
             }
 
             /* Check if the lock is held */
@@ -1346,11 +1355,14 @@ ThreadScan:
     if (LastThread) ObDereferenceObject(LastThread);
 
     /* Loop our temporary list */
-    NextEntry = TempList.Flink;
-    while (NextEntry != &TempList)
+    while (!IsListEmpty(&TempList))
     {
-        /* FIXME: TODO */
-        KEBUGCHECK(0);
+        /* Remove the event */
+        NextEntry = RemoveHeadList(&TempList);
+        DebugEvent = CONTAINING_RECORD (NextEntry, DEBUG_EVENT, EventList);
+
+        /* Wake it */
+        DbgkpWakeTarget(DebugEvent);
     }
 
     /* Check if we got here through success and mark the PEB, then return */
@@ -1520,9 +1532,8 @@ NtDebugContinue(IN HANDLE DebugHandle,
 
     /* Make sure that the status is valid */
     if ((ContinueStatus != DBG_CONTINUE) &&
+        (ContinueStatus != DBG_EXCEPTION_HANDLED) &&
         (ContinueStatus != DBG_EXCEPTION_NOT_HANDLED) &&
-        (ContinueStatus != DBG_REPLY_LATER) &&
-        (ContinueStatus != DBG_UNABLE_TO_PROVIDE_HANDLE) &&
         (ContinueStatus != DBG_TERMINATE_THREAD) &&
         (ContinueStatus != DBG_TERMINATE_PROCESS))
     {
@@ -1820,41 +1831,48 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
     DBGUI_WAIT_STATE_CHANGE WaitStateChange;
     NTSTATUS Status = STATUS_SUCCESS;
     PDEBUG_EVENT DebugEvent, DebugEvent2;
-    PLIST_ENTRY ListHead, NextEntry;
+    PLIST_ENTRY ListHead, NextEntry, NextEntry2;
     PAGED_CODE();
     DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
 
     /* Clear the initial wait state change structure */
     RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
 
-    /* Check if the call was from user mode */
-    if (PreviousMode != KernelMode)
+    /* Protect probe in SEH */
+    _SEH_TRY
     {
-        /* Protect probe in SEH */
-        _SEH_TRY
+        /* Check if we came with a timeout */
+        if (Timeout)
         {
-            /* Check if we came with a timeout */
-            if (Timeout)
+            /* Check if the call was from user mode */
+            if (PreviousMode != KernelMode)
             {
-                /* Make a copy on the stack */
-                SafeTimeOut = ProbeForReadLargeInteger(Timeout);
-                Timeout = &SafeTimeOut;
+                /* Probe it */
+                ProbeForReadLargeInteger(Timeout);
             }
 
-            /* Probe the state change structure */
-            ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
+            /* Make a local copy */
+            SafeTimeOut = *Timeout;
+            Timeout = &SafeTimeOut;
+
+            /* Query the current time */
+            KeQuerySystemTime(&StartTime);
         }
-        _SEH_HANDLE
+
+        /* Check if the call was from user mode */
+        if (PreviousMode != KernelMode)
         {
-            /* Get the exception code */
-            Status = _SEH_GetExceptionCode();
+            /* Probe the state change structure */
+            ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
         }
-        _SEH_END;
-        if (!NT_SUCCESS(Status)) return Status;
-
-        /* Query the current time */
-        KeQuerySystemTime(&StartTime);
     }
+    _SEH_HANDLE
+    {
+        /* Get the exception code */
+        Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    if (!NT_SUCCESS(Status)) return Status;
 
     /* Get the debug object */
     Status = ObReferenceObjectByHandle(DebugHandle,
@@ -1870,13 +1888,13 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
     Thread = NULL;
 
     /* Wait on the debug object given to us */
-    Status = KeWaitForSingleObject(DebugObject,
-                                   Executive,
-                                   PreviousMode,
-                                   Alertable,
-                                   Timeout);
     while (TRUE)
     {
+        Status = KeWaitForSingleObject(DebugObject,
+                                       Executive,
+                                       PreviousMode,
+                                       Alertable,
+                                       Timeout);
         if (!NT_SUCCESS(Status) ||
             (Status == STATUS_TIMEOUT) ||
             (Status == STATUS_ALERTED) ||
@@ -1917,10 +1935,11 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                     GotEvent = TRUE;
 
                     /* Loop the list internally */
-                    while (&DebugEvent->EventList != NextEntry)
+                    NextEntry2 = DebugObject->EventList.Flink;
+                    while (NextEntry2 != NextEntry)
                     {
                         /* Get the debug event */
-                        DebugEvent2 = CONTAINING_RECORD(NextEntry,
+                        DebugEvent2 = CONTAINING_RECORD(NextEntry2,
                                                         DEBUG_EVENT,
                                                         EventList);
 
@@ -1936,7 +1955,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                         }
 
                         /* Move to the next entry */
-                        NextEntry = NextEntry->Flink;
+                        NextEntry2 = NextEntry2->Flink;
                     }
 
                     /* Check if we still have a valid event */
@@ -1962,14 +1981,15 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
 
                 /* Set flag */
                 DebugEvent->Flags |= 1;
-                Status = STATUS_SUCCESS;
             }
             else
             {
                 /* Unsignal the event */
-                DebugObject->EventsPresent.Header.SignalState = 0;
-                Status = STATUS_SUCCESS;
+                KeClearEvent(&DebugObject->EventsPresent);
             }
+
+            /* Set success */
+            Status = STATUS_SUCCESS;
         }
 
         /* Release the mutex */
@@ -1980,13 +2000,22 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
         if (!GotEvent)
         {
             /* Check if we can wait again */
-            if (!SafeTimeOut.QuadPart)
+            if (SafeTimeOut.QuadPart < 0)
             {
                 /* Query the new time */
                 KeQuerySystemTime(&NewTime);
 
                 /* Substract times */
-                /* FIXME: TODO */
+                SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
+                StartTime = NewTime;
+
+                /* Check if we've timed out */
+                if (SafeTimeOut.QuadPart > 0)
+                {
+                    /* We have, break out of the loop */
+                    Status = STATUS_TIMEOUT;
+                    break;
+                }
             }
         }
         else
index 9ec54ba..174fc19 100644 (file)
@@ -93,6 +93,33 @@ _UnexpectedMsg:
 _UnhandledMsg:
     .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
 
+_KiTrapPrefixTable:
+    .byte 0xF2                      /* REP                                  */
+    .byte 0xF3                      /* REP INS/OUTS                         */
+    .byte 0x67                      /* ADDR                                 */
+    .byte 0xF0                      /* LOCK                                 */
+    .byte 0x66                      /* OP                                   */
+    .byte 0x2E                      /* SEG                                  */
+    .byte 0x3E                      /* DS                                   */
+    .byte 0x26                      /* ES                                   */
+    .byte 0x64                      /* FS                                   */
+    .byte 0x65                      /* GS                                   */
+    .byte 0x36                      /* SS                                   */
+
+_KiTrapIoTable:
+    .byte 0xE4                      /* IN                                   */
+    .byte 0xE5                      /* IN                                   */
+    .byte 0xEC                      /* IN                                   */
+    .byte 0xED                      /* IN                                   */
+    .byte 0x6C                      /* INS                                  */
+    .byte 0x6D                      /* INS                                  */
+    .byte 0xE6                      /* OUT                                  */
+    .byte 0xE7                      /* OUT                                  */
+    .byte 0xEE                      /* OUT                                  */
+    .byte 0xEF                      /* OUT                                  */
+    .byte 0x6E                      /* OUTS                                 */
+    .byte 0x6F                      /* OUTS                                 */
+
 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
 .text
 
@@ -1426,6 +1453,29 @@ _KiTrap12:
     jmp _KiSystemFatalException
 .endfunc
 
+.func KiTrapExceptHandler
+_KiTrapExceptHandler:
+
+    /* Setup SEH handler frame */
+    mov esp, [esp+8]
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 4
+    pop ebp
+
+    /* Check if the fault came from user mode */
+    test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jnz SetException
+
+    /* Kernel fault, bugcheck */
+    push ebp
+    push 0
+    push 0
+    push 0
+    push 0
+    push KMODE_EXCEPTION_NOT_HANDLED
+    call _KeBugCheckWithTf@24
+.endfunc
+
 .func KiTrap13
 Dr_kitd:    DR_TRAP_FIXUP
 V86_kitd:   V86_TRAP_FIXUP
@@ -1630,6 +1680,7 @@ SegPopGpf:
     lea eax, [ebp+KTRAP_FRAME_ESP]
     cmp edx, eax
     jz HandleSegPop
+    int 3
 
     /* Handle segment POP fault by setting it to 0 */
 HandleSegPop:
@@ -1668,7 +1719,7 @@ HandleSegPop2:
     /* Update EIP (will be updated below again) */
     add dword ptr [ebp+KTRAP_FRAME_EIP], 1
 
-HandleBop4:
+HandleEsPop:
     /* Clear the segment, update EIP and ESP */
     mov dword ptr [edx], 0
     add dword ptr [ebp+KTRAP_FRAME_EIP], 1
@@ -1680,15 +1731,23 @@ CheckVdmGpf:
     cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
     jz CheckPrivilegedInstruction
 
+    /* Bring interrupts back */
+    sti
+
     /* Check what kind of instruction this is */
     mov eax, [ebp+KTRAP_FRAME_EIP]
     mov eax, [eax]
 
     /* FIXME: Check for BOP4 */
 
-    /* Check if this is POP FS */
+    /* Check if this is POP ES */
     mov edx, ebp
-    add edx, KTRAP_FRAME_FS
+    add edx, KTRAP_FRAME_ES
+    cmp al, 0x07
+    jz HandleEsPop
+
+    /* Check if this is POP FS */
+    add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
     cmp ax, 0xA10F
     jz HandleSegPop2
 
@@ -1698,16 +1757,102 @@ CheckVdmGpf:
     jz HandleSegPop2
 
 CheckPrivilegedInstruction:
+    /* Bring interrupts back */
+    sti
+
+    /* Setup a SEH handler */
+    push ebp
+    push offset _KiTrapExceptHandler
+    push fs:[KPCR_EXCEPTION_LIST]
+    mov fs:[KPCR_EXCEPTION_LIST], esp
+
+    /* Get EIP */
+    mov esi, [ebp+KTRAP_FRAME_EIP]
+
+    /* Setup loop count */
+    mov ecx, 15
+
+InstLoop:
+    /* Save loop count */
+    push ecx
+
+    /* Get the instruction */
+    lods byte ptr [esi]
+
+    /* Now lookup in the prefix table */
+    mov ecx, 11
+    mov edi, offset _KiTrapPrefixTable
+    repnz scasb
+
+    /* Restore loop count */
+    pop ecx
+
+    /* If it's not a prefix byte, check other instructions */
+    jnz NotPrefixByte
+
     /* FIXME */
     UNHANDLED_PATH
 
-CheckPrivilegedInstruction2:
+NotPrefixByte:
+    /* FIXME: Check if it's a HLT */
+
+    /* Check if the instruction has two bytes */
+    cmp al, 0xF
+    jne CheckRing3Io
+
     /* FIXME */
     UNHANDLED_PATH
 
+CheckRing3Io:
+    /* Get EFLAGS and IOPL */
+    mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
+    and ebx, 0x3000
+    shr ebx, 12
+
+    /* Check the CS's RPL mask */
+    mov ecx, [ebp+KTRAP_FRAME_CS]
+    and ecx, RPL_MASK
+    cmp ebx, ecx
+    jge NotIoViolation
+
+CheckPrivilegedInstruction2:
+    /* Check if this is a CLI or STI */
+    cmp al, 0xFA
+    je IsPrivInstruction
+    cmp al, 0xFB
+    je IsPrivInstruction
+
+    /* Setup I/O table lookup */
+    mov ecx, 13
+    mov edi, offset _KiTrapIoTable
+
+    /* Loopup in the table */
+    repnz scasb
+    jnz NotIoViolation
+
+    /* FIXME: Check IOPM!!! */
+
+IsPrivInstruction:
+    /* Cleanup the SEH frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
+    /* Setup the exception */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov eax, STATUS_PRIVILEGED_INSTRUCTION
+    jmp _DispatchNoParam
+
+NotIoViolation:
+    /* Cleanup the SEH frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
 SetException:
-    /* FIXME */
-    UNHANDLED_PATH
+    /* Setup the exception */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov esi, -1
+    mov eax, STATUS_ACCESS_VIOLATION
+    jmp _DispatchTwoParam
 
 DispatchV86Gpf:
     /* FIXME */
index 62a0ff7..95d4071 100644 (file)
@@ -57,7 +57,7 @@ LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
     PETHREAD Thread = NULL;
     BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2;
     PAGED_CODE();
-    LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
+    DPRINT1("Message: %p. Flags: %lx\n", Message, Flags);
 
     /* Acquire the lock if not already */
     if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
@@ -342,6 +342,9 @@ LpcpDeletePort(IN PVOID ObjectBody)
         /* Send it */
         for (;;)
         {
+            /* FIXME: HACK OF D00m */
+            break;
+
             /* Send the message */
             if (LpcRequestPort(Port,
                                &ClientDiedMsg.h) != STATUS_NO_MEMORY) break;
index 92bcb4d..0cba490 100644 (file)
@@ -18,7 +18,7 @@ POBJECT_TYPE LpcPortObjectType;
 ULONG LpcpMaxMessageSize;
 PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
 KGUARDED_MUTEX LpcpLock;
-ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
+ULONG LpcpTraceLevel = 0;
 ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
 
 static GENERIC_MAPPING LpcpPortMapping =