- In Win32 DBG is defined to 0 for a non-debug build and to 1 for a debug build....
[reactos.git] / reactos / ntoskrnl / ke / i386 / trap.s
index 0844fdb..594a8f4 100644 (file)
@@ -80,7 +80,8 @@ GENERATE_IDT_STUBS                  /* INT 30-FF: UNEXPECTED INTERRUPTS     */
 
 .globl _KiIdtDescriptor
 _KiIdtDescriptor:
-    .short 0x800
+    .short 0
+    .short 0x7FF
     .long _KiIdt
 
 .globl _KiUnexpectedEntrySize
@@ -191,7 +192,7 @@ ReadBatch:
     /* Flush it */
     push edx
     push eax
-    //call [_KeGdiFlushUserBatch]
+    call [_KeGdiFlushUserBatch]
     pop eax
     pop edx
 
@@ -199,7 +200,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
@@ -238,7 +239,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
@@ -376,7 +377,7 @@ BadStack:
     push 0
     jmp _KiTrap6
 
-#ifdef DBG
+#if DBG
 InvalidIrql:
     /* Save current IRQL */
     push PCR[KPCR_IRQL]
@@ -645,18 +646,25 @@ _DispatchNoParam:
     call _CommonDispatchException
 .endfunc
 
-.func DispatchOneParam
-_DispatchOneParam:
+.func DispatchOneParamZero
+_DispatchOneParamZero:
     /* Call the common dispatcher */
     xor edx, edx
     mov ecx, 1
     call _CommonDispatchException
 .endfunc
 
+.func DispatchTwoParamZero
+_DispatchTwoParamZero:
+    /* Call the common dispatcher */
+    xor edx, edx
+    mov ecx, 2
+    call _CommonDispatchException
+.endfunc
+
 .func DispatchTwoParam
 _DispatchTwoParam:
     /* Call the common dispatcher */
-    xor edx, edx
     mov ecx, 2
     call _CommonDispatchException
 .endfunc
@@ -1033,7 +1041,7 @@ StartTrapHandle:
     sub ecx, NPX_FRAME_LENGTH
 
     /* Check if emulation is enabled */
-    test dword ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
+    test byte ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
     jnz EmulationEnabled
 
 CheckState:
@@ -1223,13 +1231,13 @@ CheckError:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_INVALID_OPERATION
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 InvalidStack:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_STACK_CHECK
-    jmp _DispatchTwoParam
+    jmp _DispatchTwoParamZero
 
 ValidNpxOpcode:
 
@@ -1239,7 +1247,7 @@ ValidNpxOpcode:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 1:
     /* Check for denormal */
@@ -1248,7 +1256,7 @@ ValidNpxOpcode:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_INVALID_OPERATION
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 1:
     /* Check for overflow */
@@ -1257,7 +1265,7 @@ ValidNpxOpcode:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_OVERFLOW
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 1:
     /* Check for underflow */
@@ -1266,7 +1274,7 @@ ValidNpxOpcode:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_UNDERFLOW
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 1:
     /* Check for precision fault */
@@ -1275,7 +1283,7 @@ ValidNpxOpcode:
 
     /* Raise exception */
     mov eax, STATUS_FLOAT_INEXACT_RESULT
-    jmp _DispatchOneParam
+    jmp _DispatchOneParamZero
 
 UnexpectedNpx:
 
@@ -1445,10 +1453,7 @@ _KiTrap13:
 
     /* Otherwise, something is very wrong, raise an exception */
     sti
-    mov ebx, [ebp+KTRAP_FRAME_EIP]
-    mov esi, -1
-    mov eax, STATUS_ACCESS_VIOLATION
-    jmp _DispatchTwoParam
+    jmp SetException
 
 RaiseIrql:
 
@@ -1492,7 +1497,7 @@ NotV86Trap:
 NotV86:
     /* Enter trap */
     TRAP_PROLOG kitd_a, kitd_t
-
+    
     /* Check if this was from kernel-mode */
     test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
     jnz UserModeGpf
@@ -1592,7 +1597,7 @@ TrapCopy:
     mov esi, [ebp+KTRAP_FRAME_ERROR_CODE]
     and esi, 0xFFFF
     mov eax, STATUS_ACCESS_VIOLATION
-    jmp _DispatchTwoParam
+    jmp _DispatchTwoParamZero
 
 MsrCheck:
 
@@ -1738,24 +1743,100 @@ InstLoop:
 
     /* If it's not a prefix byte, check other instructions */
     jnz NotPrefixByte
+    
+    /* Keep looping */
+    loop InstLoop
+    
+    /* Fixup the stack */
+    pop PCR[KPCR_EXCEPTION_LIST]
+    add esp, 8
 
-    /* FIXME */
-    UNHANDLED_PATH
+    /* Illegal instruction */
+    jmp KmodeOpcode
 
 NotPrefixByte:
-    /* FIXME: Check if it's a HLT */
+    /* Check if it's a HLT */
+    cmp al, 0x0F4
+    je IsPrivInstruction
 
     /* Check if the instruction has two bytes */
     cmp al, 0xF
     jne CheckRing3Io
-
-    /* FIXME */
-    UNHANDLED_PATH
+    
+    /* Check if this is a LLDT or LTR */
+    lods byte ptr [esi]
+    cmp al, 0
+    jne NotLldt
+    
+    /* Check if this is an LLDT */
+    lods byte ptr [esi]
+    and al, 0x38
+    cmp al, 0x10
+    je IsPrivInstruction
+    
+    /* Check if this is an LTR */
+    cmp al, 0x18
+    je IsPrivInstruction
+    
+    /* Otherwise, access violation */
+    jmp NotIoViolation
+    
+NotLldt:
+    /* Check if this is LGDT or LIDT or LMSW */
+    cmp al, 0x01
+    jne NotGdt
+    
+    /* Check if this is an LGDT */
+    lods byte ptr [esi]
+    and al, 0x38
+    cmp al, 0x10
+    je IsPrivInstruction
+    
+    /* Check if this is an LIDT */
+    cmp al, 0x18
+    je IsPrivInstruction
+    
+    /* Check if this is an LMSW */
+    cmp al, 0x30
+    je IsPrivInstruction
+    
+    /* Otherwise, access violation */
+    jmp NotIoViolation
+    
+NotGdt:
+    /* Check if it's INVD or WBINVD */
+    cmp al, 0x8
+    je IsPrivInstruction
+    cmp al, 0x9
+    je IsPrivInstruction
+    
+    /* Check if it's sysexit */
+    cmp al, 0x35
+    je IsPrivInstruction
+    
+    /* Check if it's a DR move */
+    cmp al, 0x26
+    je IsPrivInstruction
+    
+    /* Check if it's a CLTS */
+    cmp al, 0x6
+    je IsPrivInstruction
+    
+    /* Check if it's a CR move */
+    cmp al, 0x20
+    jb NotIoViolation
+    
+    /* Check if it's a DR move */
+    cmp al, 0x24
+    jbe IsPrivInstruction
+    
+    /* Everything else is an access violation */
+    jmp NotIoViolation
 
 CheckRing3Io:
     /* Get EFLAGS and IOPL */
     mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
-    and ebx, 0x3000
+    and ebx, EFLAGS_IOPL
     shr ebx, 12
 
     /* Check the CS's RPL mask */
@@ -1801,7 +1882,7 @@ SetException:
     mov ebx, [ebp+KTRAP_FRAME_EIP]
     mov esi, -1
     mov eax, STATUS_ACCESS_VIOLATION
-    jmp _DispatchTwoParam
+    jmp _DispatchTwoParamZero
 
 DispatchV86Gpf:
     /* FIXME */
@@ -1843,14 +1924,14 @@ _KiTrap14:
 NoFixUp:
     mov edi, cr2
 
-    /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
+    /* REACTOS Mm Hack of Doom */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
     je HandlePf
 
     /* Enable interrupts and check if we got here with interrupts disabled */
     sti
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
-    jz IllegalState
+    /* test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
+    jz IllegalState */
 
 HandlePf:
     /* Send trap frame and check if this is kernel-mode or usermode */
@@ -1899,8 +1980,8 @@ SysCallCopyFault:
     /* Check if the fault occured in a V86 mode */
 CheckVdmPf:
     mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
-    and ecx, 1
     shr ecx, 1
+    and ecx, 1
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
     jnz VdmPF
 
@@ -2026,6 +2107,180 @@ _KiTrap17:
     jmp _KiSystemFatalException
 .endfunc
 
+.globl _KiTrap19
+.func KiTrap19
+TRAP_FIXUPS kit19_a, kit19_t, DoFixupV86, DoNotFixupAbios
+_KiTrap19:
+    /* Push error code */
+    push 0
+
+    /* Enter trap */
+    TRAP_PROLOG kit19_a, kit19_t
+
+    /* Check if this is the NPX Thread */
+    mov eax, PCR[KPCR_CURRENT_THREAD]
+    cmp eax, PCR[KPCR_NPX_THREAD]
+
+    /* If this is a valid fault, handle it */
+    jz HandleXmmiFault
+
+    /* Otherwise, bugcheck */
+    mov eax, 19
+    jmp _KiSystemFatalException
+
+HandleXmmiFault:
+    /* Get the initial stack and NPX frame */
+    mov ecx, [eax+KTHREAD_INITIAL_STACK]
+    lea ecx, [ecx-NPX_FRAME_LENGTH]
+
+    /* Check if the trap came from V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+    jnz V86Xmmi
+
+    /* Check if it came from kernel mode */
+    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jz KernelXmmi
+
+    /* Check if it came from a VDM */
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+    jne VdmXmmi
+
+HandleUserXmmi:
+    /* Set new CR0 */
+    mov ebx, cr0
+    and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
+    mov cr0, ebx
+
+    /* Check if we have FX support */
+    test byte ptr _KeI386FxsrPresent, 1
+    jz XmmiFnSave2
+
+    /* Save the state */
+    fxsave [ecx]
+    jmp XmmiMakeCr0Dirty
+XmmiFnSave2:
+    fnsave [ecx]
+    wait
+
+XmmiMakeCr0Dirty:
+    /* Make CR0 state not loaded */
+    or ebx, NPX_STATE_NOT_LOADED
+    or ebx, [ecx+FN_CR0_NPX_STATE]
+    mov cr0, ebx
+
+    /* Update NPX state */
+    mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
+    mov dword ptr PCR[KPCR_NPX_THREAD], 0
+
+    /* Clear the TS bit and re-enable interrupts */
+    and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
+
+    /* Re-enable interrupts for user-mode and send the exception */
+    sti
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+
+    /* Get MxCSR and get current mask (bits 7-12) */
+    movzx eax, word ptr [ecx+FX_MXCSR]
+    mov edx, eax
+    shr edx, 7
+    not edx
+
+    /* Set faulting opcode address to 0 */
+    mov esi, 0
+
+    /* Apply legal exceptions mask */
+    and eax, 0x3f
+
+    /* Apply the mask we got in MXCSR itself */
+    and eax, edx
+
+    /* Check for invalid operation */
+    test al, 1
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
+    jmp _DispatchOneParamZero
+
+1:
+    /* Check for zero divide */
+    test al, 2
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
+    jmp _DispatchOneParamZero
+
+1:
+    /* Check for denormal */
+    test al, 4
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
+    jmp _DispatchOneParamZero
+
+1:
+    /* Check for overflow*/
+    test al, 8
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
+    jmp _DispatchOneParamZero
+
+1:
+    /* Check for denormal */
+    test al, 16
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
+    jmp _DispatchOneParamZero
+
+1:
+    /* Check for Precision */
+    test al, 32
+    jz UnexpectedXmmi
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
+    jmp _DispatchOneParamZero
+
+UnexpectedXmmi:
+    /* Strange result, bugcheck the OS */
+    sti
+    push ebp
+    push 1
+    push 0
+    push eax
+    push 13
+    push TRAP_CAUSE_UNKNOWN
+    call _KeBugCheckWithTf@24
+
+VdmXmmi:
+    /* Check if this is a VDM */
+    mov eax, PCR[KPCR_CURRENT_THREAD]
+    mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
+    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+    jz HandleUserXmmi
+
+V86Xmmi:
+    /* V86 XMMI not handled */
+    UNHANDLED_PATH
+
+KernelXmmi:
+    /* Another weird situation */
+    push ebp
+    push 2
+    push 0
+    push eax
+    push 13
+    push TRAP_CAUSE_UNKNOWN
+    call _KeBugCheckWithTf@24
+.endfunc
+
+
 .func KiSystemFatalException
 _KiSystemFatalException:
 
@@ -2200,16 +2455,27 @@ CheckQuantum:
     mov edi, [ebx+KPCR_CURRENT_THREAD]
 
 #ifdef CONFIG_SMP
-    #error SMP Interrupt not handled!
+    /* Raise to synch level */
+    call _KeRaiseIrqlToSynchLevel@0
+
+    /* Set context swap busy */
+    mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
+
+    /* Acquire the PRCB Lock */
+    lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
+    jnb GetNext
+    lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
+    call @KefAcquireSpinLockAtDpcLevel@4
 #endif
 
+GetNext:
     /* Get the next thread and clear it */
     mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
     and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
 
     /* Set us as the current running thread */
     mov [ebx+KPCR_CURRENT_THREAD], esi
-    mov byte ptr [esi+KTHREAD_STATE], Running
+    mov byte ptr [esi+KTHREAD_STATE_], Running
     mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
 
     /* Put thread in ECX and get the PRCB in EDX */
@@ -2221,6 +2487,12 @@ CheckQuantum:
     mov cl, APC_LEVEL
     call @KiSwapContextInternal@0
 
+#ifdef CONFIG_SMP
+    /* Lower IRQL back to dispatch */
+    mov cl, DISPATCH_LEVEL
+    call @KfLowerIrql@4
+#endif
+
     /* Restore registers */
     mov ebp, [esp+0]
     mov edi, [esp+4]
@@ -2261,8 +2533,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
@@ -2327,8 +2672,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 */
@@ -2362,7 +2707,7 @@ SpuriousInt:
 
 #ifdef CONFIG_SMP
 IntSpin:
-    SPIN_ON_LOCK esi, GetIntLock
+    SPIN_ON_LOCK(esi, GetIntLock)
 #endif
 
 IsrTimeout: