ReactOS 0.4.16-dev-1489-g8fbbb41
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
62 /* Special initialization for XSAVES */
64 {
65 /* Set bit 63 in XCOMP_BV to mark the area as compacted.
66 XRSTORS requires this and will #GP otherwise. */
67 PXSAVE_AREA XSaveArea = (PXSAVE_AREA)Thread->StateSaveArea;
68 XSaveArea->Header.Reserved[0] = 0x8000000000000000ULL;
69 }
70
71 /* Check if this is a With-Context Thread */
72 if (Context)
73 {
74 PKUINIT_FRAME InitFrame;
75
76 /* Set up the Initial Frame */
77 InitFrame = ((PKUINIT_FRAME)Thread->InitialStack) - 1;
78 StartFrame = &InitFrame->StartFrame;
79 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
80
81 /* Save back the new value of the kernel stack. */
82 Thread->KernelStack = (PVOID)InitFrame;
83
84 /* Tell the thread it will run in User Mode */
85 Thread->PreviousMode = UserMode;
86
87 /* Set the Thread's NPX State */
88 Thread->NpxState = SharedUserData->XState.EnabledFeatures;
89 Thread->Header.NpxIrql = PASSIVE_LEVEL;
90
91 /* Make sure, we have control registers, disable debug registers */
92 ASSERT((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL);
93 ContextFlags = Context->ContextFlags & ~CONTEXT_DEBUG_REGISTERS;
94
95 /* Setup the Trap Frame */
96 TrapFrame = &InitFrame->TrapFrame;
97
98 /* Zero out the trap frame */
99 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
100 RtlZeroMemory(&InitFrame->ExceptionFrame, sizeof(KEXCEPTION_FRAME));
101
102 /* Set up a trap frame from the context. */
104 &InitFrame->ExceptionFrame,
105 TrapFrame,
106 CONTEXT_AMD64 | ContextFlags,
107 UserMode);
108
109 /* Set SS, DS, ES's RPL Mask properly */
110 TrapFrame->SegSs |= RPL_MASK;
111 TrapFrame->SegDs |= RPL_MASK;
112 TrapFrame->SegEs |= RPL_MASK;
113 TrapFrame->Dr7 = 0;
114
115 /* Set the previous mode as user */
116 TrapFrame->PreviousMode = UserMode;
117
118 /* Terminate the Exception Handler List */
119 TrapFrame->ExceptionFrame = 0;
120
121 /* KiThreadStartup returns to KiUserThreadStartupExit */
123
124 /* KiUserThreadStartupExit returns to KiServiceExit3 */
126 }
127 else
128 {
129 PKKINIT_FRAME InitFrame;
130
131 /* Set up the Initial Frame for the system thread */
132 InitFrame = ((PKKINIT_FRAME)Thread->InitialStack) - 1;
133 StartFrame = &InitFrame->StartFrame;
134 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
135
136 /* Save back the new value of the kernel stack. */
137 Thread->KernelStack = (PVOID)InitFrame;
138
139 /* Tell the thread it will run in Kernel Mode */
140 Thread->PreviousMode = KernelMode;
141
142 /* No NPX State */
143 Thread->NpxState = 0;
144
145 /* This must never return! */
147 }
148
149 /* Set up the Context Switch Frame */
150 CtxSwitchFrame->Return = (ULONG64)KiThreadStartup;
151 CtxSwitchFrame->ApcBypass = TRUE;
152
153 StartFrame->P1Home = (ULONG64)StartRoutine;
154 StartFrame->P2Home = (ULONG64)StartContext;
155 StartFrame->P3Home = 0;
156 StartFrame->P4Home = (ULONG64)SystemRoutine;
157 StartFrame->Reserved = 0;
158}
159
162 _In_ BOOLEAN ApcBypass,
163 _In_ PKTHREAD OldThread,
164 _In_ PKTHREAD NewThread)
165{
166 PKIPCR Pcr = (PKIPCR)KeGetPcr();
167 PKPROCESS OldProcess, NewProcess;
168
169 /* Setup ring 0 stack pointer */
170 Pcr->TssBase->Rsp0 = (ULONG64)NewThread->InitialStack;
171 Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
172
173 /* Save old thread's extended state */
174 if (OldThread->NpxState != 0)
175 {
176 KiSaveXState(OldThread->StateSaveArea, OldThread->NpxState);
177 }
178
179 /* Load new thread's extended state */
180 if (NewThread->NpxState != 0)
181 {
182 KiRestoreXState(NewThread->StateSaveArea, NewThread->NpxState);
183 }
184
185 /* Now we are the new thread. Check if it's in a new process */
186 OldProcess = OldThread->ApcState.Process;
187 NewProcess = NewThread->ApcState.Process;
188 if (OldProcess != NewProcess)
189 {
190 /* Switch address space and flush TLB */
191 __writecr3(NewProcess->DirectoryTableBase[0]);
192
193 /* Set new TSS fields */
194 //Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
195 }
196
197 /* Set TEB pointer and GS base */
198 Pcr->NtTib.Self = (PVOID)NewThread->Teb;
199 if (NewThread->Teb)
200 {
201 /* This will switch the usermode gs */
202 __writemsr(MSR_GS_SWAP, (ULONG64)NewThread->Teb);
203 }
204
205 /* Increase context switch count */
206 Pcr->ContextSwitches++;
207 NewThread->ContextSwitches++;
208
209 /* DPCs shouldn't be active */
210 if (Pcr->Prcb.DpcRoutineActive)
211 {
212 /* Crash the machine */
213 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
214 (ULONG_PTR)OldThread,
215 (ULONG_PTR)NewThread,
216 (ULONG_PTR)OldThread->InitialStack,
217 0);
218 }
219
220 /* Old thread os no longer busy */
221 OldThread->SwapBusy = FALSE;
222
223 /* Kernel APCs may be pending */
224 if (NewThread->ApcState.KernelApcPending)
225 {
226 /* Are APCs enabled? */
227 if ((NewThread->SpecialApcDisable == 0) &&
228 (ApcBypass == 0))
229 {
230 /* Return TRUE to indicate that we want APCs to be delivered */
231 return TRUE;
232 }
233
234 /* Request an APC interrupt to be delivered later */
236 }
237
238 /* Return stating that no kernel APCs are pending*/
239 return FALSE;
240}
241
242/* EOF */
243
244
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:161
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 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:1369
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 CONTEXT_AMD64
#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
* PXSAVE_AREA
Definition: ketypes.h:977
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:499
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:91