Continue of MSVC-compiling changes....
[reactos.git] / reactos / ntoskrnl / ke / i386 / thread.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/thread.c
22 * PURPOSE: Architecture multitasking functions
23 * PROGRAMMER: David Welch (welch@cwcom.net)
24 * REVISION HISTORY:
25 * 27/06/98: Created
26 */
27
28 /* INCLUDES ****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <internal/ntoskrnl.h>
32 #include <internal/ps.h>
33 #include <internal/i386/segment.h>
34 #include <internal/i386/mm.h>
35 #include <internal/ke.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* GLOBALS *******************************************************************/
41
42 #define FLAG_NT (1<<14)
43 #define FLAG_VM (1<<17)
44 #define FLAG_IF (1<<9)
45 #define FLAG_IOPL ((1<<12)+(1<<13))
46
47 /* FUNCTIONS *****************************************************************/
48
49 NTSTATUS
50 Ki386ValidateUserContext(PCONTEXT Context)
51 /*
52 * FUNCTION: Validates a processor context
53 * ARGUMENTS:
54 * Context = Context to validate
55 * RETURNS: Status
56 * NOTE: This only validates the context as not violating system security, it
57 * doesn't guararantee the thread won't crash at some point
58 * NOTE2: This relies on there only being two selectors which can access
59 * system space
60 */
61 {
62 if (Context->Eip >= KERNEL_BASE)
63 {
64 return(STATUS_UNSUCCESSFUL);
65 }
66 if (Context->SegCs == KERNEL_CS)
67 {
68 return(STATUS_UNSUCCESSFUL);
69 }
70 if (Context->SegDs == KERNEL_DS)
71 {
72 return(STATUS_UNSUCCESSFUL);
73 }
74 if (Context->SegEs == KERNEL_DS)
75 {
76 return(STATUS_UNSUCCESSFUL);
77 }
78 if (Context->SegFs == KERNEL_DS)
79 {
80 return(STATUS_UNSUCCESSFUL);
81 }
82 if (Context->SegGs == KERNEL_DS)
83 {
84 return(STATUS_UNSUCCESSFUL);
85 }
86 if ((Context->EFlags & FLAG_IOPL) != 0 ||
87 (Context->EFlags & FLAG_NT) ||
88 (Context->EFlags & FLAG_VM) ||
89 (!(Context->EFlags & FLAG_IF)))
90 {
91 return(STATUS_UNSUCCESSFUL);
92 }
93 return(STATUS_SUCCESS);
94 }
95
96 NTSTATUS
97 Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context)
98 {
99 PULONG KernelStack;
100 ULONG InitSize;
101 PKTRAP_FRAME TrapFrame;
102
103 /*
104 * Setup a stack frame for exit from the task switching routine
105 */
106
107 InitSize = 5 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
108 sizeof(FLOATING_SAVE_AREA) + sizeof(KTRAP_FRAME);
109 KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize);
110
111 /* Set up the initial frame for the return from the dispatcher. */
112 KernelStack[0] = 0; /* EDI */
113 KernelStack[1] = 0; /* ESI */
114 KernelStack[2] = 0; /* EBX */
115 KernelStack[3] = 0; /* EBP */
116 KernelStack[4] = (ULONG)PsBeginThreadWithContextInternal; /* EIP */
117
118 /* Save the context flags. */
119 KernelStack[5] = Context->ContextFlags;
120
121 /* Set up the initial values of the debugging registers. */
122 KernelStack[6] = Context->Dr0;
123 KernelStack[7] = Context->Dr1;
124 KernelStack[8] = Context->Dr2;
125 KernelStack[9] = Context->Dr3;
126 KernelStack[10] = Context->Dr6;
127 KernelStack[11] = Context->Dr7;
128
129 /* Set up the initial floating point state. */
130 memcpy((PVOID)&KernelStack[12], (PVOID)&Context->FloatSave,
131 sizeof(FLOATING_SAVE_AREA));
132
133 /* Set up a trap frame from the context. */
134 TrapFrame = (PKTRAP_FRAME)
135 ((char*)KernelStack + 12 * sizeof(DWORD) + sizeof(FLOATING_SAVE_AREA));
136 TrapFrame->DebugEbp = (PVOID)Context->Ebp;
137 TrapFrame->DebugEip = (PVOID)Context->Eip;
138 TrapFrame->DebugArgMark = 0;
139 TrapFrame->DebugPointer = 0;
140 TrapFrame->TempCs = 0;
141 TrapFrame->TempEip = 0;
142 TrapFrame->Gs = (USHORT)Context->SegGs;
143 TrapFrame->Es = (USHORT)Context->SegEs;
144 TrapFrame->Ds = (USHORT)Context->SegDs;
145 TrapFrame->Edx = Context->Edx;
146 TrapFrame->Ecx = Context->Ecx;
147 TrapFrame->Eax = Context->Eax;
148 TrapFrame->PreviousMode = UserMode;
149 TrapFrame->ExceptionList = (PVOID)0xFFFFFFFF;
150 TrapFrame->Fs = TEB_SELECTOR;
151 TrapFrame->Edi = Context->Edi;
152 TrapFrame->Esi = Context->Esi;
153 TrapFrame->Ebx = Context->Ebx;
154 TrapFrame->Ebp = Context->Ebp;
155 TrapFrame->ErrorCode = 0;
156 TrapFrame->Cs = Context->SegCs;
157 TrapFrame->Eip = Context->Eip;
158 TrapFrame->Eflags = Context->EFlags | FLAG_IF;
159 TrapFrame->Eflags &= ~(FLAG_VM | FLAG_NT | FLAG_IOPL);
160 TrapFrame->Esp = Context->Esp;
161 TrapFrame->Ss = (USHORT)Context->SegSs;
162 /* FIXME: Should check for a v86 mode context here. */
163
164 /* Save back the new value of the kernel stack. */
165 Thread->KernelStack = (PVOID)KernelStack;
166
167 return(STATUS_SUCCESS);
168 }
169
170 NTSTATUS
171 Ke386InitThread(PKTHREAD Thread,
172 PKSTART_ROUTINE StartRoutine,
173 PVOID StartContext)
174 /*
175 * Initialize a thread
176 */
177 {
178 PULONG KernelStack;
179
180 /*
181 * Setup a stack frame for exit from the task switching routine
182 */
183
184 KernelStack = (PULONG)((char*)Thread->KernelStack - (8*4));
185 KernelStack[0] = 0; /* EDI */
186 KernelStack[1] = 0; /* ESI */
187 KernelStack[2] = 0; /* EBX */
188 KernelStack[3] = 0; /* EBP */
189 KernelStack[4] = (ULONG)PsBeginThread; /* EIP */
190 KernelStack[5] = 0; /* Return EIP */
191 KernelStack[6] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
192 KernelStack[7] = (ULONG)StartContext; /* Second argument to PsBeginThread */
193 Thread->KernelStack = (VOID*)KernelStack;
194
195 return(STATUS_SUCCESS);
196 }
197
198 /* EOF */