- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errat...
[reactos.git] / reactos / ntoskrnl / ke / i386 / trap.s
index d438650..c8458c3 100644 (file)
@@ -132,7 +132,6 @@ _KiTrapIoTable:
 
 _KiGetTickCount:
 _KiCallbackReturn:
-_KiRaiseAssertion:
     /* FIXME: TODO */
     UNHANDLED_PATH
 
@@ -200,7 +199,7 @@ NotWin32K:
     /* Increase total syscall count */
     inc dword ptr PCR[KPCR_SYSTEM_CALLS]
 
-#ifdef DBG
+#if DBG
     /* Increase per-syscall count */
     mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
     jecxz NoCountTable
@@ -239,7 +238,7 @@ CopyParams:
     call ebx
 
 AfterSysCall:
-#ifdef DBG
+#if DBG
     /* Make sure the user-mode call didn't return at elevated IRQL */
     test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
     jz SkipCheck
@@ -377,7 +376,7 @@ BadStack:
     push 0
     jmp _KiTrap6
 
-#ifdef DBG
+#if DBG
 InvalidIrql:
     /* Save current IRQL */
     push PCR[KPCR_IRQL]
@@ -461,6 +460,29 @@ AbiosExit:
     /* FIXME: TODO */
     UNHANDLED_PATH
 
+.func KiRaiseAssertion
+TRAP_FIXUPS kira_a, kira_t, DoFixupV86, DoFixupAbios
+_KiRaiseAssertion:
+
+    /* Push error code */
+    push 0
+
+    /* Enter trap */
+    TRAP_PROLOG kira_a, kira_t
+
+    /*
+     * Modify EIP so it points to the faulting instruction and set it as the
+     * exception address. Note that the 'int 2C' instruction used for this call
+     * is 2 bytes long as opposed to 1 byte 'int 3'.
+     */
+    sub dword ptr [ebp+KTRAP_FRAME_EIP], 2
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+
+    /* Raise an assertion failure */
+    mov eax, STATUS_ASSERTION_FAILURE
+    jmp _DispatchNoParam
+.endfunc
+
 .func KiDebugService
 TRAP_FIXUPS kids_a, kids_t, DoFixupV86, DoFixupAbios
 _KiDebugService:
@@ -780,8 +802,11 @@ _KiTrap3:
     /* Enter trap */
     TRAP_PROLOG kit3_a, kit3_t
 
-    /* Set status code */
-    mov eax, 0 //STATUS_SUCCESS
+    /*
+     * Set the special code to indicate that this is a software breakpoint
+     * and not a debug service call
+     */
+    mov eax, BREAKPOINT_BREAK
 
     /* Check for V86 */
 PrepareInt3:
@@ -922,6 +947,7 @@ _KiTrap6:
     /* Enter V86 Trap */
     V86_TRAP_PROLOG kit6_a, kit6_v
 
+VdmOpCodeFault:
     /* Not yet supported (Invalid OPCODE from V86) */
     UNHANDLED_PATH
 
@@ -932,6 +958,7 @@ NotV86UD:
     /* Enter trap */
     TRAP_PROLOG kit6_a, kit6_t
 
+DispatchLockErrata:
     /* Check if this happened in kernel mode */
     test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
     jz KmodeOpcode
@@ -1338,7 +1365,6 @@ BogusTrap:
 .globl _KiTrap8
 .func KiTrap8
 _KiTrap8:
-
     /* Can't really do too much */
     mov eax, 8
     jmp _KiSystemFatalException
@@ -1511,6 +1537,7 @@ NotV86:
     cmp eax, offset CheckPrivilegedInstruction
     jbe KmodeGpf
     cmp eax, offset CheckPrivilegedInstruction2
+    jae KmodeGpf
 
     /* FIXME: TODO */
     UNHANDLED_PATH
@@ -1924,14 +1951,21 @@ _KiTrap14:
 NoFixUp:
     mov edi, cr2
 
-    /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
+    /* Check if this processor has the cmpxchg8b lock errata */
+    cmp byte ptr _KiI386PentiumLockErrataPresent, 0
+    jnz HandleLockErrata
+
+NotLockErrata:
+    /* HACK: Handle page faults with interrupts disabled */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
     je HandlePf
 
     /* Enable interrupts and check if we got here with interrupts disabled */
     sti
+#ifdef HACK_ABOVE_FIXED
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
     jz IllegalState
+#endif
 
 HandlePf:
     /* Send trap frame and check if this is kernel-mode or usermode */
@@ -2050,6 +2084,33 @@ VdmAlertGpf:
 
     /* FIXME: NOT SUPPORTED */
     UNHANDLED_PATH
+
+HandleLockErrata:
+
+    /* Fail if this isn't a write fault */
+    test word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0x4
+    jnz NotLockErrata
+
+    /* Also make sure the page fault is for IDT entry 6 */
+    mov eax, PCR[KPCR_IDT]
+    add eax, 0x30
+    cmp eax, edi
+    jne NotLockErrata
+
+    /*
+     * This is a write fault to the Invalid Opcode handler entry.
+     * We assume this is the lock errata and not a real write fault.
+     */
+
+    /* Clear the error code */
+    and dword ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
+
+    /* Check if this happened in V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+    jnz VdmOpCodeFault
+
+    /* Dispatch this to the invalid opcode handler */
+    jmp DispatchLockErrata
 .endfunc
 
 .func KiTrap0F
@@ -2533,8 +2594,81 @@ TRAP_FIXUPS kit_a, kit_t, DoFixupV86, DoFixupAbios
 .func KiChainedDispatch2ndLvl@0
 _KiChainedDispatch2ndLvl@0:
 
-    /* Not yet supported */
-    UNHANDLED_PATH
+NextSharedInt:
+    /* Raise IRQL if necessary */
+    mov cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
+    cmp cl, [edi+KINTERRUPT_IRQL]
+    je 1f
+    call @KfRaiseIrql@4
+
+1:
+    /* Acquire the lock */
+    mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
+GetIntLock2:
+    ACQUIRE_SPINLOCK(esi, IntSpin2)
+
+    /* Make sure that this interrupt isn't storming */
+    VERIFY_INT kid2
+
+    /* Save the tick count */
+    mov esi, _KeTickCount
+
+    /* Call the ISR */
+    mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
+    push eax
+    push edi
+    call [edi+KINTERRUPT_SERVICE_ROUTINE]
+
+    /* Save the ISR result */
+    mov bl, al
+
+    /* Check if the ISR timed out */
+    add esi, _KiISRTimeout
+    cmp _KeTickCount, esi
+    jnc ChainedIsrTimeout
+
+ReleaseLock2:
+    /* Release the lock */
+    mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
+    RELEASE_SPINLOCK(esi)
+
+    /* Lower IRQL if necessary */
+    mov cl, [edi+KINTERRUPT_IRQL]
+    cmp cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
+    je 1f
+    call @KfLowerIrql@4
+
+1:
+    /* Check if the interrupt is handled */
+    or bl, bl
+    jnz 1f
+
+    /* Try the next shared interrupt handler */
+    mov eax, [edi+KINTERRUPT_INTERRUPT_LIST_HEAD]
+    lea edi, [eax-KINTERRUPT_INTERRUPT_LIST_HEAD]
+    jmp NextSharedInt
+
+1:
+    ret
+
+#ifdef CONFIG_SMP
+IntSpin2:
+    SPIN_ON_LOCK(esi, GetIntLock2)
+#endif
+
+ChainedIsrTimeout:
+    /* Print warning message */
+    push [edi+KINTERRUPT_SERVICE_ROUTINE]
+    push offset _IsrTimeoutMsg
+    call _DbgPrint
+    add esp,8
+
+    /* Break into debugger, then continue */
+    int 3
+    jmp ReleaseLock2
+
+    /* Cleanup verification */
+    VERIFY_INT_END kid2, 0
 .endfunc
 
 .func KiChainedDispatch@0
@@ -2599,8 +2733,8 @@ _KiInterruptDispatch@0:
     jz SpuriousInt
 
     /* Acquire the lock */
-GetIntLock:
     mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
+GetIntLock:
     ACQUIRE_SPINLOCK(esi, IntSpin)
 
     /* Make sure that this interrupt isn't storming */
@@ -2663,12 +2797,26 @@ _KeSynchronizeExecution@12:
     /* Go to DIRQL */
     mov cl, [ebx+KINTERRUPT_SYNCHRONIZE_IRQL]
     call @KfRaiseIrql@4
+    push eax
+
+#ifdef CONFIG_SMP
+    /* Acquire the interrupt spinlock FIXME: Write this in assembly */
+    mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
+    call @KefAcquireSpinLockAtDpcLevel@4
+#endif
 
     /* Call the routine */
-    push eax
     push [esp+20]
     call [esp+20]
 
+#ifdef CONFIG_SMP
+    /* Release the interrupt spinlock FIXME: Write this in assembly */
+    push eax
+    mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
+    call @KefReleaseSpinLockFromDpcLevel@4
+    pop eax
+#endif
+
     /* Lower IRQL */
     mov ebx, eax
     pop ecx
@@ -2679,3 +2827,32 @@ _KeSynchronizeExecution@12:
     pop ebx
     ret 12
 .endfunc
+
+/*++
+ * Kii386SpinOnSpinLock 
+ *
+ *     FILLMEIN
+ *
+ * Params:
+ *     SpinLock - FILLMEIN
+ *
+ *     Flags - FILLMEIN
+ *
+ * Returns:
+ *     None.
+ *
+ * Remarks:
+ *     FILLMEIN
+ *
+ *--*/
+.globl _Kii386SpinOnSpinLock@8
+.func Kii386SpinOnSpinLock@8
+_Kii386SpinOnSpinLock@8:
+
+#ifdef CONFIG_SMP
+    /* FIXME: TODO */
+    int 3
+#endif
+
+    ret 8
+.endfunc