ReactOS 0.4.17-dev-684-ga6524ef
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#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
20extern void KiReloadWow64Fs();
21#endif
22
23typedef struct _KUINIT_FRAME
24{
29 //FX_SAVE_AREA FxSaveArea;
31
32typedef struct _KKINIT_FRAME
33{
36 //FX_SAVE_AREA FxSaveArea;
38
39/* FUNCTIONS *****************************************************************/
40
41VOID
44 IN PKSYSTEM_ROUTINE SystemRoutine,
46 IN PVOID StartContext,
48{
49 PKSTART_FRAME StartFrame;
50 PKSWITCH_FRAME CtxSwitchFrame;
51 PKTRAP_FRAME TrapFrame;
52 PKEXCEPTION_FRAME ExceptionFrame;
53 ULONG ContextFlags;
54 PVOID InitialStack;
55
56 /* Allocate space on the stack for the XSAVE area */
57 InitialStack = (PUCHAR)Thread->InitialStack - KeXStateLength;
58 InitialStack = ALIGN_DOWN_POINTER_BY(InitialStack, 64);
59 Thread->InitialStack = InitialStack;
60
61 /* Initialize the state save area */
62 Thread->StateSaveArea = InitialStack;
63 RtlZeroMemory(Thread->StateSaveArea, KeXStateLength);
64 Thread->StateSaveArea->MxCsr = INITIAL_MXCSR;
65 Thread->StateSaveArea->ControlWord = INITIAL_FPCSR;
66
67 /* Check if we use XSAVE */
69 {
70 /* Enable the mask for legacy floating point state */
71 PXSAVE_AREA XSaveArea = (PXSAVE_AREA)Thread->StateSaveArea;
72 XSaveArea->Header.Mask |= XSTATE_MASK_LEGACY_FLOATING_POINT;
73
74 /* Special initialization for XSAVES */
76 {
77 /* Set bit 63 in XCOMP_BV to mark the area as compacted.
78 XRSTORS requires this and will #GP otherwise.
79 Also mark legacy FP as compacted. */
80 XSaveArea->Header.CompactionMask |= 0x8000000000000000ULL |
82 }
83 }
84
85 /* Check if this is a With-Context Thread */
86 if (Context)
87 {
88 PKUINIT_FRAME InitFrame;
89
90 /* Set up the Initial Frame */
91 InitFrame = ((PKUINIT_FRAME)Thread->InitialStack) - 1;
92 StartFrame = &InitFrame->StartFrame;
93 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
94
95 /* Save back the new value of the kernel stack. */
96 Thread->KernelStack = (PVOID)InitFrame;
97
98 /* Tell the thread it will run in User Mode */
99 Thread->PreviousMode = UserMode;
100
101 /* Set the Thread's NPX State */
102 Thread->NpxState = SharedUserData->XState.EnabledFeatures;
103 Thread->Header.NpxIrql = PASSIVE_LEVEL;
104
105 /* Make sure, we have control registers, disable debug registers */
106 ASSERT((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL);
107 ContextFlags = Context->ContextFlags & ~CONTEXT_DEBUG_REGISTERS;
108
109 /* Zero-initialize the Trap Frame and exception frame */
110 TrapFrame = &InitFrame->TrapFrame;
111 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
112 ExceptionFrame = &InitFrame->ExceptionFrame;
113 RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME));
114
115 /* Copy integer registers */
116 TrapFrame->Rax = Context->Rax;
117 TrapFrame->Rcx = Context->Rcx;
118 TrapFrame->Rdx = Context->Rdx;
119 TrapFrame->Rbp = 0; // Context->Rbp; // 0 on Vista, copied on Win 10
120 TrapFrame->R8 = Context->R8;
121 TrapFrame->R9 = Context->R9;
122 TrapFrame->R10 = Context->R10;
123 TrapFrame->R11 = Context->R11;
124 ExceptionFrame->Rbx = Context->Rbx;
125 ExceptionFrame->Rsi = Context->Rsi;
126 ExceptionFrame->Rdi = Context->Rdi;
127 ExceptionFrame->R12 = Context->R12;
128 ExceptionFrame->R13 = Context->R13;
129 ExceptionFrame->R14 = Context->R14;
130 ExceptionFrame->R15 = Context->R15;
131
132 /* Copy RIP, RSP, EFLAGS */
133 TrapFrame->Rip = Context->Rip;
134 TrapFrame->Rsp = Context->Rsp;
135 TrapFrame->EFlags = Context->EFlags;
136
137 /* Sanitize EFLAGS */
139 TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
140
141 /* Set user mode segment selectors */
142 TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
143 TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
144 TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
145 TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
146 TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
147 TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
148
149 /* Clear DR7 */
150 TrapFrame->Dr7 = 0;
151
152 /* Initialize floating point state */
153 TrapFrame->MxCsr = INITIAL_MXCSR;
154
155 /* Set the previous mode as user */
156 TrapFrame->PreviousMode = UserMode;
157
158 /* Terminate the Exception Handler List */
159 TrapFrame->ExceptionFrame = 0;
160
161 /* KiThreadStartup returns to KiUserThreadStartupExit */
163
164 /* KiUserThreadStartupExit returns to KiServiceExit3 */
165 ExceptionFrame->Return = (ULONG64)KiServiceExit3;
166
167 /* Allocate home space on the stack */
168 TrapFrame->Rsp -= 5 * sizeof(PVOID);
169 }
170 else
171 {
172 PKKINIT_FRAME InitFrame;
173
174 /* Set up the Initial Frame for the system thread */
175 InitFrame = ((PKKINIT_FRAME)Thread->InitialStack) - 1;
176 StartFrame = &InitFrame->StartFrame;
177 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
178
179 /* Save back the new value of the kernel stack. */
180 Thread->KernelStack = (PVOID)InitFrame;
181
182 /* Tell the thread it will run in Kernel Mode */
183 Thread->PreviousMode = KernelMode;
184
185 /* No NPX State */
186 Thread->NpxState = 0;
187
188 /* This must never return! */
190 }
191
192 /* Set up the Context Switch Frame */
193 CtxSwitchFrame->Return = (ULONG64)KiThreadStartup;
194 CtxSwitchFrame->ApcBypass = TRUE;
195
196 StartFrame->P1Home = (ULONG64)StartRoutine;
197 StartFrame->P2Home = (ULONG64)StartContext;
198 StartFrame->P3Home = 0;
199 StartFrame->P4Home = (ULONG64)SystemRoutine;
200 StartFrame->Reserved = 0;
201}
202
205 _In_ BOOLEAN ApcBypass,
206 _In_ PKTHREAD OldThread,
207 _In_ PKTHREAD NewThread)
208{
209 PKIPCR Pcr = (PKIPCR)KeGetPcr();
210 PKPROCESS OldProcess, NewProcess;
211 ULONG64 CurrentCycleTime, ElapsedCycles;
212
213 /* Setup ring 0 stack pointer */
214 Pcr->TssBase->Rsp0 = (ULONG64)NewThread->InitialStack;
215 Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
216
217 /* Save old thread's extended state */
218 if (OldThread->NpxState != 0)
219 {
220 KiSaveXState(OldThread->StateSaveArea, OldThread->NpxState);
221 }
222
223 /* Load new thread's extended state */
224 if (NewThread->NpxState != 0)
225 {
226 KiRestoreXState(NewThread->StateSaveArea, NewThread->NpxState);
227 }
228
229 /* Now we are the new thread. Check if it's in a new process */
230 OldProcess = OldThread->ApcState.Process;
231 NewProcess = NewThread->ApcState.Process;
232 if (OldProcess != NewProcess)
233 {
234 /* Switch address space and flush TLB */
235 __writecr3(NewProcess->DirectoryTableBase[0]);
236
237 /* Set new TSS fields */
238 //Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
239 }
240
241 /* Update the old thread's cycle time */
242 CurrentCycleTime = __rdtsc();
243 ElapsedCycles = CurrentCycleTime - Pcr->Prcb.StartCycles;
244 ((PETHREAD)OldThread)->CycleTime += ElapsedCycles;
245 InterlockedAdd64((PLONG64)&((PEPROCESS)OldProcess)->CycleTime, ElapsedCycles);
246 Pcr->Prcb.StartCycles = CurrentCycleTime;
247
248 /* Set TEB pointer and GS base */
249 Pcr->NtTib.Self = (PVOID)NewThread->Teb;
250 if (NewThread->Teb)
251 {
252 /* This will switch the usermode gs */
253 __writemsr(MSR_GS_SWAP, (ULONG64)NewThread->Teb);
254
255#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
256 PEPROCESS ENewProcess = (PEPROCESS)NewProcess;
257
258 if (ENewProcess->Wow64Process != NULL)
259 {
260 ULONG_PTR Base = (ULONG_PTR)PS_GET_TEB32_FROM_TEB(NewThread->Teb);
261
263 CmTebEntry->LimitLow = 0xFFFF;
264 CmTebEntry->Bits.LimitHigh = 0xFFFF;
265
266 CmTebEntry->BaseLow = Base & 0xFFFF;
267 CmTebEntry->Bits.BaseMiddle = (Base & 0xFF0000) >> 16;
268 CmTebEntry->Bits.BaseHigh = (Base & 0xFF000000) >> 24;
269
270 KiReloadWow64Fs();
271 }
272#endif
273 }
274
275 /* Increase context switch count */
276 Pcr->ContextSwitches++;
277 NewThread->ContextSwitches++;
278
279 /* DPCs shouldn't be active */
280 if (Pcr->Prcb.DpcRoutineActive)
281 {
282 /* Crash the machine */
283 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
284 (ULONG_PTR)OldThread,
285 (ULONG_PTR)NewThread,
286 (ULONG_PTR)OldThread->InitialStack,
287 0);
288 }
289
290 /* Old thread os no longer busy */
291 OldThread->SwapBusy = FALSE;
292
293 /* Kernel APCs may be pending */
294 if (NewThread->ApcState.KernelApcPending)
295 {
296 /* Are APCs enabled? */
297 if ((NewThread->SpecialApcDisable == 0) &&
298 (ApcBypass == 0))
299 {
300 /* Return TRUE to indicate that we want APCs to be delivered */
301 return TRUE;
302 }
303
304 /* Request an APC interrupt to be delivered later */
306 }
307
308 /* Return stating that no kernel APCs are pending*/
309 return FALSE;
310}
311
312/* EOF */
313
314
#define EFLAGS_INTERRUPT_MASK
#define KGDT64_R3_CODE
#define KGDT64_R3_DATA
#define KGDT64_R3_CMTEB
#define RPL_MASK
unsigned char BOOLEAN
Definition: actypes.h:127
ULONG64 KeFeatureBits
Definition: krnlinit.c:22
FORCEINLINE VOID KiRestoreXState(_In_ PVOID Buffer, _In_ ULONG64 ComponentMask)
Definition: intrin_i.h:91
FORCEINLINE PKGDTENTRY64 KiGetGdtEntry(PVOID pGdt, USHORT Selector)
Definition: intrin_i.h:13
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:204
VOID NTAPI KiInitializeContextThread(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context)
Definition: thrdini.c:43
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
__int64 * PLONG64
Definition: basetsd.h:177
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
#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
#define InterlockedAdd64
Definition: interlocked.h:72
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
PPC_QUAL unsigned long long __rdtsc(void)
Definition: intrin_ppc.h:688
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1826
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
#define EFLAGS_USER_THREAD_SANITIZE
Definition: ketypes.h:220
#define KF_XSTATE
Definition: ketypes.h:55
#define MSR_GS_SWAP
Definition: ketypes.h:269
struct _KIPCR * PKIPCR
#define KF_XSAVES
Definition: ketypes.h:68
#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:881
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2486
#define _In_
Definition: no_sal2.h:158
#define CONTEXT_CONTROL
Definition: nt_native.h:1372
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
SIZE_T KeXStateLength
Definition: stubs.c:18
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
#define INITIAL_FPCSR
#define SharedUserData
#define INITIAL_MXCSR
_In_ PVOID Context
Definition: storport.h:2269
ULONG64 Return
Definition: ketypes.h:1079
ULONG ContextSwitches
Definition: ketypes.h:1006
KPRCB Prcb
Definition: ketypes.h:1003
union _KGDTENTRY64 * GdtBase
Definition: ketypes.h:974
struct _KTSS64 * TssBase
Definition: ketypes.h:975
NT_TIB NtTib
Definition: ketypes.h:971
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:34
KSTART_FRAME StartFrame
Definition: thrdini.c:35
UINT64 RspBase
Definition: ketypes.h:680
UINT64 StartCycles
Definition: ketypes.h:859
UCHAR DpcRoutineActive
Definition: ketypes.h:792
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2234
ULONG64 P2Home
Definition: ketypes.h:1153
ULONG64 Reserved
Definition: ketypes.h:1156
ULONG64 P1Home
Definition: ketypes.h:1152
ULONG64 Return
Definition: ketypes.h:1157
ULONG64 P4Home
Definition: ketypes.h:1155
ULONG64 P3Home
Definition: ketypes.h:1154
ULONG64 Return
Definition: ketypes.h:1170
KIRQL ApcBypass
Definition: ketypes.h:1167
UINT64 Rsp
Definition: ketypes.h:491
CHAR PreviousMode
Definition: ketypes.h:418
UINT64 Rbp
Definition: ketypes.h:477
UINT64 Rdx
Definition: ketypes.h:425
ULONG EFlags
Definition: ketypes.h:489
USHORT SegSs
Definition: ketypes.h:492
UINT64 ExceptionFrame
Definition: ketypes.h:481
UINT64 Dr7
Definition: ketypes.h:452
USHORT SegCs
Definition: ketypes.h:485
UINT64 Rax
Definition: ketypes.h:423
UINT64 R10
Definition: ketypes.h:428
UINT64 Rip
Definition: ketypes.h:484
USHORT SegEs
Definition: ketypes.h:470
USHORT SegFs
Definition: ketypes.h:471
USHORT SegGs
Definition: ketypes.h:472
UINT64 R9
Definition: ketypes.h:427
USHORT SegDs
Definition: ketypes.h:469
ULONG MxCsr
Definition: ketypes.h:422
UINT64 R8
Definition: ketypes.h:426
UINT64 Rcx
Definition: ketypes.h:424
UINT64 R11
Definition: ketypes.h:429
KTRAP_FRAME TrapFrame
Definition: thrdini.c:28
KSTART_FRAME StartFrame
Definition: thrdini.c:26
KEXCEPTION_FRAME ExceptionFrame
Definition: thrdini.c:27
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:25
struct _NT_TIB * Self
Definition: compat.h:720
ULONG CycleTime
Definition: svw_pata.c:43
#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
USHORT LimitLow
Definition: ketypes.h:512
struct _KGDTENTRY64::@2539::@2541::@2544 Bits
USHORT BaseLow
Definition: ketypes.h:513
* PXSAVE_AREA
Definition: ketypes.h:1046
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:567
#define XSTATE_MASK_LEGACY_FLOATING_POINT
Definition: ketypes.h:1298
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:92