ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

usercall.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.