ReactOS  0.4.11-dev-721-g95bc44e
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;
112  Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK);
113  ServiceTable += Offset;
114  DescriptorTable = (PVOID)ServiceTable;
115 
116  //
117  // Get the service call number and validate it
118  //
119  Number = Id & SERVICE_NUMBER_MASK;
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  //
137  if (Offset & SERVICE_TABLE_TEST)
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  //
222  OldIrql = KeGetCurrentIrql();
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 
DWORD *typedef PVOID
Definition: winlogon.h:61
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
struct _CONTEXT CONTEXT
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define SERVICE_TABLE_MASK
Definition: ketypes.h:78
void __cdecl _enable(void)
Definition: intrin_arm.h:373
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 CONTEXT_FULL
Definition: compat.h:270
_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_NUMBER_MASK
Definition: ketypes.h:83
#define BUILD_SYSCALLS
Definition: usercall.c:20
BUILD_SYSCALLS typedef NTSTATUS(* PKI_SYSCALL_PARAM_HANDLER)(IN PVOID p, IN PVOID *g)
Definition: usercall.c:56
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
GLenum GLclampf GLint i
Definition: glfuncs.h:14
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
#define FALSE
Definition: types.h:117
#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
ULONG ContextFlags
Definition: compat.h:331
_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
LONG NTSTATUS
Definition: precomp.h:26
if(!(yy_init))
Definition: macro.lex.yy.c:717
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
VOID(NTAPI * PKNORMAL_ROUTINE)(IN PVOID NormalContext OPTIONAL, IN PVOID SystemArgument1 OPTIONAL, IN PVOID SystemArgument2 OPTIONAL)
Definition: ketypes.h:632
_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
static SERVICE_TABLE_ENTRYW ServiceTable[2]
Definition: eventlog.c:24
#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:1027
unsigned int ULONG
Definition: retypes.h:1
ULONG Sp
Definition: compat.h:350
#define UNIMPLEMENTED
Definition: debug.h:114
#define ULONG_PTR
Definition: config.h:101
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
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