ReactOS 0.4.16-dev-1946-g52006dd
thrdini.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/amd64/thrdini.c
5 * PURPOSE: amd64 Thread Context Creation
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * Alex Ionescu (alex@relsoft.net)
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
17extern void KiUserThreadStartupExit(void);
18extern void KiServiceExit3(void);
19
20typedef struct _KUINIT_FRAME
21{
26 //FX_SAVE_AREA FxSaveArea;
28
29typedef struct _KKINIT_FRAME
30{
33 //FX_SAVE_AREA FxSaveArea;
35
36/* FUNCTIONS *****************************************************************/
37
38VOID
41 IN PKSYSTEM_ROUTINE SystemRoutine,
43 IN PVOID StartContext,
45{
46 PKSTART_FRAME StartFrame;
47 PKSWITCH_FRAME CtxSwitchFrame;
48 PKTRAP_FRAME TrapFrame;
49 ULONG ContextFlags;
50 PVOID InitialStack;
51
52 /* Allocate space on the stack for the XSAVE area */
53 InitialStack = (PUCHAR)Thread->InitialStack - KeXStateLength;
54 InitialStack = ALIGN_DOWN_POINTER_BY(InitialStack, 64);
55 Thread->InitialStack = InitialStack;
56
57 /* Initialize the state save area */
58 Thread->StateSaveArea = InitialStack;
59 RtlZeroMemory(Thread->StateSaveArea, KeXStateLength);
60 Thread->StateSaveArea->MxCsr = INITIAL_MXCSR;
61 Thread->StateSaveArea->ControlWord = INITIAL_FPCSR;
62
63 /* Check if we use XSAVE */
65 {
66 /* Enable the mask for legacy floating point state */
67 PXSAVE_AREA XSaveArea = (PXSAVE_AREA)Thread->StateSaveArea;
68 XSaveArea->Header.Mask |= XSTATE_MASK_LEGACY_FLOATING_POINT;
69
70 /* Special initialization for XSAVES */
72 {
73 /* Set bit 63 in XCOMP_BV to mark the area as compacted.
74 XRSTORS requires this and will #GP otherwise.
75 Also mark legacy FP as compacted. */
76 XSaveArea->Header.CompactionMask |= 0x8000000000000000ULL |
78 }
79 }
80
81 /* Check if this is a With-Context Thread */
82 if (Context)
83 {
84 PKUINIT_FRAME InitFrame;
85
86 /* Set up the Initial Frame */
87 InitFrame = ((PKUINIT_FRAME)Thread->InitialStack) - 1;
88 StartFrame = &InitFrame->StartFrame;
89 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
90
91 /* Save back the new value of the kernel stack. */
92 Thread->KernelStack = (PVOID)InitFrame;
93
94 /* Tell the thread it will run in User Mode */
95 Thread->PreviousMode = UserMode;
96
97 /* Set the Thread's NPX State */
98 Thread->NpxState = SharedUserData->XState.EnabledFeatures;
99 Thread->Header.NpxIrql = PASSIVE_LEVEL;
100
101 /* Make sure, we have control registers, disable debug registers */
102 ASSERT((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL);
103 ContextFlags = Context->ContextFlags & ~CONTEXT_DEBUG_REGISTERS;
104
105 /* Setup the Trap Frame */
106 TrapFrame = &InitFrame->TrapFrame;
107
108 /* Zero out the trap frame */
109 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
110 RtlZeroMemory(&InitFrame->ExceptionFrame, sizeof(KEXCEPTION_FRAME));
111
112 /* Set up a trap frame from the context. */
114 &InitFrame->ExceptionFrame,
115 TrapFrame,
116 CONTEXT_AMD64 | ContextFlags,
117 UserMode);
118
119 /* Set SS, DS, ES's RPL Mask properly */
120 TrapFrame->SegSs |= RPL_MASK;
121 TrapFrame->SegDs |= RPL_MASK;
122 TrapFrame->SegEs |= RPL_MASK;
123 TrapFrame->Dr7 = 0;
124
125 /* Set the previous mode as user */
126 TrapFrame->PreviousMode = UserMode;
127
128 /* Terminate the Exception Handler List */
129 TrapFrame->ExceptionFrame = 0;
130
131 /* KiThreadStartup returns to KiUserThreadStartupExit */
133
134 /* KiUserThreadStartupExit returns to KiServiceExit3 */
136 }
137 else
138 {
139 PKKINIT_FRAME InitFrame;
140
141 /* Set up the Initial Frame for the system thread */
142 InitFrame = ((PKKINIT_FRAME)Thread->InitialStack) - 1;
143 StartFrame = &InitFrame->StartFrame;
144 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
145
146 /* Save back the new value of the kernel stack. */
147 Thread->KernelStack = (PVOID)InitFrame;
148
149 /* Tell the thread it will run in Kernel Mode */
150 Thread->PreviousMode = KernelMode;
151
152 /* No NPX State */
153 Thread->NpxState = 0;
154
155 /* This must never return! */
157 }
158
159 /* Set up the Context Switch Frame */
160 CtxSwitchFrame->Return = (ULONG64)KiThreadStartup;
161 CtxSwitchFrame->ApcBypass = TRUE;
162
163 StartFrame->P1Home = (ULONG64)StartRoutine;
164 StartFrame->P2Home = (ULONG64)StartContext;
165 StartFrame->P3Home = 0;
166 StartFrame->P4Home = (ULONG64)SystemRoutine;
167 StartFrame->Reserved = 0;
168}
169
172 _In_ BOOLEAN ApcBypass,
173 _In_ PKTHREAD OldThread,
174 _In_ PKTHREAD NewThread)
175{
176 PKIPCR Pcr = (PKIPCR)KeGetPcr();
177 PKPROCESS OldProcess, NewProcess;
178
179 /* Setup ring 0 stack pointer */
180 Pcr->TssBase->Rsp0 = (ULONG64)NewThread->InitialStack;
181 Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
182
183 /* Save old thread's extended state */
184 if (OldThread->NpxState != 0)
185 {
186 KiSaveXState(OldThread->StateSaveArea, OldThread->NpxState);
187 }
188
189 /* Load new thread's extended state */
190 if (NewThread->NpxState != 0)
191 {
192 KiRestoreXState(NewThread->StateSaveArea, NewThread->NpxState);
193 }
194
195 /* Now we are the new thread. Check if it's in a new process */
196 OldProcess = OldThread->ApcState.Process;
197 NewProcess = NewThread->ApcState.Process;
198 if (OldProcess != NewProcess)
199 {
200 /* Switch address space and flush TLB */
201 __writecr3(NewProcess->DirectoryTableBase[0]);
202
203 /* Set new TSS fields */
204 //Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
205 }
206
207 /* Set TEB pointer and GS base */
208 Pcr->NtTib.Self = (PVOID)NewThread->Teb;
209 if (NewThread->Teb)
210 {
211 /* This will switch the usermode gs */
212 __writemsr(MSR_GS_SWAP, (ULONG64)NewThread->Teb);
213 }
214
215 /* Increase context switch count */
216 Pcr->ContextSwitches++;
217 NewThread->ContextSwitches++;
218
219 /* DPCs shouldn't be active */
220 if (Pcr->Prcb.DpcRoutineActive)
221 {
222 /* Crash the machine */
223 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
224 (ULONG_PTR)OldThread,
225 (ULONG_PTR)NewThread,
226 (ULONG_PTR)OldThread->InitialStack,
227 0);
228 }
229
230 /* Old thread os no longer busy */
231 OldThread->SwapBusy = FALSE;
232
233 /* Kernel APCs may be pending */
234 if (NewThread->ApcState.KernelApcPending)
235 {
236 /* Are APCs enabled? */
237 if ((NewThread->SpecialApcDisable == 0) &&
238 (ApcBypass == 0))
239 {
240 /* Return TRUE to indicate that we want APCs to be delivered */
241 return TRUE;
242 }
243
244 /* Request an APC interrupt to be delivered later */
246 }
247
248 /* Return stating that no kernel APCs are pending*/
249 return FALSE;
250}
251
252/* EOF */
253
254
unsigned char BOOLEAN
ULONG64 KeFeatureBits
Definition: krnlinit.c:22
FORCEINLINE VOID KiRestoreXState(_In_ PVOID Buffer, _In_ ULONG64 ComponentMask)
Definition: intrin_i.h:91
FORCEINLINE VOID KiSaveXState(_Out_ PVOID Buffer, _In_ ULONG64 ComponentMask)
Definition: intrin_i.h:66
BOOLEAN KiSwapContextResume(_In_ BOOLEAN ApcBypass, _In_ PKTHREAD OldThread, _In_ PKTHREAD NewThread)
Definition: thrdini.c:171
VOID NTAPI KiInitializeContextThread(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context)
Definition: thrdini.c:40
void KiInvalidSystemThreadStartupExit(void)
struct _KKINIT_FRAME KKINIT_FRAME
void KiUserThreadStartupExit(void)
void KiServiceExit3(void)
struct _KUINIT_FRAME * PKUINIT_FRAME
struct _KKINIT_FRAME * PKKINIT_FRAME
struct _KUINIT_FRAME KUINIT_FRAME
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define APC_LEVEL
Definition: env_spec_w32.h:695
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1808
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
#define KF_XSTATE
Definition: ketypes.h:55
#define MSR_GS_SWAP
Definition: ketypes.h:263
struct _KIPCR * PKIPCR
#define KF_XSAVES
Definition: ketypes.h:68
#define RPL_MASK
Definition: ketypes.h:124
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
#define KeGetPcr()
Definition: ketypes.h:81
VOID(NTAPI * PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
Definition: ketypes.h:862
#define _In_
Definition: no_sal2.h:158
#define CONTEXT_CONTROL
Definition: nt_native.h:1372
SIZE_T KeXStateLength
Definition: stubs.c:18
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define INITIAL_FPCSR
#define SharedUserData
#define INITIAL_MXCSR
ULONG64 Return
Definition: ketypes.h:1069
ULONG ContextSwitches
Definition: ketypes.h:996
KPRCB Prcb
Definition: ketypes.h:993
struct _KTSS64 * TssBase
Definition: ketypes.h:965
NT_TIB NtTib
Definition: ketypes.h:961
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:31
KSTART_FRAME StartFrame
Definition: thrdini.c:32
UINT64 RspBase
Definition: ketypes.h:674
UCHAR DpcRoutineActive
Definition: ketypes.h:786
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2215
ULONG64 P2Home
Definition: ketypes.h:1143
ULONG64 Reserved
Definition: ketypes.h:1146
ULONG64 P1Home
Definition: ketypes.h:1142
ULONG64 Return
Definition: ketypes.h:1147
ULONG64 P4Home
Definition: ketypes.h:1145
ULONG64 P3Home
Definition: ketypes.h:1144
ULONG64 Return
Definition: ketypes.h:1160
KIRQL ApcBypass
Definition: ketypes.h:1157
CHAR PreviousMode
Definition: ketypes.h:412
USHORT SegSs
Definition: ketypes.h:486
UINT64 ExceptionFrame
Definition: ketypes.h:475
UINT64 Dr7
Definition: ketypes.h:446
USHORT SegEs
Definition: ketypes.h:464
USHORT SegDs
Definition: ketypes.h:463
KTRAP_FRAME TrapFrame
Definition: thrdini.c:25
KSTART_FRAME StartFrame
Definition: thrdini.c:23
KEXCEPTION_FRAME ExceptionFrame
Definition: thrdini.c:24
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:22
struct _NT_TIB * Self
Definition: compat.h:720
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
#define CONTEXT_AMD64
Definition: winnt.h:26
* PXSAVE_AREA
Definition: ketypes.h:1030
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:551
#define XSTATE_MASK_LEGACY_FLOATING_POINT
Definition: ketypes.h:1282
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:92