- Revert 49927 "Update to trunk" as it breaks KsStudio (again)
[reactos.git] / ntoskrnl / ke / amd64 / ctxswitch.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/amd64/ctxswitch.S
5 * PURPOSE: Thread Context Switching
6 *
7 * PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <reactos/asm.h>
13 #include <ndk/amd64/asm.h>
14
15 /* FUNCTIONS ****************************************************************/
16
17 .code64
18
19 /*++
20 * KiThreadStartup
21 *
22 * The KiThreadStartup routine is the beginning of any thread.
23 *
24 * Params:
25 * SystemRoutine - Pointer to the System Startup Routine. Either
26 * PspUserThreadStartup or PspSystemThreadStartup
27 *
28 * StartRoutine - For Kernel Threads only, specifies the starting execution
29 * point of the new thread.
30 *
31 * StartContext - For Kernel Threads only, specifies a pointer to variable
32 * context data to be sent to the StartRoutine above.
33 *
34 * UserThread - Indicates whether or not this is a user thread. This tells
35 * us if the thread has a context or not.
36 *
37 * TrapFrame - Pointer to the KTHREAD to which the caller wishes to
38 * switch from.
39 *
40 * Returns:
41 * Should never return for a system thread. Returns through the System Call
42 * Exit Dispatcher for a user thread.
43 *
44 * Remarks:
45 * If a return from a system thread is detected, a bug check will occur.
46 *
47 *--*/
48 PUBLIC KiThreadStartup
49 KiThreadStartup:
50
51 /*
52 * Clear all the non-volatile registers, so the thread won't be tempted to
53 * expect any static data (like some badly coded usermode/win9x apps do)
54 */
55 xor rbx, rbx
56 xor rsi, rsi
57 xor rdi, rdi
58 xor rbp, rbp
59 xor r10, r10
60 xor r11, r11
61 xor r12, r12
62 xor r13, r13
63 xor r14, r14
64 xor r15, r15
65
66 /* It's now safe to go to APC */
67 mov rax, APC_LEVEL
68 mov cr8, rax
69
70 /*
71 * Call the System Routine which is right on our stack now.
72 * After we pop the pointer, the Start Routine/Context is on the
73 * stack, we pop it as parameters to the System Routine into rcx
74 */
75 pop rax
76 pop rcx
77 call rax
78
79 /* The thread returned... was it a user-thread? */
80 pop rcx
81 or rcx, rcx
82 jz BadThread
83
84 /* Yes it was, set our trapframe for the System Call Exit Dispatcher */
85 mov ebp, esp
86
87 /* Exit back to user-mode */
88 // jmp _KiServiceExit2
89 UNIMPLEMENTED KiThreadStartup_KiServiceExit2
90
91 BadThread:
92
93 /* A system thread returned...this is very bad! */
94 int 3
95
96
97 /*++
98 * KiSwapContextInternal
99 *
100 * The KiSwapContextInternal routine switches context to another thread.
101 *
102 * Params:
103 * ESI - Pointer to the KTHREAD to which the caller wishes to
104 * switch to.
105 * EDI - Pointer to the KTHREAD to which the caller wishes to
106 * switch from.
107 *
108 * Returns:
109 * None.
110 *
111 * Remarks:
112 * Absolutely all registers except ESP can be trampled here for maximum code flexibility.
113 *
114 *--*/
115 PUBLIC KiSwapContextInternal
116 KiSwapContextInternal:
117 UNIMPLEMENTED KiSwapContextInternal
118 ret
119
120
121 /**
122 * KiSwapContext
123 *
124 * \brief
125 * The KiSwapContext routine switches context to another thread.
126 *
127 * BOOLEAN
128 * KiSwapContext(PKTHREAD CurrentThread, PKTHREAD TargetThread);
129 *
130 * \param CurrentThread
131 * Pointer to the KTHREAD of the current thread.
132 *
133 * \param TargetThread
134 * Pointer to the KTHREAD to which the caller wishes to switch to.
135 *
136 * \returns
137 * The WaitStatus of the Target Thread.
138 *
139 * \remarks
140 * This is a wrapper around KiSwapContextInternal which will save all the
141 * non-volatile registers so that the Internal function can use all of
142 * them. It will also save the old current thread and set the new one.
143 *
144 * The calling thread does not return after KiSwapContextInternal until
145 * another thread switches to IT.
146 *
147 *--*/
148 PUBLIC KiSwapContext
149 KiSwapContext:
150
151 /* Save 10 registers */
152 sub rsp, 10 * 8
153
154 /* Save all the non-volatile ones */
155 mov [rsp+72], r15
156 mov [rsp+64], r14
157 mov [rsp+56], r13
158 mov [rsp+48], r12
159 mov [rsp+40], r11
160 mov [rsp+32], r10
161
162 mov [rsp+24], rbx
163 mov [rsp+16], rsi
164 mov [rsp+8], rdi
165 mov [rsp+0], rbp
166
167 /* Get the PCR */
168 mov rbx, gs:[KPCR_SELF]
169
170 /* Get the current thread */
171 mov rdi, rcx
172
173 /* Get the New Thread */
174 mov rsi, rdx
175
176 /* Get the wait IRQL */
177 movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
178
179 /* Do the swap with the registers correctly setup */
180 call KiSwapContextInternal
181
182 /* Restore the registers */
183 mov rbp, [rsp+0]
184 mov rdi, [rsp+8]
185 mov rsi, [rsp+16]
186 mov rbx, [rsp+24]
187
188 mov r10, [rsp+32]
189 mov r11, [rsp+40]
190 mov r12, [rsp+48]
191 mov r13, [rsp+56]
192 mov r14, [rsp+64]
193 mov r15, [rsp+72]
194
195 /* Clean stack */
196 add esp, 10 * 8
197 ret
198
199 END