- Correctly zero out esi. Thanks to Patrick Baggett.
[reactos.git] / reactos / ntoskrnl / ke / i386 / ctxswitch.S
index d24520d..f8de2f0 100644 (file)
@@ -5,17 +5,14 @@
  * PURPOSE:         Thread Context Switching
  * 
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  Gregor Anich (FPU Code)
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <roscfg.h>
-#include <internal/i386/segment.h>
 #include <internal/i386/ke.h>
-#include <internal/i386/fpu.h>
-#include <internal/ps.h>
-#include <ntos/tss.h>
-#include <internal/ntoskrnl.h>
+#include <ndk/asm.h>
 .intel_syntax noprefix
 
 #define Running 2 
@@ -63,7 +60,7 @@ _KiThreadStartup@156:
      * expect any static data (like some badly coded usermode/win9x apps do)
      */
     xor ebx, ebx
-    xor esi, edi
+    xor esi, esi
     xor edi, edi
     xor ebp, ebp
     
@@ -125,45 +122,66 @@ SaveTrapFrameForKDB_Return:
     
     /* Set the Thread to running */
     mov byte ptr [esi+KTHREAD_STATE], Running
-    
+
     /* Save the Exception list */
     push [ebx+KPCR_EXCEPTION_LIST]
     
     /* Switching, disable interrupts now */
     cli
-    
+
+    /* Save the initial stack in EAX */
+    mov eax, [edi+KTHREAD_INITIAL_STACK]
+
 #ifdef CONFIG_SMP
     /* Save FPU state if the thread has used it. */
-    mov [ebx+KPCR_NPX_THREAD], 0
+    mov dword ptr [ebx+KPCR_NPX_THREAD], 0
     test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
     jz 3f
-    mov eax, [edi+KTHREAD_INITIAL_STACK]
-    cmp _FxsrSupport, 0
+    cmp dword ptr _FxsrSupport, 0
     je 1f
     fxsave [eax-SIZEOF_FX_SAVE_AREA]
     jmp 2f
 1:
     fnsave [eax-SIZEOF_FX_SAVE_AREA]
 2:
-    mov byte ptr [edi+KTHREAD_INITIAL_STACK], NPX_STATE_VALID
+    mov byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_VALID
 3:
 #endif /* CONFIG_SMP */
     
     /* Save the stack pointer in this processors TSS */
     mov ebp, [ebx+KPCR_TSS]
+
+    /* Check if this isn't V86 Mode, so we can bias the Esp0 */
+    test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz NoAdjust
+
+    /* Bias esp */
+    //sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+
+NoAdjust:
+    /* Push ESP0 Value */
     push ss:[ebp+KTSS_ESP0]
 
+    /* Check if address space switch is needed */
+    mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
+    cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
+    mov eax, [eax+KPROCESS_DIRECTORY_TABLE_BASE]
+
     /* Switch stacks */
     mov [edi+KTHREAD_KERNEL_STACK], esp
     mov esp, [esi+KTHREAD_KERNEL_STACK]
+    
+    jz NoAddressSpaceSwitch
+    
+    /* Switch address space */
+    mov cr3, eax
+   
+NoAddressSpaceSwitch:   
    
     /* Stack is OK, safe to enable interrupts now */
     sti 
-    
-    /* Check if address space switch is needed */
-    mov eax, [edi+KTHREAD_APCSTATE_PROCESS]
-    cmp eax, [esi+KTHREAD_APCSTATE_PROCESS]
-    
+
+    /* Check if address space switch is needed (the result from above is valid) */
     /* If they match, then use the fast-path and skip all this */
     jz SameProcess
     
@@ -178,12 +196,12 @@ SaveTrapFrameForKDB_Return:
     /* Write the LDT Selector */
     mov ebp, [ebx+KPCR_GDT]
     mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0]
-    mov [ebp+LDT_SELECTOR], eax
+    mov [ebp+KGDT_LDT], eax
     mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1]
-    mov [ebp+LDT_SELECTOR+4], eax
+    mov [ebp+KGDT_LDT+4], eax
     
     /* Save LDT Selector */
-    mov eax, LDT_SELECTOR
+    mov eax, KGDT_LDT
         
 NoLdt:
     
@@ -195,10 +213,6 @@ NoLdt:
 
     /* Set current IOPM offset in the TSS */
     mov [ebp+KTSS_IOMAPBASE], cx
-
-    /* Change the address space */
-    mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE]
-    mov cr3, eax
     
 SameProcess:
     
@@ -281,8 +295,8 @@ SameProcess:
     
     /* Return the registers */
     mov ebp, [esp+0]
-    mov esi, [esp+4]
-    mov edi, [esp+8]
+    mov edi, [esp+4]
+    mov esi, [esp+8]
     mov ebx, [esp+12]
     
     /* Clean stack */
@@ -293,32 +307,55 @@ SameProcess:
 
 SaveTrapFrameForKDB:
     /* Set up a trap frame */
-    
-    /* Fake Interrupt Stack */
-    push esp                                     // 0x74
     pushf                                        // 0x70
     push cs                                      // 0x6C
-    push [esp+12]    /* EIP */                   // 0x68
-    mov [esp+16], ss                             // 0x78
-    
-    /* Trap Frame */
-    push 0           /* Error Code */            // 0x64
+    push 0             /* Error Code */          // 0x64
     push ebp                                     // 0x60
     push ebx
+    
+    /* Fake Interrupt Stack */
+    mov ebp, [esp+20]  /* Eip */
+    mov ebx, [esp+16]  /* Eflags */
+    mov [esp+20], ebx
+    mov ebx, [esp+12]  /* Cs */
+    mov [esp+16], ebx
+    mov [esp+12], ebp
+    
     push esi
     push edi
     push fs
-    push -1          /* Exception List */        // 0x4C
-    push 0           /* Previous Mode */         // 0x48
+    push -1            /* Exception List */      // 0x4C
+    push 0             /* Previous Mode */       // 0x48
     push eax
     push ecx
     push edx
     push ds
     push es
     push gs                                      // 0x30
-    sub esp, 0x28    /* Debug Registers */       // 0x8
-    push [esp+60]    /* Debug EIP */             // 0x4
-    push ebp         /* Debug EBP */             // 0x0
+
+    mov eax, dr7
+    push eax           /* Dr7 */
+    /* Clear breakpoint enables in dr7. */
+    and eax, 0xffff0000
+    mov dr7, eax
+    mov eax, dr6
+    push eax           /* Dr6 */
+    mov eax, dr3
+    push eax           /* Dr3 */
+    mov eax, dr2
+    push eax           /* Dr2 */
+    mov eax, dr1
+    push eax           /* Dr1 */
+    mov eax, dr0
+    push eax           /* Dr0 */
+        
+    lea eax, [esp+0x58]
+    push eax           /* TempEsp */
+    push ss            /* TempSegSs */
+    push 0             /* DebugPointer */
+    push -1            /* DebugArgMark */
+    push [esp+60]      /* Debug EIP */           // 0x4
+    push ebp           /* Debug EBP */           // 0x0
     
     /* Set Stack */
     mov ebp, esp
@@ -329,19 +366,21 @@ SaveTrapFrameForKDB:
     /* Save new one */
     mov [edi+KTHREAD_TRAP_FRAME], ebp
     
+    /* Restore EBP, EBX and EAX */
+    mov ebp, [ebp+KTRAP_FRAME_EBP]
+    mov ebx, [ebp+KTRAP_FRAME_EBX]
+    mov eax, [ebp+KTRAP_FRAME_EAX]
+    
     /* Return EIP */
     push offset RestoreTrapFrameForKDB
         
-    /* Restore EBP */
-    mov ebp, [ebp+KTRAP_FRAME_EBP]
-    
     /* Jump to normal code */
     jmp SaveTrapFrameForKDB_Return
 
 RestoreTrapFrameForKDB:
   
     /* Restore the old trapframe */
-    pop [edi+KTHREAD_TRAP_FRAME]
+    pop [esi+KTHREAD_TRAP_FRAME]
         
     /* Pop unused portions of the trap frame */
     add esp, 0x30
@@ -353,23 +392,13 @@ RestoreTrapFrameForKDB:
     pop edx
     pop ecx
     pop eax
-    add esp, 8
+    add esp, 8           /* ExceptionList and PreviousMode */
     pop fs
     pop edi
     pop esi
     pop ebx
-
-    /* Remove SS:ESP from the stack */
-    mov ebp, [esp+16]
-    mov [esp+24], ebp
-    mov ebp, [esp+12]
-    mov [esp+20], ebp
-    mov ebp, [esp+8]
-    mov [esp+16], ebp
-    
-    /* Restore Fake INT Stack */
     pop ebp
-    add esp, 12
+    add esp, 4           /* ErrorCode */
 
     /* Return to the caller. */
     iret