[NTOS:KE:I386] Fix parameter description for KiSwapContext
[reactos.git] / ntoskrnl / ke / i386 / ctxswitch.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/ctxswitch.S
5 * PURPOSE: Thread Context Switching
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * Gregor Anich (FPU Code)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <asm.inc>
14 #include <ks386.inc>
15
16 EXTERN @KiSwapContextEntry@8:PROC
17 EXTERN @KiSwapContextExit@8:PROC
18 EXTERN @KiRetireDpcList@4:PROC
19 EXTERN @KiEnterV86Mode@4:PROC
20 EXTERN @KiExitV86Mode@4:PROC
21 EXTERN _KeI386FxsrPresent:DWORD
22
23 /* FUNCTIONS ****************************************************************/
24 .code
25
26 /*++
27 * KiSwapContextInternal
28 *
29 * \brief
30 * The KiSwapContextInternal routine switches context to another thread.
31 *
32 * BOOLEAN USERCALL KiSwapContextInternal(ULONG_PTR OldThreadAndApcFlag@<edx>);
33 *
34 * \param OldThreadAndApcFlag@<edx>
35 * Pointer to the current thread with the lowest bit set to the current IRQL.
36 *
37 * \returns
38 * APC state.
39 *
40 * \remarks
41 * Absolutely all registers except ESP can be trampled here for maximum code flexibility.
42 *
43 *--*/
44 PUBLIC @KiSwapContextInternal@0
45 @KiSwapContextInternal@0:
46 /* Build switch frame */
47 sub esp, 2 * 4
48 mov ecx, esp
49 jmp @KiSwapContextEntry@8
50
51
52 /**
53 * KiSwapContext
54 *
55 * \brief
56 * The KiSwapContext routine switches context to another thread.
57 *
58 * BOOLEAN FASTCALL
59 * KiSwapContext(KIRQL WaitIrql@<cl>, PKTHREAD CurrentThread@<edx>);
60 *
61 * \param WaitIrql@<cl>
62 * The IRQL at which the wait happens.
63 *
64 * \param CurrentThread@<edx>
65 * Pointer to the KTHREAD of the current thread.
66 *
67 * \returns
68 * The WaitStatus of the Target Thread.
69 *
70 * \remarks
71 * This is a wrapper around KiSwapContextInternal which will save all the
72 * non-volatile registers so that the Internal function can use all of
73 * them. It will also save the old current thread and set the new one.
74 *
75 * The calling thread does not return after KiSwapContextInternal until
76 * another thread switches to IT.
77 *
78 *--*/
79 PUBLIC @KiSwapContext@8
80 @KiSwapContext@8:
81 /* Save 4 registers */
82 sub esp, 4 * 4
83
84 /* Save all the non-volatile ones */
85 mov [esp+12], ebx
86 mov [esp+8], esi
87 mov [esp+4], edi
88 mov [esp+0], ebp
89
90 /* Combine current thread and the wait IRQL in edx */
91 or dl, cl
92
93 /* Do the swap with the registers correctly setup */
94 call @KiSwapContextInternal@0
95
96 /* Restore the registers */
97 mov ebp, [esp+0]
98 mov edi, [esp+4]
99 mov esi, [esp+8]
100 mov ebx, [esp+12]
101
102 /* Clean stack */
103 add esp, 4 * 4
104 ret
105
106
107 PUBLIC @KiSwitchThreads@8
108 @KiSwitchThreads@8:
109 /* Load the new kernel stack and switch OS to new thread */
110 mov esp, edx
111 #if DBG
112 /* Restore the frame pointer early to get sensible backtraces */
113 mov ebp, [esp+12]
114 #endif
115 call @KiSwapContextExit@8
116
117 /* Now we're on the new thread. Return to the caller to restore registers */
118 add esp, 2 * 4
119 ret
120
121
122 PUBLIC @KiRetireDpcListInDpcStack@8
123 @KiRetireDpcListInDpcStack@8:
124 /* Switch stacks and retire DPCs */
125 mov eax, esp
126 mov esp, edx
127 push eax
128 call @KiRetireDpcList@4
129
130 /* Return on original stack */
131 pop esp
132 ret
133
134 PUBLIC _Ki386EnableCurrentLargePage@8
135 _Ki386EnableCurrentLargePage@8:
136 /* Save StartAddress in eax */
137 mov eax, [esp + 4]
138
139 /* Save new CR3 value in ecx */
140 mov ecx, [esp + 8]
141
142 /* Save flags value */
143 pushfd
144
145 /* Disable interrupts */
146 cli
147
148 /* Compute linear address */
149 sub eax, offset _Ki386EnableCurrentLargePage@8
150 add eax, offset _Ki386LargePageIdentityLabel
151
152 /* Save old CR3 in edx and replace with a new one */
153 mov edx, cr3
154 mov cr3, ecx
155
156 /* Jump to the next instruction but in linear mapping */
157 jmp eax
158
159 _Ki386LargePageIdentityLabel:
160 /* Disable paging */
161 mov eax, cr0
162 and eax, NOT CR0_PG
163 mov cr0, eax
164
165 /* Jump to the next instruction to clear the prefetch queue */
166 jmp $+2
167
168 /* Enable Page Size Extension in CR4 */
169 mov ecx, cr4
170 or ecx, CR4_PSE
171 mov cr4, ecx
172
173 /* Done, now re-enable paging */
174 or eax, CR0_PG
175 mov cr0, eax
176
177 /* Jump to virtual address */
178 mov eax, offset VirtualSpace
179 jmp eax
180
181 VirtualSpace:
182 /* Restore CR3 contents */
183 mov cr3, edx
184
185 /* Restore flags */
186 popfd
187
188 ret 8
189
190 /* FIXFIX: Move to C code ****/
191 PUBLIC _Ki386SetupAndExitToV86Mode@4
192 _Ki386SetupAndExitToV86Mode@4:
193
194 /* Enter V8086 mode */
195 pushad
196 sub esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
197 mov ecx, esp
198 call @KiEnterV86Mode@4
199 jmp $
200
201
202 PUBLIC @Ki386BiosCallReturnAddress@4
203 @Ki386BiosCallReturnAddress@4:
204
205 /* Exit V8086 mode */
206 call @KiExitV86Mode@4
207 mov esp, eax
208 add esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
209 popad
210 ret 4
211
212 PUBLIC _FrRestore
213 PUBLIC @Ke386LoadFpuState@4
214 @Ke386LoadFpuState@4:
215
216 /* Check if we have FXSR and choose which operand to use */
217 test byte ptr [_KeI386FxsrPresent], 1
218 jz _FrRestore
219
220 /* Restore all the FPU, MMX, XMM and MXCSR registers */
221 fxrstor [ecx]
222 ret
223
224 /*
225 * Just restore the basic FPU registers.
226 * This may raise an exception depending
227 * on the status word, which KiNpxHandler will
228 * need to check for and handle during delayed load
229 * to avoid raising an unhandled exception
230 * and crashing the system.
231 */
232 _FrRestore:
233 frstor [ecx]
234 ret
235
236 END