ReactOS  r73429
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  /* Initialize the idle loop: disable interrupts */
159  _enable();
160  YieldProcessor();
161  YieldProcessor();
162  _disable();
163 
164  /* Now loop forever */
165  while (TRUE)
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  /* We are back in the idle thread -- disable interrupts again */
200  _enable();
201  YieldProcessor();
202  YieldProcessor();
203  _disable();
204  }
205  else
206  {
207  /* Continue staying idle. Note the HAL returns with interrupts on */
208  Prcb->PowerState.IdleFunction(&Prcb->PowerState);
209  }
210  }
211 }
212 
213 BOOLEAN
214 FASTCALL
216  IN PKSWITCHFRAME SwitchFrame)
217 {
218  PKIPCR Pcr = (PKIPCR)KeGetPcr();
219  PKPROCESS OldProcess, NewProcess;
220  PKTHREAD NewThread;
221  ARM_TTB_REGISTER TtbRegister;
222 
223  /* We are on the new thread stack now */
224  NewThread = Pcr->Prcb.CurrentThread;
225 
226  /* Now we are the new thread. Check if it's in a new process */
227  OldProcess = OldThread->ApcState.Process;
228  NewProcess = NewThread->ApcState.Process;
229  if (OldProcess != NewProcess)
230  {
231  TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
232  ASSERT(TtbRegister.Reserved == 0);
234  }
235 
236  /* Increase thread context switches */
237  NewThread->ContextSwitches++;
238 
239  /* DPCs shouldn't be active */
240  if (Pcr->Prcb.DpcRoutineActive)
241  {
242  /* Crash the machine */
243  KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
244  (ULONG_PTR)OldThread,
245  (ULONG_PTR)NewThread,
246  (ULONG_PTR)OldThread->InitialStack,
247  0);
248  }
249 
250  /* Kernel APCs may be pending */
251  if (NewThread->ApcState.KernelApcPending)
252  {
253  /* Are APCs enabled? */
254  if (!NewThread->SpecialApcDisable)
255  {
256  /* Request APC delivery */
257  if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
258  return TRUE;
259  }
260  }
261 
262  /* Return */
263  return FALSE;
264 }
265 
266 VOID
267 FASTCALL
268 KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
269  IN ULONG_PTR OldThreadAndApcFlag)
270 {
271  PKIPCR Pcr = (PKIPCR)KeGetPcr();
272  PKTHREAD OldThread, NewThread;
273 
274  /* Save APC bypass disable */
275  SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
276 
277  /* Increase context switch count and check if tracing is enabled */
278  Pcr->Prcb.KeContextSwitches++;
279 #if 0
280  if (Pcr->PerfGlobalGroupMask)
281  {
282  /* We don't support this yet on x86 either */
283  DPRINT1("WMI Tracing not supported\n");
284  ASSERT(FALSE);
285  }
286 #endif // 0
287 
288  /* Get thread pointers */
289  OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
290  NewThread = Pcr->Prcb.CurrentThread;
291 
292  /* Get the old thread and set its kernel stack */
293  OldThread->KernelStack = SwitchFrame;
294 
295  /* Do the switch */
296  KiSwitchThreads(OldThread, NewThread->KernelStack);
297 }
298 
299 VOID
300 NTAPI
302 {
303  PKIPCR Pcr = (PKIPCR)KeGetPcr();
304  PKPRCB Prcb = &Pcr->Prcb;
305  PKTHREAD NewThread, OldThread;
306 
307  /* Disable interrupts */
308  _disable();
309 
310  /* Check for pending timers, pending DPCs, or pending ready threads */
311  if ((Prcb->DpcData[0].DpcQueueDepth) ||
312  (Prcb->TimerRequest) ||
313  (Prcb->DeferredReadyListHead.Next))
314  {
315  /* Retire DPCs while under the DPC stack */
316  //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
317  // FIXME!!! //
318  KiRetireDpcList(Prcb);
319  }
320 
321  /* Re-enable interrupts */
322  _enable();
323 
324  /* Check for quantum end */
325  if (Prcb->QuantumEnd)
326  {
327  /* Handle quantum end */
328  Prcb->QuantumEnd = FALSE;
329  KiQuantumEnd();
330  }
331  else if (Prcb->NextThread)
332  {
333  /* Capture current thread data */
334  OldThread = Prcb->CurrentThread;
335  NewThread = Prcb->NextThread;
336 
337  /* Set new thread data */
338  Prcb->NextThread = NULL;
339  Prcb->CurrentThread = NewThread;
340 
341  /* The thread is now running */
342  NewThread->State = Running;
343  OldThread->WaitReason = WrDispatchInt;
344 
345  /* Make the old thread ready */
346  KxQueueReadyThread(OldThread, Prcb);
347 
348  /* Swap to the new thread */
349  KiSwapContext(APC_LEVEL, OldThread);
350  }
351 }
352 
353 /* 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:268
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:18
#define IN
Definition: typedefs.h:39
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
#define TRUE
Definition: numbers.c:17
VOID NTAPI KiQuantumEnd(VOID)
Definition: dpc.c:449
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
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:472
ULONG64 Return
Definition: ketypes.h:1027
KAPC_STATE ApcState
Definition: ketypes.h:969
#define NULL
Definition: mystdio.h:57
PVOID RetAddr
Definition: thrdini.c:21
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
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:301
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:215
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
#define FALSE
Definition: numbers.c:16
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:545
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:27
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145