* 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
* 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
/* 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
/* 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:
/* 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:
/* 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 */
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
/* 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
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