ReactOS 0.4.15-dev-5853-gcb454ef
stubs.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: stubs
5 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
6 */
7
8/* INCLUDES ******************************************************************/
9
10#include <ntoskrnl.h>
11#include <fltkernel.h>
12
13#define NDEBUG
14#include <debug.h>
15
18
19VOID
21 PKPRCB Prcb,
22 PVOID DpcStack);
23
26 VOID);
27
29VOID
31KiDpcInterruptHandler(VOID)
32{
33 PKPRCB Prcb = KeGetCurrentPrcb();
34 PKTHREAD NewThread, OldThread;
36
37 /* Raise to DISPATCH_LEVEL */
39
40 /* Send an EOI */
41 KiSendEOI();
42
43 /* Check for pending timers, pending DPCs, or pending ready threads */
44 if ((Prcb->DpcData[0].DpcQueueDepth) ||
45 (Prcb->TimerRequest) ||
47 {
48 /* Retire DPCs while under the DPC stack */
50 }
51
52 /* Enable interrupts */
53 _enable();
54
55 /* Check for quantum end */
56 if (Prcb->QuantumEnd)
57 {
58 /* Handle quantum end */
59 Prcb->QuantumEnd = FALSE;
61 }
62 else if (Prcb->NextThread)
63 {
64 /* Acquire the PRCB lock */
66
67 /* Capture current thread data */
68 OldThread = Prcb->CurrentThread;
69 NewThread = Prcb->NextThread;
70
71 /* Set new thread data */
72 Prcb->NextThread = NULL;
73 Prcb->CurrentThread = NewThread;
74
75 /* The thread is now running */
76 NewThread->State = Running;
77 OldThread->WaitReason = WrDispatchInt;
78
79 /* Make the old thread ready */
80 KxQueueReadyThread(OldThread, Prcb);
81
82 /* Swap to the new thread */
83 KiSwapContext(APC_LEVEL, OldThread);
84 }
85
86 /* Disable interrupts and go back to old irql */
87 _disable();
89}
90
93 LONG_PTR StackOffset,
94 PVOID OldStackBase);
95
96/*
97 * Kernel stack layout (example pointers):
98 * 0xFFFFFC0F'2D008000 KTHREAD::StackBase
99 * [XSAVE_AREA size == KeXStateLength = 0x440]
100 * 0xFFFFFC0F'2D007BC0 KTHREAD::StateSaveArea _XSAVE_FORMAT
101 * 0xFFFFFC0F'2D007B90 KTHREAD::InitialStack
102 * [0x190 bytes KTRAP_FRAME]
103 * 0xFFFFFC0F'2D007A00 KTHREAD::TrapFrame
104 * [KSTART_FRAME] or ...
105 * [KSWITCH_FRAME]
106 * 0xFFFFFC0F'2D007230 KTHREAD::KernelStack
107 */
108
109PVOID
110NTAPI
111KiSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
112{
113 PKTHREAD CurrentThread;
114 PVOID OldStackBase;
115 LONG_PTR StackOffset;
117 PKIPCR Pcr;
118 ULONG Eflags;
119
120 /* Get the current thread */
121 CurrentThread = KeGetCurrentThread();
122
123 /* Save the old stack base */
124 OldStackBase = CurrentThread->StackBase;
125
126 /* Get the size of the current stack */
127 StackSize = (ULONG_PTR)CurrentThread->StackBase - CurrentThread->StackLimit;
128 ASSERT(StackSize <= (ULONG_PTR)StackBase - (ULONG_PTR)StackLimit);
129
130 /* Copy the current stack contents to the new stack */
131 RtlCopyMemory((PUCHAR)StackBase - StackSize,
132 (PVOID)CurrentThread->StackLimit,
133 StackSize);
134
135 /* Calculate the offset between the old and the new stack */
136 StackOffset = (PUCHAR)StackBase - (PUCHAR)CurrentThread->StackBase;
137
138 /* Disable interrupts while messing with the stack */
139 Eflags = __readeflags();
140 _disable();
141
142 /* Set the new trap frame */
143 CurrentThread->TrapFrame = (PKTRAP_FRAME)Add2Ptr(CurrentThread->TrapFrame,
144 StackOffset);
145
146 /* Set the new initial stack */
147 CurrentThread->InitialStack = Add2Ptr(CurrentThread->InitialStack,
148 StackOffset);
149
150 /* Set the new stack limits */
151 CurrentThread->StackBase = StackBase;
152 CurrentThread->StackLimit = (ULONG_PTR)StackLimit;
153 CurrentThread->LargeStack = TRUE;
154
155 /* Adjust RspBase in the PCR */
156 Pcr = (PKIPCR)KeGetPcr();
157 Pcr->Prcb.RspBase += StackOffset;
158
159 /* Adjust Rsp0 in the TSS */
160 Pcr->TssBase->Rsp0 += StackOffset;
161
162 /* Restore interrupts */
163 __writeeflags(Eflags);
164
165 return OldStackBase;
166}
167
169VOID
171{
172 PKPRCB Prcb = KeGetCurrentPrcb();
173 PKTHREAD OldThread, NewThread;
174
175 /* Now loop forever */
176 while (TRUE)
177 {
178 /* Start of the idle loop: disable interrupts */
179 _enable();
182 _disable();
183
184 /* Check for pending timers, pending DPCs, or pending ready threads */
185 if ((Prcb->DpcData[0].DpcQueueDepth) ||
186 (Prcb->TimerRequest) ||
188 {
189 /* Quiesce the DPC software interrupt */
191
192 /* Handle it */
193 KiRetireDpcList(Prcb);
194 }
195
196 /* Check if a new thread is scheduled for execution */
197 if (Prcb->NextThread)
198 {
199 /* Enable interrupts */
200 _enable();
201
202 /* Capture current thread data */
203 OldThread = Prcb->CurrentThread;
204 NewThread = Prcb->NextThread;
205
206 /* Set new thread data */
207 Prcb->NextThread = NULL;
208 Prcb->CurrentThread = NewThread;
209
210 /* The thread is now running */
211 NewThread->State = Running;
212
213 /* Do the swap at SYNCH_LEVEL */
215
216 /* Switch away from the idle thread */
217 KiSwapContext(APC_LEVEL, OldThread);
218
219 /* Go back to DISPATCH_LEVEL */
221 }
222 else
223 {
224 /* Continue staying idle. Note the HAL returns with interrupts on */
225 Prcb->PowerState.IdleFunction(&Prcb->PowerState);
226 }
227 }
228}
229
230VOID
231NTAPI
233 IN PKPROCESS OldProcess)
234{
235 PKIPCR Pcr = (PKIPCR)KeGetPcr();
236
237#ifdef CONFIG_SMP
238 /* Update active processor mask */
239 InterlockedXor64((PLONG64)&NewProcess->ActiveProcessors, Pcr->Prcb.SetMember);
240 InterlockedXor64((PLONG64)&OldProcess->ActiveProcessors, Pcr->Prcb.SetMember);
241#endif
242
243 /* Update CR3 */
244 __writecr3(NewProcess->DirectoryTableBase[0]);
245
246 /* Update IOPM offset */
247 Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
248}
249
250#define MAX_SYSCALL_PARAMS 16
251
254{
255 /* This is the failure function */
256 return (NTSTATUS)KeGetCurrentThread()->TrapFrame->Rax;
257}
258
259PVOID
261 VOID)
262{
263 PKTRAP_FRAME TrapFrame;
264 PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
266 PULONG64 KernelParams, UserParams;
267 ULONG ServiceNumber, Offset, Count;
268 ULONG64 UserRsp;
269
270 /* Get a pointer to the trap frame */
272
273 /* Increase system call count */
274 __addgsdword(FIELD_OFFSET(KIPCR, Prcb.KeSystemCalls), 1);
275
276 /* Get the current thread */
278
279 /* Set previous mode */
280 Thread->PreviousMode = TrapFrame->PreviousMode = UserMode;
281
282 /* Save the old trap frame and set the new */
283 TrapFrame->TrapFrame = (ULONG64)Thread->TrapFrame;
284 Thread->TrapFrame = TrapFrame;
285
286 /* We don't have an exception frame yet */
287 TrapFrame->ExceptionFrame = 0;
288
289 /* Before enabling interrupts get the user rsp from the KPCR */
290 UserRsp = __readgsqword(FIELD_OFFSET(KIPCR, UserRsp));
291 TrapFrame->Rsp = UserRsp;
292
293 /* Enable interrupts */
294 _enable();
295
296 /* If the usermode rsp was not a usermode address, prepare an exception */
297 if (UserRsp > MmUserProbeAddress) UserRsp = MmUserProbeAddress;
298
299 /* Get the address of the usermode and kernelmode parameters */
300 UserParams = (PULONG64)UserRsp + 1;
301 KernelParams = (PULONG64)TrapFrame - MAX_SYSCALL_PARAMS;
302
303 /* Get the system call number from the trap frame and decode it */
304 ServiceNumber = (ULONG)TrapFrame->Rax;
305 Offset = (ServiceNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
306 ServiceNumber &= SERVICE_NUMBER_MASK;
307
308 /* Check for win32k system calls */
310 {
311 ULONG GdiBatchCount;
312
313 /* Read the GDI batch count from the TEB */
315 {
316 GdiBatchCount = NtCurrentTeb()->GdiBatchCount;
317 }
319 {
320 GdiBatchCount = 0;
321 }
322 _SEH2_END;
323
324 /* Flush batch, if there are entries */
325 if (GdiBatchCount != 0)
326 {
328 }
329 }
330
331 /* Get descriptor table */
332 DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
333
334 /* Validate the system call number */
335 if (ServiceNumber >= DescriptorTable->Limit)
336 {
337 /* Check if this is a GUI call */
338 if (!(Offset & SERVICE_TABLE_TEST))
339 {
340 /* Fail the call */
342 return (PVOID)NtSyscallFailure;
343 }
344
345 /* Convert us to a GUI thread
346 To be entirely correct. we return KiConvertToGuiThread,
347 which allocates a new stack, switches to it, calls
348 PsConvertToGuiThread and resumes in the middle of
349 KiSystemCallEntry64 to restart the system call handling. */
351 }
352
353 /* Get stack bytes and calculate argument count */
354 Count = DescriptorTable->Number[ServiceNumber] / 8;
355
357 {
358 switch (Count)
359 {
360 case 16: KernelParams[15] = UserParams[15];
361 case 15: KernelParams[14] = UserParams[14];
362 case 14: KernelParams[13] = UserParams[13];
363 case 13: KernelParams[12] = UserParams[12];
364 case 12: KernelParams[11] = UserParams[11];
365 case 11: KernelParams[10] = UserParams[10];
366 case 10: KernelParams[9] = UserParams[9];
367 case 9: KernelParams[8] = UserParams[8];
368 case 8: KernelParams[7] = UserParams[7];
369 case 7: KernelParams[6] = UserParams[6];
370 case 6: KernelParams[5] = UserParams[5];
371 case 5: KernelParams[4] = UserParams[4];
372 case 4:
373 case 3:
374 case 2:
375 case 1:
376 case 0:
377 break;
378
379 default:
380 ASSERT(FALSE);
381 break;
382 }
383 }
385 {
386 TrapFrame->Rax = _SEH2_GetExceptionCode();
387 return (PVOID)NtSyscallFailure;
388 }
389 _SEH2_END;
390
391 return (PVOID)DescriptorTable->Base[ServiceNumber];
392}
393
394
395// FIXME: we need to
396VOID
398 IN PKTRAP_FRAME TrapFrame,
400{
402 __debugbreak();
403}
404
406NTAPI
408(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
409{
411 __debugbreak();
412 return STATUS_UNSUCCESSFUL;
413}
414
416NTAPI
418 IN PVOID ControlData)
419{
420 /* Not supported */
422}
423
424
static ULONG StackSize
Definition: StackOverflow.c:19
@ Instruction
Definition: asmpp.cpp:82
LONG NTSTATUS
Definition: precomp.h:26
__int64 * PLONG64
Definition: basetsd.h:185
#define UNIMPLEMENTED
Definition: debug.h:115
#define _Requires_lock_not_held_(lock)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
VOID FASTCALL HalClearSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:282
#define KeGetCurrentThread
Definition: hal.h:55
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define InterlockedXor64
Definition: interlocked.h:291
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
#define _AddressOfReturnAddress()
Definition: intrin_ppc.h:40
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1794
#define NtCurrentTeb
#define Add2Ptr(PTR, INC)
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define UserMode
Definition: asm.h:35
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
struct _KIPCR * PKIPCR
struct _KTRAP_FRAME * PKTRAP_FRAME
#define SERVICE_TABLE_SHIFT
Definition: ketypes.h:71
#define SERVICE_TABLE_MASK
Definition: ketypes.h:78
#define SERVICE_NUMBER_MASK
Definition: ketypes.h:83
@ Running
Definition: ketypes.h:423
#define SERVICE_TABLE_TEST
Definition: ketypes.h:90
int Count
Definition: noreturn.cpp:7
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
FORCEINLINE VOID KiSendEOI(VOID)
Definition: ke.h:346
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
VOID NTAPI KiQuantumEnd(VOID)
PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch
Definition: win32.c:20
VOID FASTCALL KiRetireDpcList(IN PKPRCB Prcb)
Definition: dpc.c:562
#define MAX_SYSCALL_PARAMS
Definition: stubs.c:250
NTSTATUS KiConvertToGuiThread(VOID)
NTSTATUS NTAPI NtSetLdtEntries(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
Definition: stubs.c:408
NTSTATUS NtSyscallFailure(void)
Definition: stubs.c:253
DECLSPEC_NORETURN VOID KiIdleLoop(VOID)
Definition: stubs.c:170
PVOID KiSystemCallHandler(VOID)
Definition: stubs.c:260
VOID KiRetireDpcListInDpcStack(PKPRCB Prcb, PVOID DpcStack)
NTSTATUS NTAPI NtVdmControl(IN ULONG ControlCode, IN PVOID ControlData)
Definition: stubs.c:417
SIZE_T KeXStateLength
Definition: stubs.c:17
PVOID KiSwitchKernelStackHelper(LONG_PTR StackOffset, PVOID OldStackBase)
PVOID NTAPI KiSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
Definition: stubs.c:111
ULONG ProcessCount
Definition: stubs.c:16
VOID KiSystemService(IN PKTHREAD Thread, IN PKTRAP_FRAME TrapFrame, IN ULONG Instruction)
Definition: stubs.c:397
VOID NTAPI KiSwapProcess(IN PKPROCESS NewProcess, IN PKPROCESS OldProcess)
Definition: stubs.c:232
ULONG MmUserProbeAddress
Definition: init.c:50
#define STATUS_INVALID_SYSTEM_SERVICE
Definition: ntstatus.h:265
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define YieldProcessor
Definition: ke.h:48
#define KeGetPcr()
Definition: ke.h:26
volatile ULONG DpcQueueDepth
Definition: ketypes.h:798
KPRCB Prcb
Definition: ketypes.h:894
struct _KTSS64 * TssBase
Definition: ketypes.h:866
UCHAR QuantumEnd
Definition: ketypes.h:701
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:800
UINT64 SetMember
Definition: ketypes.h:583
UINT64 RspBase
Definition: ketypes.h:581
KDPC_DATA DpcData[2]
Definition: ketypes.h:681
struct _KTHREAD * CurrentThread
Definition: ketypes.h:571
struct _KTHREAD * NextThread
Definition: ketypes.h:572
UINT64 TimerRequest
Definition: ketypes.h:696
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:633
PVOID DpcStack
Definition: ketypes.h:682
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1714
PVOID InitialStack
Definition: ketypes.h:1604
UCHAR WaitReason
Definition: ketypes.h:1904
PVOID StackBase
Definition: ketypes.h:1606
volatile VOID * StackLimit
Definition: ketypes.h:1605
volatile UCHAR State
Definition: ketypes.h:1729
UINT64 Rsp
Definition: ketypes.h:391
CHAR PreviousMode
Definition: ketypes.h:318
UINT64 ExceptionFrame
Definition: ketypes.h:381
UINT64 Rax
Definition: ketypes.h:323
UINT64 TrapFrame
Definition: ketypes.h:373
Definition: compat.h:777
PPROCESSOR_IDLE_FUNCTION IdleFunction
Definition: potypes.h:68
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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 STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
XSAVE_FORMAT
Definition: ketypes.h:951
@ WrDispatchInt
Definition: ketypes.h:434