ReactOS  r75214
thrdini.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/ke/arm/thrdini.c
5  * PURPOSE: Implements thread context setup and startup for ARM machines
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS ********************************************************************/
16 
17 typedef struct _KSWITCHFRAME
18 {
23 
24 typedef struct _KUINIT_FRAME
25 {
30 
31 typedef struct _KKINIT_FRAME
32 {
35 
36 /* FUNCTIONS ******************************************************************/
37 
38 VOID
39 NTAPI
41 
42 VOID
45  IN PKTHREAD OldThread,
46  IN PKTHREAD NewThread
47 );
48 
49 
50 /* FIXME: THIS IS TOTALLY BUSTED NOW */
51 VOID
52 NTAPI
54  IN PKSYSTEM_ROUTINE SystemRoutine,
56  IN PVOID StartContext,
57  IN PCONTEXT ContextPointer)
58 {
59  PKTRAP_FRAME TrapFrame;
60  PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame;
61 
62  //
63  // Check if this is a user thread
64  //
65  if (ContextPointer)
66  {
67  //
68  // Setup the initial frame
69  //
70  PKUINIT_FRAME InitFrame;
71  InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
72  sizeof(KUINIT_FRAME));
73 
74  //
75  // Setup the Trap Frame and Exception frame
76  //
77  TrapFrame = &InitFrame->TrapFrame;
78  ExceptionFrame = &InitFrame->ExceptionFrame;
79 
81  // Zero out the trap frame and exception frame
82  //
83  RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
84  RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME));
85 
86  //
87  // Set up a trap frame from the context
88  //
89  KeContextToTrapFrame(ContextPointer,
90  ExceptionFrame,
91  TrapFrame,
92  ContextPointer->ContextFlags | CONTEXT_CONTROL,
93  UserMode);
94 
95  //
96  // Set the previous mode as user
97  //
98  //TrapFrame->PreviousMode = UserMode;
99  Thread->PreviousMode = UserMode;
100 
101  //
102  // Clear the return address
103  //
104  ExceptionFrame->Return = 0;
105 
106  //
107  // Context switch frame to setup below
108  //
109  CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
110  }
111  else
112  {
113  //
114  // Set up the Initial Frame for the system thread
115  //
116  PKKINIT_FRAME InitFrame;
117  InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
118  sizeof(KKINIT_FRAME));
119 
120  //
121  // Set the previous mode as kernel
122  //
123  Thread->PreviousMode = KernelMode;
124 
125  //
126  // Context switch frame to setup below
127  //
128  CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
129  }
130 
131  //
132  // Now setup the context switch frame
133  //
134  CtxSwitchFrame->Return = (ULONG)KiThreadStartup;
135  CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame);
136 
137  //
138  // Set the parameters
139  //
140  CtxSwitchFrame->R4 = (ULONG)ContextPointer;
141  CtxSwitchFrame->R5 = (ULONG)StartContext;
142  CtxSwitchFrame->R6 = (ULONG)StartRoutine;
143  CtxSwitchFrame->R7 = (ULONG)SystemRoutine;
144 
145  //
146  // Save back the new value of the kernel stack
147  //
148  Thread->KernelStack = (PVOID)CtxSwitchFrame;
149 }
150 
151 VOID
152 FASTCALL
154 {
155  PKPRCB Prcb = KeGetCurrentPrcb();
156  PKTHREAD OldThread, NewThread;
157 
158  /* Now loop forever */
159  while (TRUE)
160  {
161  /* Start of the idle loop: disable interrupts */
162  _enable();
163  YieldProcessor();
164  YieldProcessor();
165  _disable();
166 
167  /* Check for pending timers, pending DPCs, or pending ready threads */
168  if ((Prcb->DpcData[0].DpcQueueDepth) ||
169  (Prcb->TimerRequest) ||
170  (Prcb->DeferredReadyListHead.Next))
171  {
172  /* Quiesce the DPC software interrupt */
174 
175  /* Handle it */
176  KiRetireDpcList(Prcb);
177  }
178 
179  /* Check if a new thread is scheduled for execution */
180  if (Prcb->NextThread)
181  {
182  /* Enable interrupts */
183  _enable();
184 
185  /* Capture current thread data */
186  OldThread = Prcb->CurrentThread;
187  NewThread = Prcb->NextThread;
188 
189  /* Set new thread data */
190  Prcb->NextThread = NULL;
191  Prcb->CurrentThread = NewThread;
192 
193  /* The thread is now running */
194  NewThread->State = Running;
195 
196  /* Switch away from the idle thread */
197  KiSwapContext(APC_LEVEL, OldThread);
198  }
199  else
200  {
201  /* Continue staying idle. Note the HAL returns with interrupts on */
202  Prcb->PowerState.IdleFunction(&Prcb->PowerState);
203  }
204  }
205 }
206 
207 BOOLEAN
208 FASTCALL
210  IN PKSWITCHFRAME SwitchFrame)
211 {
212  PKIPCR Pcr = (PKIPCR)KeGetPcr();
213  PKPROCESS OldProcess, NewProcess;
214  PKTHREAD NewThread;
215  ARM_TTB_REGISTER TtbRegister;
216 
217  /* We are on the new thread stack now */
218  NewThread = Pcr->Prcb.CurrentThread;
219 
220  /* Now we are the new thread. Check if it's in a new process */
221  OldProcess = OldThread->ApcState.Process;
222  NewProcess = NewThread->ApcState.Process;
223  if (OldProcess != NewProcess)
224  {
225  TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
226  ASSERT(TtbRegister.Reserved == 0);
228  }
229 
230  /* Increase thread context switches */
231  NewThread->ContextSwitches++;
232 
233  /* DPCs shouldn't be active */
234  if (Pcr->Prcb.DpcRoutineActive)
235  {
236  /* Crash the machine */
237  KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
238  (ULONG_PTR)OldThread,
239  (ULONG_PTR)NewThread,
240  (ULONG_PTR)OldThread->InitialStack,
241  0);
242  }
243 
244  /* Kernel APCs may be pending */
245  if (NewThread->ApcState.KernelApcPending)
246  {
247  /* Are APCs enabled? */
248  if (!NewThread->SpecialApcDisable)
249  {
250  /* Request APC delivery */
251  if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
252  return TRUE;
253  }
254  }
255 
256  /* Return */
257  return FALSE;
258 }
259 
260 VOID
261 FASTCALL
262 KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
263  IN ULONG_PTR OldThreadAndApcFlag)
264 {
265  PKIPCR Pcr = (PKIPCR)KeGetPcr();
266  PKTHREAD OldThread, NewThread;
267 
268  /* Save APC bypass disable */
269  SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
270 
271  /* Increase context switch count and check if tracing is enabled */
272  Pcr->Prcb.KeContextSwitches++;
273 #if 0
274  if (Pcr->PerfGlobalGroupMask)
275  {
276  /* We don't support this yet on x86 either */
277  DPRINT1("WMI Tracing not supported\n");
278  ASSERT(FALSE);
279  }
280 #endif // 0
281 
282  /* Get thread pointers */
283  OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
284  NewThread = Pcr->Prcb.CurrentThread;
285 
286  /* Get the old thread and set its kernel stack */
287  OldThread->KernelStack = SwitchFrame;
288 
289  /* Do the switch */
290  KiSwitchThreads(OldThread, NewThread->KernelStack);
291 }
292 
293 VOID
294 NTAPI
296 {
297  PKIPCR Pcr = (PKIPCR)KeGetPcr();
298  PKPRCB Prcb = &Pcr->Prcb;
299  PKTHREAD NewThread, OldThread;
300 
301  /* Disable interrupts */
302  _disable();
303 
304  /* Check for pending timers, pending DPCs, or pending ready threads */
305  if ((Prcb->DpcData[0].DpcQueueDepth) ||
306  (Prcb->TimerRequest) ||
307  (Prcb->DeferredReadyListHead.Next))
308  {
309  /* Retire DPCs while under the DPC stack */
310  //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
311  // FIXME!!! //
312  KiRetireDpcList(Prcb);
313  }
314 
315  /* Re-enable interrupts */
316  _enable();
317 
318  /* Check for quantum end */
319  if (Prcb->QuantumEnd)
320  {
321  /* Handle quantum end */
322  Prcb->QuantumEnd = FALSE;
323  KiQuantumEnd();
324  }
325  else if (Prcb->NextThread)
326  {
327  /* Capture current thread data */
328  OldThread = Prcb->CurrentThread;
329  NewThread = Prcb->NextThread;
330 
331  /* Set new thread data */
332  Prcb->NextThread = NULL;
333  Prcb->CurrentThread = NewThread;
334 
335  /* The thread is now running */
336  NewThread->State = Running;
337  OldThread->WaitReason = WrDispatchInt;
338 
339  /* Make the old thread ready */
340  KxQueueReadyThread(OldThread, Prcb);
341 
342  /* Swap to the new thread */
343  KiSwapContext(APC_LEVEL, OldThread);
344  }
345 }
346 
347 /* EOF */
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
DWORD *typedef PVOID
Definition: winlogon.h:52
VOID FASTCALL KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, IN ULONG_PTR OldThreadAndApcFlag)
Definition: thrdini.c:262
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:18
#define IN
Definition: typedefs.h:39
#define TRUE
Definition: types.h:120
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:1383
KEXCEPTION_FRAME CtxSwitchFrame
Definition: thrdini.c:33
SHORT SpecialApcDisable
Definition: ketypes.h:1052
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
KDPC_DATA DpcData[2]
Definition: ketypes.h:676
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
struct _KIPCR * PKIPCR
VOID NTAPI KiQuantumEnd(VOID)
Definition: dpc.c:465
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:795
UCHAR QuantumEnd
Definition: ketypes.h:696
BOOLEAN ApcBypassDisable
Definition: thrdini.c:20
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 FASTCALL
Definition: nt_native.h:50
struct _KTHREAD * NextThread
Definition: ketypes.h:567
#define KeGetPcr()
Definition: ke.h:25
uint32_t ULONG_PTR
Definition: typedefs.h:64
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
FORCEINLINE VOID KxQueueReadyThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: ke_x.h:1343
struct _KSWITCHFRAME * PKSWITCHFRAME
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
ULONG64 Return
Definition: ketypes.h:958
#define FALSE
Definition: types.h:117
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:472
ULONG64 Return
Definition: ketypes.h:1027
KAPC_STATE ApcState
Definition: ketypes.h:969
PVOID RetAddr
Definition: thrdini.c:21
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
smooth NULL
Definition: ftsmooth.c:513
PVOID KernelStack
Definition: ketypes.h:939
ULONG KeContextSwitches
Definition: ketypes.h:648
KEXCEPTION_FRAME CtxSwitchFrame
Definition: thrdini.c:26
UCHAR WaitReason
Definition: ketypes.h:1249
unsigned char BOOLEAN
#define CONTEXT_CONTROL
Definition: compat.h:265
UINT64 TimerRequest
Definition: ketypes.h:691
VOID(NTAPI * PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
Definition: ketypes.h:625
KTRAP_FRAME TrapFrame
Definition: thrdini.c:21
struct _KKINIT_FRAME KKINIT_FRAME
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL KiIdleLoop(VOID)
Definition: thrdini.c:153
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:628
UCHAR DpcRoutineActive
Definition: ketypes.h:688
KPRCB Prcb
Definition: ketypes.h:889
VOID NTAPI KiDispatchInterrupt(VOID)
Definition: thrdini.c:295
struct _KUINIT_FRAME * PKUINIT_FRAME
struct _KUINIT_FRAME KUINIT_FRAME
struct _KKINIT_FRAME * PKKINIT_FRAME
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:628
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
VOID FASTCALL KiSwitchThreads(IN PKTHREAD OldThread, IN PKTHREAD NewThread)
volatile ULONG DpcQueueDepth
Definition: ketypes.h:746
BOOLEAN FASTCALL KiSwapContextExit(IN PKTHREAD OldThread, IN PKSWITCHFRAME SwitchFrame)
Definition: thrdini.c:209
PVOID ExceptionList
Definition: thrdini.c:19
#define DPRINT1
Definition: precomp.h:8
PPROCESSOR_IDLE_FUNCTION IdleFunction
Definition: potypes.h:54
PVOID PerfGlobalGroupMask
Definition: ketypes.h:742
VOID FASTCALL HalClearSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:282
volatile UCHAR State
Definition: ketypes.h:997
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
ULONG ContextSwitches
Definition: ketypes.h:996
struct _KSWITCHFRAME KSWITCHFRAME
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PVOID InitialStack
Definition: ketypes.h:937
#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:90
VOID FASTCALL KiRetireDpcList(IN PKPRCB Prcb)
Definition: dpc.c:561
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:27
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145