Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenusercall.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/ke/arm/usercall.c 00005 * PURPOSE: Implements system calls and user-mode callbacks for ARM 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #include <internal/arm/ksarm.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS ********************************************************************/ 00017 00018 // 00019 // System call wrapper generator 00020 // 00021 #define BUILD_SYSCALLS \ 00022 SYSCALL(00, ()) \ 00023 SYSCALL(01, (_1)) \ 00024 SYSCALL(02, (_1, _2)) \ 00025 SYSCALL(03, (_1, _2, _3)) \ 00026 SYSCALL(04, (_1, _2, _3, _4 )) \ 00027 SYSCALL(05, (_1, _2, _3, _4, _5)) \ 00028 SYSCALL(06, (_1, _2, _3, _4, _5, _6)) \ 00029 SYSCALL(07, (_1, _2, _3, _4, _5, _6, _7)) \ 00030 SYSCALL(08, (_1, _2, _3, _4, _5, _6, _7, _8)) \ 00031 SYSCALL(09, (_1, _2, _3, _4, _5, _6, _7, _8, _9)) \ 00032 SYSCALL(0A, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a)) \ 00033 SYSCALL(0B, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b)) \ 00034 SYSCALL(0C, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c)) \ 00035 SYSCALL(0D, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d)) \ 00036 SYSCALL(0E, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e)) \ 00037 SYSCALL(0F, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f)) \ 00038 SYSCALL(10, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10)) \ 00039 SYSCALL(11, (_1, _2, _3, _4, _5, _6, _7, _8, _9, a, b, c, d, e, f, _10, _11)) 00040 00041 // 00042 // Generate function pointer definitions 00043 // 00044 #define PROTO 00045 #include "ke_i.h" 00046 BUILD_SYSCALLS 00047 00048 // 00049 // Generate function code 00050 // 00051 #define FUNC 00052 #include "ke_i.h" 00053 BUILD_SYSCALLS 00054 00055 /* SYSTEM CALL STUBS **********************************************************/ 00056 00057 typedef NTSTATUS (*PKI_SYSCALL_PARAM_HANDLER)(IN PVOID p, IN PVOID *g); 00058 PKI_SYSCALL_PARAM_HANDLER KiSyscallHandlers[0x12] = 00059 { 00060 KiSyscall00Param, 00061 KiSyscall01Param, 00062 KiSyscall02Param, 00063 KiSyscall03Param, 00064 KiSyscall04Param, 00065 KiSyscall05Param, 00066 KiSyscall06Param, 00067 KiSyscall07Param, 00068 KiSyscall08Param, 00069 KiSyscall09Param, 00070 KiSyscall0AParam, 00071 KiSyscall0BParam, 00072 KiSyscall0CParam, 00073 KiSyscall0DParam, 00074 KiSyscall0EParam, 00075 KiSyscall0FParam, 00076 KiSyscall10Param, 00077 KiSyscall11Param, 00078 }; 00079 00080 /* FUNCIONS *******************************************************************/ 00081 00082 VOID 00083 KiSystemService(IN PKTHREAD Thread, 00084 IN PKTRAP_FRAME TrapFrame, 00085 IN ULONG Instruction) 00086 { 00087 ULONG Id, Number, ArgumentCount, i; 00088 PKPCR Pcr; 00089 ULONG_PTR ServiceTable, Offset; 00090 PKSERVICE_TABLE_DESCRIPTOR DescriptorTable; 00091 PVOID SystemCall; 00092 PVOID* Argument; 00093 PVOID Arguments[0x11]; // Maximum 17 arguments 00094 KIRQL OldIrql; 00095 ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00); 00096 00097 // 00098 // Increase count of system calls 00099 // 00100 Pcr = (PKPCR)KeGetPcr(); 00101 Pcr->Prcb->KeSystemCalls++; 00102 00103 // 00104 // Get the system call ID 00105 // 00106 Id = Instruction & 0xFFFFF; 00107 //DPRINT1("[SWI] (%x) %p (%d) \n", Id, Thread, Thread->PreviousMode); 00108 00109 // 00110 // Get the descriptor table 00111 // 00112 ServiceTable = (ULONG_PTR)Thread->ServiceTable; 00113 Offset = ((Id >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK); 00114 ServiceTable += Offset; 00115 DescriptorTable = (PVOID)ServiceTable; 00116 00117 // 00118 // Get the service call number and validate it 00119 // 00120 Number = Id & SERVICE_NUMBER_MASK; 00121 if (Number > DescriptorTable->Limit) 00122 { 00123 // 00124 // Check if this is a GUI call 00125 // 00126 UNIMPLEMENTED; 00127 ASSERT(FALSE); 00128 } 00129 00130 // 00131 // Save the function responsible for handling this system call 00132 // 00133 SystemCall = (PVOID)DescriptorTable->Base[Number]; 00134 00135 // 00136 // Check if this is a GUI call 00137 // 00138 if (Offset & SERVICE_TABLE_TEST) 00139 { 00140 // 00141 // TODO 00142 // 00143 UNIMPLEMENTED; 00144 ASSERT(FALSE); 00145 } 00146 00147 // 00148 // Check how many arguments this system call takes 00149 // 00150 ArgumentCount = DescriptorTable->Number[Number] / 4; 00151 ASSERT(ArgumentCount <= 17); 00152 00153 // 00154 // Copy the register-arguments first 00155 // First four arguments are in a1, a2, a3, a4 00156 // 00157 Argument = (PVOID*)&TrapFrame->R0; 00158 for (i = 0; (i < ArgumentCount) && (i < 4); i++) 00159 { 00160 // 00161 // Copy them into the kernel stack 00162 // 00163 Arguments[i] = *Argument; 00164 Argument++; 00165 } 00166 00167 // 00168 // If more than four, we'll have some on the user stack 00169 // 00170 if (ArgumentCount > 4) 00171 { 00172 // 00173 // Check where the stack is 00174 // 00175 if (Thread->PreviousMode == UserMode) 00176 { 00177 // 00178 // FIXME-USER: Validate the user stack 00179 // 00180 ASSERT(FALSE); 00181 Argument = (PVOID*)TrapFrame->UserSp; 00182 } 00183 else 00184 { 00185 // 00186 // We were called from the kernel 00187 // 00188 Argument = (PVOID*)(TrapFrame + 1); 00189 } 00190 00191 // 00192 // Copy the rest 00193 // 00194 for (i = 4; i < ArgumentCount; i++) 00195 { 00196 // 00197 // Copy into kernel stack 00198 // 00199 Arguments[i] = *Argument; 00200 Argument++; 00201 } 00202 } 00203 00204 // 00205 // We can safely enable interrupts here 00206 // 00207 _enable(); 00208 00209 // 00210 // Do the system call and save result in EAX 00211 // 00212 TrapFrame->R0 = KiSyscallHandlers[ArgumentCount]((PVOID)SystemCall, 00213 (PVOID)Arguments); 00214 00215 // 00216 // Check if this was a user call 00217 // 00218 if (KiGetPreviousMode(TrapFrame) == UserMode) 00219 { 00220 // 00221 // Make sure we didn't return at elevated IRQL 00222 // 00223 OldIrql = KeGetCurrentIrql(); 00224 if (OldIrql != PASSIVE_LEVEL) 00225 { 00226 // 00227 // Forcibly put us in a sane state 00228 // 00229 KeGetPcr()->Irql = 0; 00230 _disable(); 00231 00232 // 00233 // Fail 00234 // 00235 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE, 00236 (ULONG_PTR)SystemCall, 00237 OldIrql, 00238 0, 00239 0); 00240 } 00241 00242 // 00243 // Make sure we're not attached and that APCs are not disabled 00244 // 00245 if ((KeGetCurrentThread()->ApcStateIndex != CurrentApcEnvironment) || 00246 (KeGetCurrentThread()->CombinedApcDisable != 0)) 00247 { 00248 // 00249 // Fail 00250 // 00251 KeBugCheckEx(APC_INDEX_MISMATCH, 00252 (ULONG_PTR)SystemCall, 00253 KeGetCurrentThread()->ApcStateIndex, 00254 KeGetCurrentThread()->CombinedApcDisable, 00255 0); 00256 } 00257 } 00258 00259 // 00260 // Restore the old trap frame 00261 // 00262 Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->PreviousTrapFrame; 00263 } 00264 00265 VOID 00266 NTAPI 00267 KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame, 00268 IN PKTRAP_FRAME TrapFrame, 00269 IN PKNORMAL_ROUTINE NormalRoutine, 00270 IN PVOID NormalContext, 00271 IN PVOID SystemArgument1, 00272 IN PVOID SystemArgument2) 00273 { 00274 CONTEXT Context; 00275 ULONG_PTR Stack; 00276 ULONG ContextLength; 00277 DPRINT1("User APC: %p %p %p\n", NormalContext, SystemArgument1, SystemArgument2); 00278 00279 // 00280 // Build the user mode context 00281 // 00282 Context.ContextFlags = CONTEXT_FULL; 00283 KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context); 00284 00285 // 00286 // Setup the context on the user stack 00287 // 00288 ContextLength = sizeof(CONTEXT); 00289 Stack = (ULONG_PTR)(Context.Sp & ~7) - ContextLength; 00290 00291 // 00292 // Make sure the stack is valid, and copy the context 00293 // 00294 ProbeForWrite((PVOID)Stack, ContextLength, sizeof(QUAD)); 00295 RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT)); 00296 00297 // 00298 // Setup the trap frame when we return to user mode 00299 // 00300 TrapFrame->R0 = (ULONG)NormalContext; 00301 TrapFrame->R1 = (ULONG)SystemArgument1; 00302 TrapFrame->R2 = (ULONG)SystemArgument2; 00303 TrapFrame->R3 = (ULONG)NormalRoutine; 00304 TrapFrame->R8 = Stack; 00305 TrapFrame->UserSp = Stack; 00306 TrapFrame->UserLr = (ULONG)KeUserApcDispatcher; 00307 } Generated on Sun May 27 2012 04:37:31 for ReactOS by
1.7.6.1
|