ReactOS 0.4.16-dev-117-g38f21f9
traphandler.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for traphandler.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MAX_SYSCALL_PARAMS   16
 

Functions

VOID KiRetireDpcListInDpcStack (PKPRCB Prcb, PVOID DpcStack)
 
NTSTATUS KiConvertToGuiThread (VOID)
 
 _Requires_lock_not_held_ (Prcb->PrcbLock) VOID NTAPI KiDpcInterruptHandler(VOID)
 
VOID KiNmiInterruptHandler (_In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
 
NTSTATUS NtSyscallFailure (void)
 
PVOID KiSystemCallHandler (VOID)
 
VOID KiSystemService (IN PKTHREAD Thread, IN PKTRAP_FRAME TrapFrame, IN ULONG Instruction)
 

Macro Definition Documentation

◆ MAX_SYSCALL_PARAMS

#define MAX_SYSCALL_PARAMS   16

Definition at line 127 of file traphandler.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file traphandler.c.

Function Documentation

◆ _Requires_lock_not_held_()

_Requires_lock_not_held_ ( Prcb->  PrcbLock)

Definition at line 24 of file traphandler.c.

28{
29 PKPRCB Prcb = KeGetCurrentPrcb();
30 PKTHREAD NewThread, OldThread;
32
33 /* Raise to DISPATCH_LEVEL */
35
36 /* Send an EOI */
37 KiSendEOI();
38
39 /* Check for pending timers, pending DPCs, or pending ready threads */
40 if ((Prcb->DpcData[0].DpcQueueDepth) ||
41 (Prcb->TimerRequest) ||
43 {
44 /* Retire DPCs while under the DPC stack */
46 }
47
48 /* Enable interrupts */
49 _enable();
50
51 /* Check for quantum end */
52 if (Prcb->QuantumEnd)
53 {
54 /* Handle quantum end */
55 Prcb->QuantumEnd = FALSE;
57 }
58 else if (Prcb->NextThread)
59 {
60 /* Acquire the PRCB lock */
62
63 /* Capture current thread data */
64 OldThread = Prcb->CurrentThread;
65 NewThread = Prcb->NextThread;
66
67 /* Set new thread data */
68 Prcb->NextThread = NULL;
69 Prcb->CurrentThread = NewThread;
70
71 /* The thread is now running */
72 NewThread->State = Running;
73 OldThread->WaitReason = WrDispatchInt;
74
75 /* Make the old thread ready */
76 KxQueueReadyThread(OldThread, Prcb);
77
78 /* Swap to the new thread */
79 KiSwapContext(APC_LEVEL, OldThread);
80 }
81
82 /* Disable interrupts and go back to old irql */
83 _disable();
85}
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
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
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
@ Running
Definition: ketypes.h:390
FORCEINLINE VOID KiSendEOI(VOID)
Definition: ke.h:346
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
VOID NTAPI KiQuantumEnd(VOID)
volatile ULONG DpcQueueDepth
Definition: ketypes.h:858
UINT64 TimerRequest
Definition: ketypes.h:775
KDPC_DATA DpcData[2]
Definition: ketypes.h:760
UCHAR QuantumEnd
Definition: ketypes.h:780
struct _KTHREAD * CurrentThread
Definition: ketypes.h:650
struct _KTHREAD * NextThread
Definition: ketypes.h:651
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:712
PVOID DpcStack
Definition: ketypes.h:761
UCHAR WaitReason
Definition: ketypes.h:1964
volatile UCHAR State
Definition: ketypes.h:1789
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
VOID KiRetireDpcListInDpcStack(PKPRCB Prcb, PVOID DpcStack)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ WrDispatchInt
Definition: ketypes.h:446

◆ KiConvertToGuiThread()

NTSTATUS KiConvertToGuiThread ( VOID  )

Referenced by KiSystemCallHandler().

◆ KiNmiInterruptHandler()

VOID KiNmiInterruptHandler ( _In_ PKTRAP_FRAME  TrapFrame,
_In_ PKEXCEPTION_FRAME  ExceptionFrame 
)

Definition at line 88 of file traphandler.c.

91{
92 BOOLEAN ManualSwapGs = FALSE;
93
94 /* Check if the NMI came from kernel mode */
95 if ((TrapFrame->SegCs & MODE_MASK) == 0)
96 {
97 /* Check if GS base is already kernel mode. This is needed, because
98 we might be interrupted during an interrupt/exception from user-mode
99 before the swapgs instruction. */
100 if ((LONG64)__readmsr(MSR_GS_BASE) >= 0)
101 {
102 /* Swap GS to kernel */
103 __swapgs();
104 ManualSwapGs = TRUE;
105 }
106 }
107
108 /* Check if this is a freeze */
109 if (KiProcessorFreezeHandler(TrapFrame, ExceptionFrame))
110 {
111 /* NMI was handled */
112 goto Exit;
113 }
114
115 /* Handle the NMI */
116 KiHandleNmi();
117
118Exit:
119 /* Check if we need to swap GS back */
120 if (ManualSwapGs)
121 {
122 /* Swap GS back to user */
123 __swapgs();
124 }
125}
unsigned char BOOLEAN
#define MODE_MASK
Definition: orders.h:326
#define TRUE
Definition: types.h:120
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
#define MSR_GS_BASE
Definition: ketypes.h:253
BOOLEAN KiProcessorFreezeHandler(_In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: freeze.c:21
BOOLEAN NTAPI KiHandleNmi(VOID)
Definition: bug.c:1165
static void Exit(void)
Definition: sock.c:1330
int64_t LONG64
Definition: typedefs.h:68

◆ KiRetireDpcListInDpcStack()

VOID KiRetireDpcListInDpcStack ( PKPRCB  Prcb,
PVOID  DpcStack 
)

◆ KiSystemCallHandler()

PVOID KiSystemCallHandler ( VOID  )

Definition at line 137 of file traphandler.c.

139{
140 PKTRAP_FRAME TrapFrame;
141 PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
143 PULONG64 KernelParams, UserParams;
144 ULONG ServiceNumber, TableIndex, Count;
145 ULONG64 UserRsp;
146
147 /* Get a pointer to the trap frame */
149
150 /* Increase system call count */
151 __addgsdword(FIELD_OFFSET(KIPCR, Prcb.KeSystemCalls), 1);
152
153 /* Get the current thread */
155
156 /* Set previous mode */
157 Thread->PreviousMode = TrapFrame->PreviousMode = UserMode;
158
159 /* We don't have an exception frame yet */
160 TrapFrame->ExceptionFrame = 0;
161
162 /* Before enabling interrupts get the user rsp from the KPCR */
163 UserRsp = __readgsqword(FIELD_OFFSET(KIPCR, UserRsp));
164 TrapFrame->Rsp = UserRsp;
165
166 /* Enable interrupts */
167 _enable();
168
169 /* If the usermode rsp was not a usermode address, prepare an exception */
170 if (UserRsp > MmUserProbeAddress) UserRsp = MmUserProbeAddress;
171
172 /* Get the address of the usermode and kernelmode parameters */
173 UserParams = (PULONG64)UserRsp + 1;
174 KernelParams = (PULONG64)TrapFrame - MAX_SYSCALL_PARAMS;
175
176 /* Get the system call number from the trap frame and decode it */
177 ServiceNumber = (ULONG)TrapFrame->Rax;
178 TableIndex = (ServiceNumber >> TABLE_OFFSET_BITS) & ((1 << TABLE_NUMBER_BITS) - 1);
179 ServiceNumber &= SERVICE_NUMBER_MASK;
180
181 /* Check for win32k system calls */
182 if (TableIndex == WIN32K_SERVICE_INDEX)
183 {
184 ULONG GdiBatchCount;
185
186 /* Read the GDI batch count from the TEB */
188 {
189 GdiBatchCount = NtCurrentTeb()->GdiBatchCount;
190 }
192 {
193 GdiBatchCount = 0;
194 }
195 _SEH2_END;
196
197 /* Flush batch, if there are entries */
198 if (GdiBatchCount != 0)
199 {
201 }
202 }
203
204 /* Get descriptor table */
205 DescriptorTable = &((PKSERVICE_TABLE_DESCRIPTOR)Thread->ServiceTable)[TableIndex];
206
207 /* Validate the system call number */
208 if (ServiceNumber >= DescriptorTable->Limit)
209 {
210 /* Check if this is a GUI call and this is not a GUI thread yet */
211 if ((TableIndex == WIN32K_SERVICE_INDEX) &&
212 (Thread->ServiceTable == KeServiceDescriptorTable))
213 {
214 /* Convert this thread to a GUI thread.
215 It is invalid to change the stack in the middle of a C function,
216 therefore we return KiConvertToGuiThread to the system call entry
217 point, which then calls the asm function KiConvertToGuiThread,
218 which allocates a new stack, switches to it, calls
219 PsConvertToGuiThread and resumes in the middle of
220 KiSystemCallEntry64 to restart the system call handling.
221 If converting fails, the system call returns a failure code. */
223 }
224
225 /* Fail the call */
227 return (PVOID)NtSyscallFailure;
228 }
229
230 /* Get stack bytes and calculate argument count */
231 Count = DescriptorTable->Number[ServiceNumber] / 8;
232
234 {
235 switch (Count)
236 {
237 case 16: KernelParams[15] = UserParams[15];
238 case 15: KernelParams[14] = UserParams[14];
239 case 14: KernelParams[13] = UserParams[13];
240 case 13: KernelParams[12] = UserParams[12];
241 case 12: KernelParams[11] = UserParams[11];
242 case 11: KernelParams[10] = UserParams[10];
243 case 10: KernelParams[9] = UserParams[9];
244 case 9: KernelParams[8] = UserParams[8];
245 case 8: KernelParams[7] = UserParams[7];
246 case 7: KernelParams[6] = UserParams[6];
247 case 6: KernelParams[5] = UserParams[5];
248 case 5: KernelParams[4] = UserParams[4];
249 case 4:
250 case 3:
251 case 2:
252 case 1:
253 case 0:
254 break;
255
256 default:
257 ASSERT(FALSE);
258 break;
259 }
260 }
262 {
263 TrapFrame->Rax = _SEH2_GetExceptionCode();
264 return (PVOID)NtSyscallFailure;
265 }
266 _SEH2_END;
267
268 return (PVOID)DescriptorTable->Base[ServiceNumber];
269}
#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
#define KeGetCurrentThread
Definition: hal.h:55
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define _AddressOfReturnAddress()
Definition: intrin_ppc.h:40
#define NtCurrentTeb
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
#define UserMode
Definition: asm.h:35
struct _KTRAP_FRAME * PKTRAP_FRAME
#define WIN32K_SERVICE_INDEX
Definition: ketypes.h:49
#define TABLE_OFFSET_BITS
Definition: ketypes.h:42
#define SERVICE_NUMBER_MASK
Definition: ketypes.h:83
struct _KSERVICE_TABLE_DESCRIPTOR * PKSERVICE_TABLE_DESCRIPTOR
#define TABLE_NUMBER_BITS
Definition: ketypes.h:41
int Count
Definition: noreturn.cpp:7
PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch
Definition: win32.c:20
ULONG MmUserProbeAddress
Definition: init.c:50
#define STATUS_INVALID_SYSTEM_SERVICE
Definition: ntstatus.h:265
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[SSDT_MAX_ENTRIES]
Definition: procobj.c:23
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
UINT64 Rsp
Definition: ketypes.h:471
CHAR PreviousMode
Definition: ketypes.h:398
UINT64 ExceptionFrame
Definition: ketypes.h:461
UINT64 Rax
Definition: ketypes.h:403
#define MAX_SYSCALL_PARAMS
Definition: traphandler.c:127
NTSTATUS KiConvertToGuiThread(VOID)
NTSTATUS NtSyscallFailure(void)
Definition: traphandler.c:130
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint32_t ULONG
Definition: typedefs.h:59

◆ KiSystemService()

VOID KiSystemService ( IN PKTHREAD  Thread,
IN PKTRAP_FRAME  TrapFrame,
IN ULONG  Instruction 
)

Definition at line 274 of file traphandler.c.

277{
279 __debugbreak();
280}
#define UNIMPLEMENTED
Definition: debug.h:118
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698

◆ NtSyscallFailure()

NTSTATUS NtSyscallFailure ( void  )

Definition at line 130 of file traphandler.c.

131{
132 /* This is the failure function */
133 return (NTSTATUS)KeGetCurrentThread()->TrapFrame->Rax;
134}
LONG NTSTATUS
Definition: precomp.h:26

Referenced by KiSystemCallHandler().