[CMAKE]
[reactos.git] / ntoskrnl / ke / i386 / thrdini.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/thread.c
5 * PURPOSE: i386 Thread Context Creation
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 typedef struct _KSWITCHFRAME
16 {
17 PVOID ExceptionList;
18 BOOLEAN ApcBypassDisable;
19 PVOID RetAddr;
20 } KSWITCHFRAME, *PKSWITCHFRAME;
21
22 typedef struct _KSTART_FRAME
23 {
24 PKSYSTEM_ROUTINE SystemRoutine;
25 PKSTART_ROUTINE StartRoutine;
26 PVOID StartContext;
27 BOOLEAN UserThread;
28 } KSTART_FRAME, *PKSTART_FRAME;
29
30 typedef struct _KUINIT_FRAME
31 {
32 KSWITCHFRAME CtxSwitchFrame;
33 KSTART_FRAME StartFrame;
34 KTRAP_FRAME TrapFrame;
35 FX_SAVE_AREA FxSaveArea;
36 } KUINIT_FRAME, *PKUINIT_FRAME;
37
38 typedef struct _KKINIT_FRAME
39 {
40 KSWITCHFRAME CtxSwitchFrame;
41 KSTART_FRAME StartFrame;
42 FX_SAVE_AREA FxSaveArea;
43 } KKINIT_FRAME, *PKKINIT_FRAME;
44
45 /* FUNCTIONS *****************************************************************/
46
47 VOID
48 NTAPI
49 KiThreadStartup(VOID)
50 {
51 PKTRAP_FRAME TrapFrame;
52 PKSTART_FRAME StartFrame;
53 PKUINIT_FRAME InitFrame;
54
55 /* Get the start and trap frames */
56 InitFrame = KeGetCurrentThread()->KernelStack;
57 StartFrame = &InitFrame->StartFrame;
58 TrapFrame = &InitFrame->TrapFrame;
59
60 /* Lower to APC level */
61 KfLowerIrql(APC_LEVEL);
62
63 /* Call the system routine */
64 StartFrame->SystemRoutine(StartFrame->StartRoutine, StartFrame->StartContext);
65
66 /* If we returned, we better be a user thread */
67 if (!StartFrame->UserThread) DbgBreakPoint();
68
69 /* Exit to user-mode */
70 KiServiceExit2(TrapFrame);
71 }
72
73 VOID
74 NTAPI
75 KiInitializeContextThread(IN PKTHREAD Thread,
76 IN PKSYSTEM_ROUTINE SystemRoutine,
77 IN PKSTART_ROUTINE StartRoutine,
78 IN PVOID StartContext,
79 IN PCONTEXT ContextPointer)
80 {
81 PFX_SAVE_AREA FxSaveArea;
82 PFXSAVE_FORMAT FxSaveFormat;
83 PKSTART_FRAME StartFrame;
84 PKSWITCHFRAME CtxSwitchFrame;
85 PKTRAP_FRAME TrapFrame;
86 CONTEXT LocalContext;
87 PCONTEXT Context = NULL;
88 ULONG ContextFlags;
89
90 /* Check if this is a With-Context Thread */
91 if (ContextPointer)
92 {
93 /* Set up the Initial Frame */
94 PKUINIT_FRAME InitFrame;
95 InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
96 sizeof(KUINIT_FRAME));
97
98 /* Copy over the context we got */
99 RtlCopyMemory(&LocalContext, ContextPointer, sizeof(CONTEXT));
100 Context = &LocalContext;
101 ContextFlags = CONTEXT_CONTROL;
102
103 /* Zero out the trap frame and save area */
104 RtlZeroMemory(&InitFrame->TrapFrame,
105 KTRAP_FRAME_LENGTH + sizeof(FX_SAVE_AREA));
106
107 /* Setup the Fx Area */
108 FxSaveArea = &InitFrame->FxSaveArea;
109
110 /* Check if we support FXsr */
111 if (KeI386FxsrPresent)
112 {
113 /* Get the FX Save Format Area */
114 FxSaveFormat = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
115
116 /* Set an initial state */
117 FxSaveFormat->ControlWord = 0x27F;
118 FxSaveFormat->StatusWord = 0;
119 FxSaveFormat->TagWord = 0;
120 FxSaveFormat->ErrorOffset = 0;
121 FxSaveFormat->ErrorSelector = 0;
122 FxSaveFormat->DataOffset = 0;
123 FxSaveFormat->DataSelector = 0;
124 FxSaveFormat->MXCsr = 0x1F80;
125 }
126 else
127 {
128 /* Setup the regular save area */
129 Context->FloatSave.ControlWord = 0x27F;
130 Context->FloatSave.StatusWord = 0;
131 Context->FloatSave.TagWord = -1;
132 Context->FloatSave.ErrorOffset = 0;
133 Context->FloatSave.ErrorSelector = 0;
134 Context->FloatSave.DataOffset =0;
135 Context->FloatSave.DataSelector = 0;
136 }
137
138 /* Check if the CPU has NPX */
139 if (KeI386NpxPresent)
140 {
141 /* Set an intial NPX State */
142 Context->FloatSave.Cr0NpxState = 0;
143 FxSaveArea->Cr0NpxState = 0;
144 FxSaveArea->NpxSavedCpu = 0;
145
146 /* Now set the context flags depending on XMM support */
147 ContextFlags |= (KeI386FxsrPresent) ? CONTEXT_EXTENDED_REGISTERS :
148 CONTEXT_FLOATING_POINT;
149
150 /* Set the Thread's NPX State */
151 Thread->NpxState = NPX_STATE_NOT_LOADED;
152 Thread->DispatcherHeader.NpxIrql = PASSIVE_LEVEL;
153 }
154 else
155 {
156 /* We'll use emulation */
157 FxSaveArea->Cr0NpxState = CR0_EM;
158 Thread->NpxState = NPX_STATE_NOT_LOADED &~ CR0_MP;
159 }
160
161 /* Disable any debug registers */
162 Context->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;
163
164 /* Setup the Trap Frame */
165 TrapFrame = &InitFrame->TrapFrame;
166
167 /* Set up a trap frame from the context. */
168 KeContextToTrapFrame(Context,
169 NULL,
170 TrapFrame,
171 Context->ContextFlags | ContextFlags,
172 UserMode);
173
174 /* Set SS, DS, ES's RPL Mask properly */
175 TrapFrame->HardwareSegSs |= RPL_MASK;
176 TrapFrame->SegDs |= RPL_MASK;
177 TrapFrame->SegEs |= RPL_MASK;
178 TrapFrame->Dr7 = 0;
179
180 /* Set the debug mark */
181 TrapFrame->DbgArgMark = 0xBADB0D00;
182
183 /* Set the previous mode as user */
184 TrapFrame->PreviousPreviousMode = UserMode;
185
186 /* Terminate the Exception Handler List */
187 TrapFrame->ExceptionList = EXCEPTION_CHAIN_END;
188
189 /* Setup the Stack for KiThreadStartup and Context Switching */
190 StartFrame = &InitFrame->StartFrame;
191 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
192
193 /* Tell the thread it will run in User Mode */
194 Thread->PreviousMode = UserMode;
195
196 /* Tell KiThreadStartup of that too */
197 StartFrame->UserThread = TRUE;
198 }
199 else
200 {
201 /* Set up the Initial Frame for the system thread */
202 PKKINIT_FRAME InitFrame;
203 InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
204 sizeof(KKINIT_FRAME));
205
206 /* Setup the Fx Area */
207 FxSaveArea = &InitFrame->FxSaveArea;
208 RtlZeroMemory(FxSaveArea, sizeof(FX_SAVE_AREA));
209
210 /* Check if we have Fxsr support */
211 if (KeI386FxsrPresent)
212 {
213 /* Set the stub FX area */
214 FxSaveArea->U.FxArea.ControlWord = 0x27F;
215 FxSaveArea->U.FxArea.MXCsr = 0x1F80;
216 }
217 else
218 {
219 /* Set the stub FN area */
220 FxSaveArea->U.FnArea.ControlWord = 0x27F;
221 FxSaveArea->U.FnArea.TagWord = -1;
222 }
223
224 /* No NPX State */
225 Thread->NpxState = NPX_STATE_NOT_LOADED;
226
227 /* Setup the Stack for KiThreadStartup and Context Switching */
228 StartFrame = &InitFrame->StartFrame;
229 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
230
231 /* Tell the thread it will run in Kernel Mode */
232 Thread->PreviousMode = KernelMode;
233
234 /* Tell KiThreadStartup of that too */
235 StartFrame->UserThread = FALSE;
236 }
237
238 /* Now setup the remaining data for KiThreadStartup */
239 StartFrame->StartContext = StartContext;
240 StartFrame->StartRoutine = StartRoutine;
241 StartFrame->SystemRoutine = SystemRoutine;
242
243 /* And set up the Context Switch Frame */
244 CtxSwitchFrame->RetAddr = KiThreadStartup;
245 CtxSwitchFrame->ApcBypassDisable = TRUE;
246 CtxSwitchFrame->ExceptionList = EXCEPTION_CHAIN_END;
247
248 /* Save back the new value of the kernel stack. */
249 Thread->KernelStack = (PVOID)CtxSwitchFrame;
250 }
251
252 /* EOF */
253
254