Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014
00015
00016
00017 typedef struct _KSWITCHFRAME
00018 {
00019 PVOID ExceptionList;
00020 BOOLEAN ApcBypassDisable;
00021 PVOID RetAddr;
00022 } KSWITCHFRAME, *PKSWITCHFRAME;
00023
00024 typedef struct _KUINIT_FRAME
00025 {
00026 KEXCEPTION_FRAME CtxSwitchFrame;
00027 KEXCEPTION_FRAME ExceptionFrame;
00028 KTRAP_FRAME TrapFrame;
00029 } KUINIT_FRAME, *PKUINIT_FRAME;
00030
00031 typedef struct _KKINIT_FRAME
00032 {
00033 KEXCEPTION_FRAME CtxSwitchFrame;
00034 } KKINIT_FRAME, *PKKINIT_FRAME;
00035
00036
00037
00038 VOID
00039 NTAPI
00040 KiThreadStartup(VOID);
00041
00042 VOID
00043 FASTCALL
00044 KiSwitchThreads(
00045 IN PKTHREAD OldThread,
00046 IN PKTHREAD NewThread
00047 );
00048
00049
00050
00051 VOID
00052 NTAPI
00053 KiInitializeContextThread(IN PKTHREAD Thread,
00054 IN PKSYSTEM_ROUTINE SystemRoutine,
00055 IN PKSTART_ROUTINE StartRoutine,
00056 IN PVOID StartContext,
00057 IN PCONTEXT ContextPointer)
00058 {
00059 PKTRAP_FRAME TrapFrame;
00060 PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame;
00061
00062
00063
00064
00065 if (ContextPointer)
00066 {
00067
00068
00069
00070 PKUINIT_FRAME InitFrame;
00071 InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
00072 sizeof(KUINIT_FRAME));
00073
00074
00075
00076
00077 TrapFrame = &InitFrame->TrapFrame;
00078 ExceptionFrame = &InitFrame->ExceptionFrame;
00079
00081
00082
00083 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
00084 RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME));
00085
00086
00087
00088
00089 KeContextToTrapFrame(ContextPointer,
00090 ExceptionFrame,
00091 TrapFrame,
00092 ContextPointer->ContextFlags | CONTEXT_CONTROL,
00093 UserMode);
00094
00095
00096
00097
00098
00099 Thread->PreviousMode = UserMode;
00100
00101
00102
00103
00104 ExceptionFrame->Lr = 0;
00105
00106
00107
00108
00109 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
00110 }
00111 else
00112 {
00113
00114
00115
00116 PKKINIT_FRAME InitFrame;
00117 InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
00118 sizeof(KKINIT_FRAME));
00119
00120
00121
00122
00123 Thread->PreviousMode = KernelMode;
00124
00125
00126
00127
00128 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
00129 }
00130
00131
00132
00133
00134 CtxSwitchFrame->Lr = (ULONG)KiThreadStartup;
00135 CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame);
00136
00137
00138
00139
00140 CtxSwitchFrame->R4 = (ULONG)ContextPointer;
00141 CtxSwitchFrame->R5 = (ULONG)StartContext;
00142 CtxSwitchFrame->R6 = (ULONG)StartRoutine;
00143 CtxSwitchFrame->R7 = (ULONG)SystemRoutine;
00144
00145
00146
00147
00148 Thread->KernelStack = (PVOID)CtxSwitchFrame;
00149 }
00150
00151 VOID
00152 FASTCALL
00153 KiIdleLoop(VOID)
00154 {
00155 PKPRCB Prcb = KeGetCurrentPrcb();
00156 PKTHREAD OldThread, NewThread;
00157
00158
00159 _enable();
00160 YieldProcessor();
00161 YieldProcessor();
00162 _disable();
00163
00164
00165 while (TRUE)
00166 {
00167
00168 if ((Prcb->DpcData[0].DpcQueueDepth) ||
00169 (Prcb->TimerRequest) ||
00170 (Prcb->DeferredReadyListHead.Next))
00171 {
00172
00173 HalClearSoftwareInterrupt(DISPATCH_LEVEL);
00174
00175
00176 KiRetireDpcList(Prcb);
00177 }
00178
00179
00180 if (Prcb->NextThread)
00181 {
00182
00183 _enable();
00184
00185
00186 OldThread = Prcb->CurrentThread;
00187 NewThread = Prcb->NextThread;
00188
00189
00190 Prcb->NextThread = NULL;
00191 Prcb->CurrentThread = NewThread;
00192
00193
00194 NewThread->State = Running;
00195
00196
00197 KiSwapContext(APC_LEVEL, OldThread);
00198
00199
00200 _enable();
00201 YieldProcessor();
00202 YieldProcessor();
00203 _disable();
00204 }
00205 else
00206 {
00207
00208 Prcb->PowerState.IdleFunction(&Prcb->PowerState);
00209 }
00210 }
00211 }
00212
00213 BOOLEAN
00214 FASTCALL
00215 KiSwapContextExit(IN PKTHREAD OldThread,
00216 IN PKSWITCHFRAME SwitchFrame)
00217 {
00218 PKIPCR Pcr = (PKIPCR)KeGetPcr();
00219 PKPROCESS OldProcess, NewProcess;
00220 PKTHREAD NewThread;
00221 ARM_TTB_REGISTER TtbRegister;
00222
00223
00224 NewThread = Pcr->PrcbData.CurrentThread;
00225
00226
00227 OldProcess = OldThread->ApcState.Process;
00228 NewProcess = NewThread->ApcState.Process;
00229 if (OldProcess != NewProcess)
00230 {
00231 TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
00232 ASSERT(TtbRegister.Reserved == 0);
00233 KeArmTranslationTableRegisterSet(TtbRegister);
00234 }
00235
00236
00237 NewThread->ContextSwitches++;
00238
00239
00240 Pcr->NtTib.ExceptionList = SwitchFrame->ExceptionList;
00241
00242
00243 if (Pcr->PrcbData.DpcRoutineActive)
00244 {
00245
00246 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
00247 (ULONG_PTR)OldThread,
00248 (ULONG_PTR)NewThread,
00249 (ULONG_PTR)OldThread->InitialStack,
00250 0);
00251 }
00252
00253
00254 if (NewThread->ApcState.KernelApcPending)
00255 {
00256
00257 if (!NewThread->SpecialApcDisable)
00258 {
00259
00260 if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
00261 return TRUE;
00262 }
00263 }
00264
00265
00266 return FALSE;
00267 }
00268
00269 VOID
00270 FASTCALL
00271 KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
00272 IN ULONG_PTR OldThreadAndApcFlag)
00273 {
00274 PKIPCR Pcr = (PKIPCR)KeGetPcr();
00275 PKTHREAD OldThread, NewThread;
00276
00277
00278 SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
00279 SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
00280
00281
00282 Pcr->ContextSwitches++;
00283 if (Pcr->PerfGlobalGroupMask)
00284 {
00285
00286 DPRINT1("WMI Tracing not supported\n");
00287 ASSERT(FALSE);
00288 }
00289
00290
00291 OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
00292 NewThread = Pcr->PrcbData.CurrentThread;
00293
00294
00295 OldThread->KernelStack = SwitchFrame;
00296
00297
00298 KiSwitchThreads(OldThread, NewThread->KernelStack);
00299 }
00300
00301 VOID
00302 NTAPI
00303 KiDispatchInterrupt(VOID)
00304 {
00305 PKIPCR Pcr = (PKIPCR)KeGetPcr();
00306 PKPRCB Prcb = &Pcr->PrcbData;
00307 PVOID OldHandler;
00308 PKTHREAD NewThread, OldThread;
00309
00310
00311 _disable();
00312
00313
00314 if ((Prcb->DpcData[0].DpcQueueDepth) ||
00315 (Prcb->TimerRequest) ||
00316 (Prcb->DeferredReadyListHead.Next))
00317 {
00318
00319 OldHandler = Pcr->NtTib.ExceptionList;
00320 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
00321
00322
00323
00324
00325 KiRetireDpcList(Prcb);
00326
00327
00328 Pcr->NtTib.ExceptionList = OldHandler;
00329 }
00330
00331
00332 _enable();
00333
00334
00335 if (Prcb->QuantumEnd)
00336 {
00337
00338 Prcb->QuantumEnd = FALSE;
00339 KiQuantumEnd();
00340 }
00341 else if (Prcb->NextThread)
00342 {
00343
00344 OldThread = Prcb->CurrentThread;
00345 NewThread = Prcb->NextThread;
00346
00347
00348 Prcb->NextThread = NULL;
00349 Prcb->CurrentThread = NewThread;
00350
00351
00352 NewThread->State = Running;
00353 OldThread->WaitReason = WrDispatchInt;
00354
00355
00356 KxQueueReadyThread(OldThread, Prcb);
00357
00358
00359 KiSwapContext(APC_LEVEL, OldThread);
00360 }
00361 }
00362
00363