- Rewrite the low-level trap/exception/system call code from the ground up:
[reactos.git] / reactos / ntoskrnl / ke / arm / usercall.c
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"
45 BUILD_SYSCALLS
46
47 //
48 // Generate function code
49 //
50 #define FUNC
51 #include "ke_i.h"
52 BUILD_SYSCALLS
53
54 /* SYSTEM CALL STUBS **********************************************************/
55
56 typedef NTSTATUS (*PKI_SYSCALL_PARAM_HANDLER)(IN PVOID p, IN PVOID *g);
57 PKI_SYSCALL_PARAM_HANDLER KiSyscallHandlers[0x12] =
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
82 KiSystemService(IN PKTHREAD Thread,
83 IN PKTRAP_FRAME TrapFrame,
84 IN ULONG Instruction)
85 {
86 ULONG Id, Number, ArgumentCount, i;
87 PKPCR Pcr;
88 ULONG_PTR ServiceTable, Offset;
89 PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
90 PVOID SystemCall;
91 PVOID* Argument;
92 PVOID Arguments[0x11]; // Maximum 17 arguments
93 ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
94
95 //
96 // Increase count of system calls
97 //
98 Pcr = (PKPCR)KeGetPcr();
99 Pcr->Prcb->KeSystemCalls++;
100
101 //
102 // Get the system call ID
103 //
104 Id = Instruction & 0xFFFFF;
105 //DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode);
106
107 //
108 // Get the descriptor table
109 //
110 ServiceTable = (ULONG_PTR)Thread->ServiceTable;
111 Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK);
112 ServiceTable += Offset;
113 DescriptorTable = (PVOID)ServiceTable;
114
115 //
116 // Get the service call number and validate it
117 //
118 Number = Id & SERVICE_NUMBER_MASK;
119 if (Number > DescriptorTable->Limit)
120 {
121 //
122 // Check if this is a GUI call
123 //
124 UNIMPLEMENTED;
125 ASSERT(FALSE);
126 }
127
128 //
129 // Save the function responsible for handling this system call
130 //
131 SystemCall = (PVOID)DescriptorTable->Base[Number];
132
133 //
134 // Check if this is a GUI call
135 //
136 if (Offset & SERVICE_TABLE_TEST)
137 {
138 //
139 // TODO
140 //
141 UNIMPLEMENTED;
142 ASSERT(FALSE);
143 }
144
145 //
146 // Check how many arguments this system call takes
147 //
148 ArgumentCount = DescriptorTable->Number[Number] / 4;
149 ASSERT(ArgumentCount <= 20);
150
151 //
152 // Copy the register-arguments first
153 // First four arguments are in a1, a2, a3, a4
154 //
155 Argument = (PVOID*)&TrapFrame->R0;
156 for (i = 0; (i < ArgumentCount) && (i < 4); i++)
157 {
158 //
159 // Copy them into the kernel stack
160 //
161 Arguments[i] = *Argument;
162 Argument++;
163 }
164
165 //
166 // If more than four, we'll have some on the user stack
167 //
168 if (ArgumentCount > 4)
169 {
170 //
171 // Check where the stack is
172 //
173 if (Thread->PreviousMode == UserMode)
174 {
175 //
176 // FIXME: Validate the user stack
177 //
178 ASSERT(FALSE);
179 Argument = (PVOID*)TrapFrame->UserSp;
180 }
181 else
182 {
183 //
184 // We were called from the kernel
185 //
186 Argument = (PVOID*)(TrapFrame + 1);
187 }
188
189 //
190 // Copy the rest
191 //
192 for (i = 4; i < ArgumentCount; i++)
193 {
194 //
195 // Copy into kernel stack
196 //
197 Arguments[i] = *Argument;
198 Argument++;
199 }
200 }
201
202 //
203 // Do the system call and save result in EAX
204 //
205 TrapFrame->R0 = KiSyscallHandlers[ArgumentCount]((PVOID)SystemCall,
206 (PVOID)Arguments);
207 }