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