ReactOS  0.4.14-dev-593-g1793dcc
usercall.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/usercall.c
5  * PURPOSE: Implements system calls and user-mode callbacks for ARM
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 //
18 // System call wrapper generator
19 //
20 #define BUILD_SYSCALLS \
21 SYSCALL(00, ()) \
22 SYSCALL(01, (_1)) \
23 SYSCALL(02, (_1, _2)) \
24 SYSCALL(03, (_1, _2, _3)) \
25 SYSCALL(04, (_1, _2, _3, _4 )) \
26 SYSCALL(05, (_1, _2, _3, _4, _5)) \
27 SYSCALL(06, (_1, _2, _3, _4, _5, _6)) \
28 SYSCALL(07, (_1, _2, _3, _4, _5, _6, _7)) \
29 SYSCALL(08, (_1, _2, _3, _4, _5, _6, _7, _8)) \
30 SYSCALL(09, (_1, _2, _3, _4, _5, _6, _7, _8, _9)) \
31 SYSCALL(0A, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a)) \
32 SYSCALL(0B, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b)) \
33 SYSCALL(0C, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c)) \
34 SYSCALL(0D, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d)) \
35 SYSCALL(0E, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e)) \
36 SYSCALL(0F, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f)) \
37 SYSCALL(10, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10)) \
38 SYSCALL(11, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10, _11))
39 
40 //
41 // Generate function pointer definitions
42 //
43 #define PROTO
44 #include "ke_i.h"
46 
47 //
48 // Generate function code
49 //
50 #define FUNC
51 #include "ke_i.h"
53 
54 /* SYSTEM CALL STUBS **********************************************************/
55 
58 {
59  KiSyscall00Param,
60  KiSyscall01Param,
61  KiSyscall02Param,
62  KiSyscall03Param,
63  KiSyscall04Param,
64  KiSyscall05Param,
65  KiSyscall06Param,
66  KiSyscall07Param,
67  KiSyscall08Param,
68  KiSyscall09Param,
69  KiSyscall0AParam,
70  KiSyscall0BParam,
71  KiSyscall0CParam,
72  KiSyscall0DParam,
73  KiSyscall0EParam,
74  KiSyscall0FParam,
75  KiSyscall10Param,
76  KiSyscall11Param,
77 };
78 
79 /* FUNCIONS *******************************************************************/
80 
81 VOID
83  IN PKTRAP_FRAME TrapFrame,
84  IN ULONG Instruction)
85 {
86  ULONG Id, Number, ArgumentCount, i;
87  PKPCR Pcr;
89  PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
90  PVOID SystemCall;
91  PVOID* Argument;
92  PVOID Arguments[0x11]; // Maximum 17 arguments
93  KIRQL OldIrql;
94  ASSERT(TrapFrame->Reserved == 0xBADB0D00);
95 
96  //
97  // Increase count of system calls
98  //
99  Pcr = KeGetPcr();
100  Pcr->CurrentPrcb->KeSystemCalls++;
101 
102  //
103  // Get the system call ID
104  //
105  Id = Instruction & 0xFFFFF;
106  //DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode);
107 
108  //
109  // Get the descriptor table
110  //
111  ServiceTable = (ULONG_PTR)Thread->ServiceTable;
113  ServiceTable += Offset;
114  DescriptorTable = (PVOID)ServiceTable;
115 
116  //
117  // Get the service call number and validate it
118  //
120  if (Number > DescriptorTable->Limit)
121  {
122  //
123  // Check if this is a GUI call
124  //
126  ASSERT(FALSE);
127  }
128 
129  //
130  // Save the function responsible for handling this system call
131  //
132  SystemCall = (PVOID)DescriptorTable->Base[Number];
133 
134  //
135  // Check if this is a GUI call
136  //
138  {
139  //
140  // TODO
141  //
143  ASSERT(FALSE);
144  }
145 
146  //
147  // Check how many arguments this system call takes
148  //
149  ArgumentCount = DescriptorTable->Number[Number] / 4;
150  ASSERT(ArgumentCount <= 17);
151 
152  //
153  // Copy the register-arguments first
154  // First four arguments are in a1, a2, a3, a4
155  //
156  Argument = (PVOID*)&TrapFrame->R0;
157  for (i = 0; (i < ArgumentCount) && (i < 4); i++)
158  {
159  //
160  // Copy them into the kernel stack
161  //
162  Arguments[i] = *Argument;
163  Argument++;
164  }
165 
166  //
167  // If more than four, we'll have some on the user stack
168  //
169  if (ArgumentCount > 4)
170  {
171  //
172  // Check where the stack is
173  //
174  if (Thread->PreviousMode == UserMode)
175  {
176  //
177  // FIXME-USER: Validate the user stack
178  //
179  ASSERT(FALSE);
180  Argument = (PVOID*)TrapFrame->Sp;
181  }
182  else
183  {
184  //
185  // We were called from the kernel
186  //
187  Argument = (PVOID*)(TrapFrame + 1);
188  }
189 
190  //
191  // Copy the rest
192  //
193  for (i = 4; i < ArgumentCount; i++)
194  {
195  //
196  // Copy into kernel stack
197  //
198  Arguments[i] = *Argument;
199  Argument++;
200  }
201  }
202 
203  //
204  // We can safely enable interrupts here
205  //
206  _enable();
207 
208  //
209  // Do the system call and save result in EAX
210  //
211  TrapFrame->R0 = KiSyscallHandlers[ArgumentCount]((PVOID)SystemCall,
212  (PVOID)Arguments);
213 
214  //
215  // Check if this was a user call
216  //
217  if (KiGetPreviousMode(TrapFrame) == UserMode)
218  {
219  //
220  // Make sure we didn't return at elevated IRQL
221  //
223  if (OldIrql != PASSIVE_LEVEL)
224  {
225  //
226  // Forcibly put us in a sane state
227  //
228  KeGetPcr()->CurrentIrql = 0;
229  _disable();
230 
231  //
232  // Fail
233  //
234  KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
235  (ULONG_PTR)SystemCall,
236  OldIrql,
237  0,
238  0);
239  }
240 
241  //
242  // Make sure we're not attached and that APCs are not disabled
243  //
244  if ((KeGetCurrentThread()->ApcStateIndex != CurrentApcEnvironment) ||
245  (KeGetCurrentThread()->CombinedApcDisable != 0))
246  {
247  //
248  // Fail
249  //
250  KeBugCheckEx(APC_INDEX_MISMATCH,
251  (ULONG_PTR)SystemCall,
252  KeGetCurrentThread()->ApcStateIndex,
253  KeGetCurrentThread()->CombinedApcDisable,
254  0);
255  }
256  }
257 
258  //
259  // Restore the old trap frame
260  //
261  Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
262 }
263 
264 VOID
265 NTAPI
267  IN PKTRAP_FRAME TrapFrame,
268  IN PKNORMAL_ROUTINE NormalRoutine,
269  IN PVOID NormalContext,
272 {
274  ULONG_PTR Stack;
275  ULONG ContextLength;
276  DPRINT1("User APC: %p %p %p\n", NormalContext, SystemArgument1, SystemArgument2);
277 
278  //
279  // Build the user mode context
280  //
281  Context.ContextFlags = CONTEXT_FULL;
282  KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
283 
284  //
285  // Setup the context on the user stack
286  //
287  ContextLength = sizeof(CONTEXT);
288  Stack = (ULONG_PTR)(Context.Sp & ~7) - ContextLength;
289 
290  //
291  // Make sure the stack is valid, and copy the context
292  //
293  ProbeForWrite((PVOID)Stack, ContextLength, sizeof(QUAD));
294  RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
295 
296  //
297  // Setup the trap frame when we return to user mode
298  //
299  TrapFrame->R0 = (ULONG)NormalContext;
300  TrapFrame->R1 = (ULONG)SystemArgument1;
301  TrapFrame->R2 = (ULONG)SystemArgument2;
302  TrapFrame->R3 = (ULONG)NormalRoutine;
303  TrapFrame->Sp = Stack;
304  TrapFrame->Lr = (ULONG)KeUserApcDispatcher;
305 }
306 
307 NTSTATUS
308 NTAPI
310  IN PVOID Argument,
311  IN ULONG ArgumentLength,
312  OUT PVOID *Result,
314 {
315  ASSERT(FALSE);
316  return STATUS_NOT_IMPLEMENTED;
317 }
318 
319 NTSTATUS
320 NTAPI
323  IN PULONG OutputLength)
324 {
325  ASSERT(FALSE);
326  return STATUS_NOT_IMPLEMENTED;
327 }
328 
329 NTSTATUS
330 NTAPI
332  _In_ PVOID Result,
335 {
336  ASSERT(FALSE);
337  return STATUS_NOT_IMPLEMENTED;
338 }
339 
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
PKI_SYSCALL_PARAM_HANDLER KiSyscallHandlers[0x12]
Definition: usercall.c:57
#define IN
Definition: typedefs.h:38
#define SERVICE_TABLE_SHIFT
Definition: ketypes.h:71
PVOID KeUserApcDispatcher
Definition: ke.h:137
NTSTATUS NTAPI NtCallbackReturn(_In_ PVOID Result, _In_ ULONG ResultLength, _In_ NTSTATUS CallbackStatus)
Definition: usercall.c:331
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define SERVICE_TABLE_MASK
Definition: ketypes.h:78
void __cdecl _enable(void)
Definition: intrin_arm.h:373
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI KeUserModeCallback(IN ULONG RoutineIndex, IN PVOID Argument, IN ULONG ArgumentLength, OUT PVOID *Result, OUT PULONG ResultLength)
Definition: usercall.c:309
Definition: ke.h:280
#define SERVICE_NUMBER_MASK
Definition: ketypes.h:83
#define BUILD_SYSCALLS
Definition: usercall.c:20
struct _CONTEXT CONTEXT
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define KeGetPcr()
Definition: ke.h:25
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
DWORD Id
uint32_t ULONG_PTR
Definition: typedefs.h:63
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define SERVICE_TABLE_TEST
Definition: ketypes.h:90
VOID NTAPI KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT Context)
Definition: context.c:147
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
void * PVOID
Definition: retypes.h:9
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
struct _KPRCB * CurrentPrcb
Definition: ke.h:291
GLboolean GLboolean g
Definition: glext.h:6204
#define CONTEXT_FULL
Definition: nt_native.h:1375
BUILD_SYSCALLS typedef NTSTATUS(* PKI_SYSCALL_PARAM_HANDLER)(IN PVOID p, IN PVOID *g)
Definition: usercall.c:56
if(!(yy_init))
Definition: macro.lex.yy.c:714
VOID NTAPI KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN PKNORMAL_ROUTINE NormalRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: usercall.c:266
#define for
Definition: utility.h:88
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_In_ FLT_PREOP_CALLBACK_STATUS CallbackStatus
Definition: fltkernel.h:1020
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define NTSTATUS
Definition: precomp.h:20
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
VOID KiSystemService(IN PKTHREAD Thread, IN PKTRAP_FRAME TrapFrame, IN ULONG Instruction)
Definition: usercall.c:82
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
#define _In_
Definition: no_sal2.h:204
#define KiGetLinkedTrapFrame(x)
Definition: ke.h:133
unsigned int * PULONG
Definition: retypes.h:1
#define KiGetPreviousMode(tf)
Definition: ke.h:180
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:39
void __cdecl _disable(void)
Definition: intrin_arm.h:365
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define ULONG_PTR
Definition: config.h:101
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:632
GLfloat GLfloat p
Definition: glext.h:8902
#define KeGetCurrentThread
Definition: hal.h:44
NTSTATUS NTAPI KiCallUserMode(IN PVOID *OutputBuffer, IN PULONG OutputLength)
Definition: usercall.c:321
SERVICE_TABLE_ENTRYW ServiceTable[]
Definition: service.c:18
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:107