ReactOS  0.4.15-dev-1367-g07cc0b5
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 
16 typedef struct _KUINIT_FRAME
17 {
22  //FX_SAVE_AREA FxSaveArea;
24 
25 typedef struct _KKINIT_FRAME
26 {
29  //FX_SAVE_AREA FxSaveArea;
31 
32 /* FUNCTIONS *****************************************************************/
33 
34 VOID
35 NTAPI
37  IN PKSYSTEM_ROUTINE SystemRoutine,
39  IN PVOID StartContext,
41 {
42  //PFX_SAVE_AREA FxSaveArea;
43  //PFXSAVE_FORMAT FxSaveFormat;
44  PKSTART_FRAME StartFrame;
45  PKSWITCH_FRAME CtxSwitchFrame;
46  PKTRAP_FRAME TrapFrame;
47  ULONG ContextFlags;
48 
49  /* Check if this is a With-Context Thread */
50  if (Context)
51  {
52  PKUINIT_FRAME InitFrame;
53 
54  /* Set up the Initial Frame */
55  InitFrame = ((PKUINIT_FRAME)Thread->InitialStack) - 1;
56  StartFrame = &InitFrame->StartFrame;
57  CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
58 
59  /* Save back the new value of the kernel stack. */
60  Thread->KernelStack = (PVOID)InitFrame;
61 
62  /* Tell the thread it will run in User Mode */
63  Thread->PreviousMode = UserMode;
64 
65  // FIXME Setup the Fx Area
66 
67  /* Set the Thread's NPX State */
68  Thread->NpxState = 0xA;
69  Thread->Header.NpxIrql = PASSIVE_LEVEL;
70 
71  /* Make sure, we have control registers, disable debug registers */
72  ASSERT((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL);
73  ContextFlags = Context->ContextFlags & ~CONTEXT_DEBUG_REGISTERS;
74 
75  /* Setup the Trap Frame */
76  TrapFrame = &InitFrame->TrapFrame;
77 
78  /* Zero out the trap frame */
79  RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
80  RtlZeroMemory(&InitFrame->ExceptionFrame, sizeof(KEXCEPTION_FRAME));
81 
82  /* Set up a trap frame from the context. */
84  &InitFrame->ExceptionFrame,
85  TrapFrame,
86  CONTEXT_AMD64 | ContextFlags,
87  UserMode);
88 
89  /* Set SS, DS, ES's RPL Mask properly */
90  TrapFrame->SegSs |= RPL_MASK;
91  TrapFrame->SegDs |= RPL_MASK;
92  TrapFrame->SegEs |= RPL_MASK;
93  TrapFrame->Dr7 = 0;
94 
95  /* Set the previous mode as user */
96  TrapFrame->PreviousMode = UserMode;
97 
98  /* Terminate the Exception Handler List */
99  TrapFrame->ExceptionFrame = 0;
100 
101  /* We return to ... */
102  StartFrame->Return = (ULONG64)KiServiceExit2;
103  }
104  else
105  {
106  PKKINIT_FRAME InitFrame;
107 
108  /* Set up the Initial Frame for the system thread */
109  InitFrame = ((PKKINIT_FRAME)Thread->InitialStack) - 1;
110  StartFrame = &InitFrame->StartFrame;
111  CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
112 
113  /* Save back the new value of the kernel stack. */
114  Thread->KernelStack = (PVOID)InitFrame;
115 
116  /* Tell the thread it will run in Kernel Mode */
117  Thread->PreviousMode = KernelMode;
118 
119  // FIXME Setup the Fx Area
120 
121  /* No NPX State */
122  Thread->NpxState = 0xA;
123 
124  /* We have no return address! */
125  StartFrame->Return = 0;
126  }
127 
128  /* Set up the Context Switch Frame */
129  CtxSwitchFrame->Return = (ULONG64)KiThreadStartup;
130  CtxSwitchFrame->ApcBypass = FALSE;
131 
132  StartFrame->P1Home = (ULONG64)StartRoutine;
133  StartFrame->P2Home = (ULONG64)StartContext;
134  StartFrame->P3Home = 0;
135  StartFrame->P4Home = (ULONG64)SystemRoutine;
136  StartFrame->Reserved = 0;
137 }
138 
139 BOOLEAN
141  _In_ BOOLEAN ApcBypass,
142  _In_ PKTHREAD OldThread,
143  _In_ PKTHREAD NewThread)
144 {
145  PKIPCR Pcr = (PKIPCR)KeGetPcr();
146  PKPROCESS OldProcess, NewProcess;
147 
148  /* Setup ring 0 stack pointer */
149  Pcr->TssBase->Rsp0 = (ULONG64)NewThread->InitialStack; // FIXME: NPX save area?
150  Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
151 
152  /* Now we are the new thread. Check if it's in a new process */
153  OldProcess = OldThread->ApcState.Process;
154  NewProcess = NewThread->ApcState.Process;
155  if (OldProcess != NewProcess)
156  {
157  /* Switch address space and flush TLB */
158  __writecr3(NewProcess->DirectoryTableBase[0]);
159 
160  /* Set new TSS fields */
161  //Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
162  }
163 
164  /* Set TEB pointer and GS base */
165  Pcr->NtTib.Self = (PVOID)NewThread->Teb;
166  if (NewThread->Teb)
167  {
168  /* This will switch the usermode gs */
169  __writemsr(MSR_GS_SWAP, (ULONG64)NewThread->Teb);
170  }
171 
172  /* Increase context switch count */
173  Pcr->ContextSwitches++;
174  NewThread->ContextSwitches++;
175 
176  /* DPCs shouldn't be active */
177  if (Pcr->Prcb.DpcRoutineActive)
178  {
179  /* Crash the machine */
180  KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
181  (ULONG_PTR)OldThread,
182  (ULONG_PTR)NewThread,
183  (ULONG_PTR)OldThread->InitialStack,
184  0);
185  }
186 
187  /* Kernel APCs may be pending */
188  if (NewThread->ApcState.KernelApcPending)
189  {
190  /* Are APCs enabled? */
191  if ((NewThread->SpecialApcDisable == 0) &&
192  (ApcBypass == 0))
193  {
194  /* Return TRUE to indicate that we want APCs to be delivered */
195  return TRUE;
196  }
197 
198  /* Request an APC interrupt to be delivered later */
200  }
201 
202  /* Return stating that no kernel APCs are pending*/
203  return FALSE;
204 }
205 
206 /* EOF */
207 
208 
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
struct _NT_TIB * Self
Definition: compat.h:579
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:18
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define IN
Definition: typedefs.h:39
ULONG64 P4Home
Definition: ketypes.h:1033
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:1977
KIRQL ApcBypass
Definition: ketypes.h:1045
KEXCEPTION_FRAME ExceptionFrame
Definition: thrdini.c:20
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:87
#define TRUE
Definition: types.h:120
struct _KIPCR * PKIPCR
#define CONTEXT_AMD64
VOID NTAPI KiInitializeContextThread(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context)
Definition: thrdini.c:36
#define KeGetPcr()
Definition: ke.h:25
struct _KTSS64 * TssBase
Definition: ketypes.h:861
uint32_t ULONG_PTR
Definition: typedefs.h:65
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1723
VOID(NTAPI * PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
Definition: ketypes.h:625
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:487
ULONG64 Return
Definition: ketypes.h:1048
KSTART_FRAME StartFrame
Definition: thrdini.c:19
USHORT SegEs
Definition: ketypes.h:365
ULONG64 P3Home
Definition: ketypes.h:1032
#define RPL_MASK
Definition: ketypes.h:69
unsigned char BOOLEAN
void * PVOID
Definition: retypes.h:9
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
BOOLEAN KiSwapContextResume(_In_ BOOLEAN ApcBypass, _In_ PKTHREAD OldThread, _In_ PKTHREAD NewThread)
Definition: thrdini.c:140
KTRAP_FRAME TrapFrame
Definition: thrdini.c:21
struct _KKINIT_FRAME KKINIT_FRAME
ULONG64 P2Home
Definition: ketypes.h:1031
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
unsigned __int64 ULONG64
Definition: imports.h:198
UCHAR DpcRoutineActive
Definition: ketypes.h:688
KPRCB Prcb
Definition: ketypes.h:889
#define CONTEXT_DEBUG_REGISTERS
Definition: nt_native.h:1373
struct _KUINIT_FRAME * PKUINIT_FRAME
ULONG64 Return
Definition: ketypes.h:1035
USHORT SegDs
Definition: ketypes.h:364
KSTART_FRAME StartFrame
Definition: thrdini.c:28
struct _KUINIT_FRAME KUINIT_FRAME
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
struct _KKINIT_FRAME * PKKINIT_FRAME
#define _In_
Definition: no_sal2.h:158
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
USHORT SegSs
Definition: ketypes.h:387
ULONG64 Reserved
Definition: ketypes.h:1034
#define KiServiceExit2
Definition: ke.h:5
UINT64 ExceptionFrame
Definition: ketypes.h:376
ULONG ContextSwitches
Definition: ketypes.h:892
ULONG64 P1Home
Definition: ketypes.h:1030
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UINT64 Dr7
Definition: ketypes.h:347
NT_TIB NtTib
Definition: ketypes.h:857
#define MSR_GS_SWAP
Definition: ketypes.h:189
UINT64 RspBase
Definition: ketypes.h:576
#define APC_LEVEL
Definition: env_spec_w32.h:695
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
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:27
CHAR PreviousMode
Definition: ketypes.h:313