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)
9 /* INCLUDES ******************************************************************/
15 typedef struct _KSWITCHFRAME
18 BOOLEAN ApcBypassDisable
;
20 } KSWITCHFRAME
, *PKSWITCHFRAME
;
22 typedef struct _KSTART_FRAME
24 PKSYSTEM_ROUTINE SystemRoutine
;
25 PKSTART_ROUTINE StartRoutine
;
28 } KSTART_FRAME
, *PKSTART_FRAME
;
30 typedef struct _KUINIT_FRAME
32 KSWITCHFRAME CtxSwitchFrame
;
33 KSTART_FRAME StartFrame
;
34 KTRAP_FRAME TrapFrame
;
35 FX_SAVE_AREA FxSaveArea
;
36 } KUINIT_FRAME
, *PKUINIT_FRAME
;
38 typedef struct _KKINIT_FRAME
40 KSWITCHFRAME CtxSwitchFrame
;
41 KSTART_FRAME StartFrame
;
42 FX_SAVE_AREA FxSaveArea
;
43 } KKINIT_FRAME
, *PKKINIT_FRAME
;
45 /* FUNCTIONS *****************************************************************/
51 PKTRAP_FRAME TrapFrame
;
52 PKSTART_FRAME StartFrame
;
53 PKUINIT_FRAME InitFrame
;
55 /* Get the start and trap frames */
56 InitFrame
= KeGetCurrentThread()->KernelStack
;
57 StartFrame
= &InitFrame
->StartFrame
;
58 TrapFrame
= &InitFrame
->TrapFrame
;
60 /* Lower to APC level */
61 KfLowerIrql(APC_LEVEL
);
63 /* Call the system routine */
64 StartFrame
->SystemRoutine(StartFrame
->StartRoutine
, StartFrame
->StartContext
);
66 /* If we returned, we better be a user thread */
67 if (!StartFrame
->UserThread
) DbgBreakPoint();
69 /* Exit to user-mode */
70 KiServiceExit2(TrapFrame
);
75 KiInitializeContextThread(IN PKTHREAD Thread
,
76 IN PKSYSTEM_ROUTINE SystemRoutine
,
77 IN PKSTART_ROUTINE StartRoutine
,
78 IN PVOID StartContext
,
79 IN PCONTEXT ContextPointer
)
81 PFX_SAVE_AREA FxSaveArea
;
82 PFXSAVE_FORMAT FxSaveFormat
;
83 PKSTART_FRAME StartFrame
;
84 PKSWITCHFRAME CtxSwitchFrame
;
85 PKTRAP_FRAME TrapFrame
;
87 PCONTEXT Context
= NULL
;
90 /* Check if this is a With-Context Thread */
93 /* Set up the Initial Frame */
94 PKUINIT_FRAME InitFrame
;
95 InitFrame
= (PKUINIT_FRAME
)((ULONG_PTR
)Thread
->InitialStack
-
96 sizeof(KUINIT_FRAME
));
98 /* Copy over the context we got */
99 RtlCopyMemory(&LocalContext
, ContextPointer
, sizeof(CONTEXT
));
100 Context
= &LocalContext
;
101 ContextFlags
= CONTEXT_CONTROL
;
103 /* Zero out the trap frame and save area */
104 RtlZeroMemory(&InitFrame
->TrapFrame
,
105 KTRAP_FRAME_LENGTH
+ sizeof(FX_SAVE_AREA
));
107 /* Setup the Fx Area */
108 FxSaveArea
= &InitFrame
->FxSaveArea
;
110 /* Check if we support FXsr */
111 if (KeI386FxsrPresent
)
113 /* Get the FX Save Format Area */
114 FxSaveFormat
= (PFXSAVE_FORMAT
)Context
->ExtendedRegisters
;
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;
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;
138 /* Check if the CPU has NPX */
139 if (KeI386NpxPresent
)
141 /* Set an intial NPX State */
142 Context
->FloatSave
.Cr0NpxState
= 0;
143 FxSaveArea
->Cr0NpxState
= 0;
144 FxSaveArea
->NpxSavedCpu
= 0;
146 /* Now set the context flags depending on XMM support */
147 ContextFlags
|= (KeI386FxsrPresent
) ? CONTEXT_EXTENDED_REGISTERS
:
148 CONTEXT_FLOATING_POINT
;
150 /* Set the Thread's NPX State */
151 Thread
->NpxState
= NPX_STATE_NOT_LOADED
;
152 Thread
->DispatcherHeader
.NpxIrql
= PASSIVE_LEVEL
;
156 /* We'll use emulation */
157 FxSaveArea
->Cr0NpxState
= CR0_EM
;
158 Thread
->NpxState
= NPX_STATE_NOT_LOADED
&~ CR0_MP
;
161 /* Disable any debug registers */
162 Context
->ContextFlags
&= ~CONTEXT_DEBUG_REGISTERS
;
164 /* Setup the Trap Frame */
165 TrapFrame
= &InitFrame
->TrapFrame
;
167 /* Set up a trap frame from the context. */
168 KeContextToTrapFrame(Context
,
171 Context
->ContextFlags
| ContextFlags
,
174 /* Set SS, DS, ES's RPL Mask properly */
175 TrapFrame
->HardwareSegSs
|= RPL_MASK
;
176 TrapFrame
->SegDs
|= RPL_MASK
;
177 TrapFrame
->SegEs
|= RPL_MASK
;
180 /* Set the debug mark */
181 TrapFrame
->DbgArgMark
= 0xBADB0D00;
183 /* Set the previous mode as user */
184 TrapFrame
->PreviousPreviousMode
= UserMode
;
186 /* Terminate the Exception Handler List */
187 TrapFrame
->ExceptionList
= EXCEPTION_CHAIN_END
;
189 /* Setup the Stack for KiThreadStartup and Context Switching */
190 StartFrame
= &InitFrame
->StartFrame
;
191 CtxSwitchFrame
= &InitFrame
->CtxSwitchFrame
;
193 /* Tell the thread it will run in User Mode */
194 Thread
->PreviousMode
= UserMode
;
196 /* Tell KiThreadStartup of that too */
197 StartFrame
->UserThread
= TRUE
;
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
));
206 /* Setup the Fx Area */
207 FxSaveArea
= &InitFrame
->FxSaveArea
;
208 RtlZeroMemory(FxSaveArea
, sizeof(FX_SAVE_AREA
));
210 /* Check if we have Fxsr support */
211 if (KeI386FxsrPresent
)
213 /* Set the stub FX area */
214 FxSaveArea
->U
.FxArea
.ControlWord
= 0x27F;
215 FxSaveArea
->U
.FxArea
.MXCsr
= 0x1F80;
219 /* Set the stub FN area */
220 FxSaveArea
->U
.FnArea
.ControlWord
= 0x27F;
221 FxSaveArea
->U
.FnArea
.TagWord
= -1;
225 Thread
->NpxState
= NPX_STATE_NOT_LOADED
;
227 /* Setup the Stack for KiThreadStartup and Context Switching */
228 StartFrame
= &InitFrame
->StartFrame
;
229 CtxSwitchFrame
= &InitFrame
->CtxSwitchFrame
;
231 /* Tell the thread it will run in Kernel Mode */
232 Thread
->PreviousMode
= KernelMode
;
234 /* Tell KiThreadStartup of that too */
235 StartFrame
->UserThread
= FALSE
;
238 /* Now setup the remaining data for KiThreadStartup */
239 StartFrame
->StartContext
= StartContext
;
240 StartFrame
->StartRoutine
= StartRoutine
;
241 StartFrame
->SystemRoutine
= SystemRoutine
;
243 /* And set up the Context Switch Frame */
244 CtxSwitchFrame
->RetAddr
= KiThreadStartup
;
245 CtxSwitchFrame
->ApcBypassDisable
= TRUE
;
246 CtxSwitchFrame
->ExceptionList
= EXCEPTION_CHAIN_END
;
248 /* Save back the new value of the kernel stack. */
249 Thread
->KernelStack
= (PVOID
)CtxSwitchFrame
;