Initial revision
[reactos.git] / msvc6 / ntoskrnl / ke_i386_tskswitch.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
4 *
5 * Moved to MSVC-compatible inline assembler by Mike Nordell, 2003-12-26
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22 * FILE: ntoskrnl/ke/i386/vm86_sup.S
23 * PURPOSE: V86 mode support
24 * PROGRAMMER: David Welch (welch@cwcom.net)
25 * UPDATE HISTORY:
26 * Created 09/10/00
27 */
28
29 /* INCLUDES ******************************************************************/
30
31 #pragma hdrstop
32
33 #include <ddk/ntddk.h>
34 #include <ddk/status.h>
35 #include <internal/i386/segment.h>
36 #include <internal/i386/fpu.h>
37 #include <internal/ps.h>
38 #include <ddk/defines.h>
39 #include <internal/v86m.h>
40 #include <ntos/tss.h>
41 //#include <ntos/service.h>
42 #include <internal/trap.h>
43 #include <internal/ps.h>
44
45 #include <roscfg.h>
46 #include <internal/ntoskrnl.h>
47 #include <internal/i386/segment.h>
48
49
50 extern KSPIN_LOCK PiThreadListLock;
51 extern ULONG PiNrThreadsAwaitingReaping;
52 extern ULONG MmGlobalKernelPageDirectory[1024];
53
54 VOID STDCALL PiWakeupReaperThread(VOID);
55 VOID KeSetBaseGdtSelector(ULONG Entry, PVOID Base);
56
57
58 /*
59 * FUNCTIONS: Switches to another thread's context
60 * ARGUMENTS:
61 * Thread = Thread to switch to
62 * OldThread = Thread to switch from
63 */
64 __declspec(naked)
65 VOID
66 Ki386ContextSwitch(struct _KTHREAD* NewThread, struct _KTHREAD* OldThread)
67 {
68 __asm
69 {
70 push ebp
71 mov ebp, esp
72
73 /* Save callee save registers. */
74 push ebx
75 push esi
76 push edi
77
78 cli /* This is a critical section for this processor. */
79
80 /* Get the pointer to the new thread. */
81 mov ebx, NewThread
82
83 /*
84 * Set the base of the TEB selector to the base of the TEB for
85 * this thread.
86 */
87 push ebx
88 push KTHREAD_TEB[ebx]
89 push TEB_SELECTOR
90 call KeSetBaseGdtSelector
91 add esp, 8
92 pop ebx
93
94 /*
95 * Load the PCR selector.
96 */
97 mov eax, PCR_SELECTOR
98 mov fs, ax
99
100 /*
101 * Set the current thread information in the PCR.
102 */
103 mov fs:KPCR_CURRENT_THREAD, ebx
104
105 /*
106 * Set the current LDT
107 */
108 xor eax, eax
109 mov edi, ETHREAD_THREADS_PROCESS[ebx]
110 test word ptr KPROCESS_LDT_DESCRIPTOR0[edi], 0xFFFF
111 jz L4
112
113 push KPROCESS_LDT_DESCRIPTOR1[edi]
114 push KPROCESS_LDT_DESCRIPTOR0[edi]
115 push LDT_SELECTOR
116 call KeSetGdtSelector
117 add esp, 12
118
119 mov eax, LDT_SELECTOR
120
121 L4:
122 lldt ax
123
124 /*
125 * Load up the iomap offset for this thread in
126 * preparation for setting it below.
127 */
128 mov eax, KPROCESS_IOPM_OFFSET[edi]
129
130 /*
131 * FIXME: Save debugging state.
132 */
133
134 /*
135 * FIXME: Save floating point state.
136 */
137
138 /*
139 * Switch stacks
140 */
141 mov ebx, 12[ebp]
142 mov KTHREAD_KERNEL_STACK[ebx], esp
143 mov ebx, 8[ebp]
144 mov esp, KTHREAD_KERNEL_STACK[ebx]
145 mov edi, KTHREAD_STACK_LIMIT[ebx]
146
147 /*
148 * Set the stack pointer in this processors TSS
149 */
150 mov esi, fs:KPCR_TSS
151
152 /*
153 * Set current IOPM offset in the TSS
154 */
155 mov KTSS_IOMAPBASE[esi], ax
156
157 mov eax, KTHREAD_INITIAL_STACK[ebx]
158 mov KTSS_ESP0[esi], eax
159
160 /*
161 * Change the address space
162 */
163 mov ebx, ETHREAD_THREADS_PROCESS[ebx]
164 mov eax, KPROCESS_DIRECTORY_TABLE_BASE[ebx]
165 mov cr3, eax
166
167 /*
168 * Set up the PDE for the top of the new stack.
169 */
170 mov ebx, 0
171 L2:
172 mov esi, edi
173 shr esi, 22
174 mov eax, 0xF03C0000[esi*4]
175 cmp eax, 0
176 jne L1
177 mov eax, MmGlobalKernelPageDirectory[esi*4]
178 mov 0xF03C0000[esi*4], eax
179 L1:
180 add edi, 4096
181 inc ebx
182 cmp ebx, (MM_STACK_SIZE / 4096)
183 jl L2
184
185 /*
186 * FIXME: Restore floating point state
187 */
188
189 /*
190 * FIXME: Restore debugging state
191 */
192
193 /*
194 * Exit the critical section
195 */
196 sti
197 }
198
199 KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
200
201 if (PiNrThreadsAwaitingReaping) {
202 PiWakeupReaperThread();
203 }
204
205 __asm
206 {
207 /*
208 * Restore the saved register and exit
209 */
210 pop edi
211 pop esi
212 pop ebx
213
214 pop ebp
215 ret
216 }
217 }