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

trapc.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/trapc.c
00005  * PURPOSE:         Implements the various trap handlers for ARM exceptions
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 /* FUNCTIONS ******************************************************************/
00017 
00018 #if 0
00019 VOID
00020 KiIdleLoop(VOID)
00021 {
00022     PKPCR Pcr = (PKPCR)KeGetPcr();
00023     PKPRCB Prcb = Pcr->Prcb;
00024     PKTHREAD OldThread, NewThread;
00025     
00026     //
00027     // Loop forever... that's why this is an idle loop
00028     //
00029     DPRINT1("[IDLE LOOP]\n");
00030     while (TRUE);
00031     
00032     while (TRUE)
00033     {
00034         //
00035         // Cycle interrupts
00036         //
00037         _disable();
00038         _enable();
00039     
00040         //
00041         // Check if there's DPC work to do
00042         //
00043         if ((Prcb->DpcData[0].DpcQueueDepth) ||
00044             (Prcb->TimerRequest) ||
00045             (Prcb->DeferredReadyListHead.Next))
00046         {
00047             //
00048             // Clear the pending interrupt
00049             //
00050             HalClearSoftwareInterrupt(DISPATCH_LEVEL);
00051         
00052             //
00053             // Retire DPCs
00054             //
00055             KiRetireDpcList(Prcb);
00056         }
00057     
00058         //
00059         // Check if there's a thread to schedule
00060         //
00061         if (Prcb->NextThread)
00062         {
00063             //
00064             // Out with the old, in with the new...
00065             //
00066             OldThread = Prcb->CurrentThread;
00067             NewThread = Prcb->NextThread;        
00068             Prcb->CurrentThread = NewThread;
00069             Prcb->NextThread = NULL;
00070         
00071             //
00072             // Update thread state
00073             //
00074             NewThread->State = Running;
00075         
00076             //
00077             // Swap to the new thread
00078             // On ARM we call KiSwapContext instead of KiSwapContextInternal,
00079             // because we're calling this from C code and not assembly.
00080             // This is similar to how it gets called for unwaiting, on x86
00081             //
00082             KiSwapContext(OldThread, NewThread);
00083         }
00084         else
00085         {
00086             //
00087             // Go into WFI (sleep more)
00088             //
00089             KeArmWaitForInterrupt();
00090         }
00091     }
00092 }
00093 #endif
00094 
00095 VOID
00096 NTAPI
00097 KiSwapProcess(IN PKPROCESS NewProcess,
00098               IN PKPROCESS OldProcess)
00099 {
00100     ARM_TTB_REGISTER TtbRegister;
00101     DPRINT1("Swapping from: %p (%16s) to %p (%16s)\n",
00102             OldProcess, ((PEPROCESS)OldProcess)->ImageFileName,
00103             NewProcess, ((PEPROCESS)NewProcess)->ImageFileName);
00104     
00105     //
00106     // Update the page directory base
00107     //
00108     TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
00109     ASSERT(TtbRegister.Reserved == 0);
00110     KeArmTranslationTableRegisterSet(TtbRegister);
00111     
00112     //
00113     // FIXME: Flush the TLB
00114     //
00115     
00116     
00117     DPRINT1("Survived!\n");
00118     while (TRUE);
00119 }
00120 
00121 #if 0
00122 BOOLEAN
00123 KiSwapContextInternal(IN PKTHREAD OldThread,
00124                       IN PKTHREAD NewThread)
00125 {
00126     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00127     PKPRCB Prcb = Pcr->Prcb;
00128     PKPROCESS OldProcess, NewProcess;
00129     
00130     DPRINT1("SWAP\n");
00131     while (TRUE);
00132     
00133     //
00134     // Increase context switch count
00135     //
00136     Pcr->ContextSwitches++;
00137     
00138     //
00139     // Check if WMI tracing is enabled
00140     //
00141     if (Pcr->PerfGlobalGroupMask)
00142     {
00143         //
00144         // We don't support this yet on x86 either
00145         //
00146         DPRINT1("WMI Tracing not supported\n");
00147         ASSERT(FALSE);
00148     }
00149     
00150     //
00151     // Check if the processes are also different
00152     //
00153     OldProcess = OldThread->ApcState.Process;
00154     NewProcess = NewThread->ApcState.Process;
00155     if (OldProcess != NewProcess)
00156     {
00157         //
00158         // Check if address space switch is needed
00159         //
00160         if (OldProcess->DirectoryTableBase[0] !=
00161             NewProcess->DirectoryTableBase[0])
00162         {
00163             //
00164             // FIXME-USER: Support address space switch
00165             //
00166             DPRINT1("Address space switch not implemented\n");
00167             ASSERT(FALSE);
00168         }
00169     }
00170     
00171     //
00172     // Increase thread context switches
00173     //
00174     NewThread->ContextSwitches++;
00175 #if 0 // I don't buy this
00176     //
00177     // Set us as the current thread
00178     // NOTE: On RISC Platforms, there is both a KPCR CurrentThread, and a
00179     // KPRCB CurrentThread.
00180     // The latter is set just like on x86-based builds, the former is only set
00181     // when actually doing the context switch (here).
00182     // Recall that the reason for the latter is due to the fact that the KPCR
00183     // is shared with user-mode (read-only), so that information is exposed
00184     // there as well.
00185     //
00186     Pcr->CurrentThread = NewThread;
00187 #endif
00188     //
00189     // DPCs shouldn't be active
00190     //
00191     if (Prcb->DpcRoutineActive)
00192     {
00193         //
00194         // Crash the machine
00195         //
00196         KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
00197                      (ULONG_PTR)OldThread,
00198                      (ULONG_PTR)NewThread,
00199                      (ULONG_PTR)OldThread->InitialStack,
00200                      0);
00201     }
00202     
00203     //
00204     // Kernel APCs may be pending
00205     //
00206     if (NewThread->ApcState.KernelApcPending)
00207     {
00208         //
00209         // Are APCs enabled?
00210         //
00211         if (NewThread->SpecialApcDisable == 0)
00212         {
00213             //
00214             // Request APC delivery
00215             //
00216             HalRequestSoftwareInterrupt(APC_LEVEL);
00217             return TRUE;
00218         }
00219     }
00220     
00221     //
00222     // Return
00223     //
00224     return FALSE;
00225 }
00226 #endif
00227 
00228 VOID
00229 KiApcInterrupt(VOID)
00230 {
00231     KPROCESSOR_MODE PreviousMode;
00232     KEXCEPTION_FRAME ExceptionFrame;
00233     PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
00234     
00235     DPRINT1("[APC TRAP]\n");
00236     while (TRUE);
00237        
00238     //
00239     // Isolate previous mode
00240     //
00241     PreviousMode = KiGetPreviousMode(TrapFrame);
00242     
00243     //
00244     // FIXME-USER: Handle APC interrupt while in user-mode
00245     //
00246     if (PreviousMode == UserMode) ASSERT(FALSE);
00247     
00248     //
00249     // Disable interrupts
00250     //
00251     _disable();
00252 
00253     //
00254     // Clear APC interrupt
00255     //
00256     HalClearSoftwareInterrupt(APC_LEVEL);
00257     
00258     //
00259     // Re-enable interrupts
00260     //
00261     _enable();
00262     
00263     //
00264     // Deliver APCs
00265     //
00266     KiDeliverApc(PreviousMode, &ExceptionFrame, TrapFrame);
00267 }
00268 
00269 #if 0
00270 VOID
00271 KiDispatchInterrupt(VOID)
00272 {
00273     PKIPCR Pcr;
00274     PKPRCB Prcb;
00275     PKTHREAD NewThread, OldThread;
00276     
00277     DPRINT1("[DPC TRAP]\n");
00278     while (TRUE);
00279     
00280     //
00281     // Get the PCR and disable interrupts
00282     //
00283     Pcr = (PKIPCR)KeGetPcr();
00284     Prcb = Pcr->Prcb;
00285     _disable();
00286     
00287     //
00288     //Check if we have to deliver DPCs, timers, or deferred threads
00289     //
00290     if ((Prcb->DpcData[0].DpcQueueDepth) ||
00291         (Prcb->TimerRequest) ||
00292         (Prcb->DeferredReadyListHead.Next))
00293     {
00294         //
00295         // Retire DPCs
00296         //
00297         KiRetireDpcList(Prcb);
00298     }
00299     
00300     //
00301     // Re-enable interrupts
00302     //
00303     _enable();
00304     
00305     //
00306     // Check for quantum end
00307     //
00308     if (Prcb->QuantumEnd)
00309     {
00310         //
00311         // Handle quantum end
00312         //
00313         Prcb->QuantumEnd = FALSE;
00314         KiQuantumEnd();
00315         return;
00316     }
00317     
00318     //
00319     // Check if we have a thread to swap to
00320     //
00321     if (Prcb->NextThread)
00322     {       
00323         //
00324         // Next is now current
00325         //
00326         OldThread = Prcb->CurrentThread;
00327         NewThread = Prcb->NextThread;
00328         Prcb->CurrentThread = NewThread;
00329         Prcb->NextThread = NULL;
00330         
00331         //
00332         // Update thread states
00333         //
00334         NewThread->State = Running;
00335         OldThread->WaitReason = WrDispatchInt;
00336         
00337         //
00338         // Make the old thread ready
00339         //
00340         KxQueueReadyThread(OldThread, Prcb);
00341         
00342         //
00343         // Swap to the new thread
00344         // On ARM we call KiSwapContext instead of KiSwapContextInternal,
00345         // because we're calling this from C code and not assembly.
00346         // This is similar to how it gets called for unwaiting, on x86
00347         //
00348         KiSwapContext(OldThread, NewThread);
00349     }
00350 }
00351 #endif
00352 
00353 VOID
00354 KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
00355                    IN ULONG Reserved)
00356 {
00357     KIRQL OldIrql, Irql;
00358     ULONG InterruptCause, InterruptMask;
00359     PKIPCR Pcr;
00360     PKTRAP_FRAME OldTrapFrame;
00361     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
00362 
00363     //
00364     // Increment interrupt count
00365     //
00366     Pcr = (PKIPCR)KeGetPcr();
00367     Pcr->Prcb->InterruptCount++;
00368     
00369     //
00370     // Get the old IRQL
00371     //
00372     OldIrql = KeGetCurrentIrql();
00373     TrapFrame->OldIrql = OldIrql;
00374     
00375     //
00376     // Get the interrupt source
00377     //
00378     InterruptCause = HalGetInterruptSource();
00379     //DPRINT1("[INT] (%x) @ %p %p\n", InterruptCause, TrapFrame->SvcLr, TrapFrame->Pc);
00380 
00381     //
00382     // Get the new IRQL and Interrupt Mask
00383     //
00384     Irql = Pcr->IrqlMask[InterruptCause];
00385     InterruptMask = Pcr->IrqlTable[Irql];
00386     
00387     //
00388     // Raise to the new IRQL
00389     //
00390     KfRaiseIrql(Irql);
00391     
00392     //
00393     // The clock ISR wants the trap frame as a parameter
00394     //
00395     OldTrapFrame = KeGetCurrentThread()->TrapFrame;
00396     KeGetCurrentThread()->TrapFrame = TrapFrame;
00397 
00398     //
00399     // Check if this interrupt is at DISPATCH or higher
00400     //
00401     if (Irql > DISPATCH_LEVEL)
00402     {   
00403         //
00404         // FIXME-TODO: Switch to interrupt stack
00405         //
00406         //DPRINT1("[ISR]\n");
00407     }
00408     else
00409     {
00410         //
00411         // We know this is APC or DPC.
00412         //
00413         //DPRINT1("[DPC/APC]\n");
00414         HalClearSoftwareInterrupt(Irql);
00415     }
00416 
00417     //
00418     // Call the registered interrupt routine
00419     //
00420     Pcr->InterruptRoutine[Irql]();
00421     ASSERT(KeGetCurrentThread()->TrapFrame == TrapFrame);
00422     KeGetCurrentThread()->TrapFrame = OldTrapFrame;
00423 //    DPRINT1("[ISR RETURN]\n");
00424     
00425     //
00426     // Restore IRQL and interrupts
00427     //
00428     KeLowerIrql(OldIrql);
00429     _enable();
00430 }
00431 
00432 NTSTATUS
00433 KiPrefetchAbortHandler(IN PKTRAP_FRAME TrapFrame)
00434 {
00435     PVOID Address = (PVOID)KeArmFaultAddressRegisterGet();
00436     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
00437     ULONG Instruction = *(PULONG)TrapFrame->Pc;
00438     ULONG DebugType, Parameter0;
00439     EXCEPTION_RECORD ExceptionRecord;
00440     
00441     DPRINT1("[PREFETCH ABORT] (%x) @ %p/%p/%p\n",
00442             KeArmInstructionFaultStatusRegisterGet(), Address, TrapFrame->SvcLr, TrapFrame->Pc);
00443     while (TRUE);
00444     
00445     //
00446     // What we *SHOULD* do is look at the instruction fault status register
00447     // and see if it's equal to 2 (debug trap). Unfortunately QEMU doesn't seem
00448     // to emulate this behaviour properly, so we use a workaround.
00449     //
00450     //if (KeArmInstructionFaultStatusRegisterGet() == 2)
00451     if (Instruction & 0xE1200070) // BKPT
00452     {
00453         //
00454         // Okay, we know this is a breakpoint, extract the index
00455         //
00456         DebugType = Instruction & 0xF;
00457         if (DebugType == BREAKPOINT_PRINT)
00458         {
00459             //
00460             // Debug Service
00461             //
00462             Parameter0 = TrapFrame->R0;
00463             TrapFrame->Pc += sizeof(ULONG);
00464         }
00465         else
00466         {
00467             //
00468             // Standard INT3 (emulate x86 behavior)
00469             //
00470             Parameter0 = STATUS_SUCCESS;
00471         }
00472         
00473         //
00474         // Build the exception record
00475         //
00476         ExceptionRecord.ExceptionCode = STATUS_BREAKPOINT;
00477         ExceptionRecord.ExceptionFlags = 0;
00478         ExceptionRecord.ExceptionRecord = NULL;
00479         ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Pc;
00480         ExceptionRecord.NumberParameters = 3;
00481         
00482         //
00483         // Build the parameters
00484         //
00485         ExceptionRecord.ExceptionInformation[0] = Parameter0;
00486         ExceptionRecord.ExceptionInformation[1] = TrapFrame->R1;
00487         ExceptionRecord.ExceptionInformation[2] = TrapFrame->R2;
00488         
00489         //
00490         // Dispatch the exception
00491         //
00492         KiDispatchException(&ExceptionRecord,
00493                             NULL,
00494                             TrapFrame,
00495                             KiGetPreviousMode(TrapFrame),
00496                             TRUE);
00497 
00498         //
00499         // We're done
00500         //
00501         return STATUS_SUCCESS;
00502     }
00503     
00504     //
00505     // Unhandled
00506     //
00507     UNIMPLEMENTED;
00508     ASSERT(FALSE);
00509     return STATUS_SUCCESS;
00510 }
00511 
00512 NTSTATUS
00513 KiDataAbortHandler(IN PKTRAP_FRAME TrapFrame)
00514 {
00515     NTSTATUS Status;
00516     PVOID Address = (PVOID)KeArmFaultAddressRegisterGet();
00517     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
00518    
00519     DPRINT1("[ABORT] (%x) @ %p/%p/%p\n",
00520             KeArmFaultStatusRegisterGet(), Address, TrapFrame->SvcLr, TrapFrame->Pc);
00521     while (TRUE);
00522         
00523     //
00524     // Check if this is a page fault
00525     //
00526     if (KeArmFaultStatusRegisterGet() == 21 || KeArmFaultStatusRegisterGet() == 23)
00527     {
00528         Status = MmAccessFault(FALSE,
00529                                Address,
00530                                KiGetPreviousMode(TrapFrame),
00531                                TrapFrame);
00532         if (NT_SUCCESS(Status)) return Status;
00533     }
00534 
00535     //
00536     // Unhandled
00537     //
00538     UNIMPLEMENTED;
00539     ASSERT(FALSE);
00540     return STATUS_SUCCESS;
00541 }
00542 
00543 VOID
00544 KiSoftwareInterruptHandler(IN PKTRAP_FRAME TrapFrame)
00545 {
00546     PKTHREAD Thread;
00547     KPROCESSOR_MODE PreviousMode;
00548     ULONG Instruction;
00549     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
00550     
00551     DPRINT1("[SWI] @ %p/%p\n", TrapFrame->SvcLr, TrapFrame->Pc);
00552     while (TRUE);
00553     
00554     //
00555     // Get the current thread
00556     //
00557     Thread = KeGetCurrentThread();
00558     
00559     //
00560     // Isolate previous mode
00561     //
00562     PreviousMode = KiGetPreviousMode(TrapFrame);
00563     
00564     //
00565     // Save old previous mode
00566     //
00567     TrapFrame->PreviousMode = PreviousMode;
00568     TrapFrame->PreviousTrapFrame = (ULONG_PTR)Thread->TrapFrame;
00569     
00570     //
00571     // Save previous mode and trap frame
00572     //
00573     Thread->TrapFrame = TrapFrame;
00574     Thread->PreviousMode = PreviousMode;
00575     
00576     //
00577     // Read the opcode
00578     //
00579     Instruction = *(PULONG)(TrapFrame->Pc - sizeof(ULONG));
00580 
00581     //
00582     // Call the service call dispatcher
00583     //
00584     KiSystemService(Thread, TrapFrame, Instruction);
00585 }
00586 
00587 NTSTATUS
00588 KiUndefinedExceptionHandler(IN PKTRAP_FRAME TrapFrame)
00589 {
00590     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
00591     
00592     //
00593     // This should never happen
00594     //
00595     DPRINT1("[UNDEF] @ %p/%p\n", TrapFrame->SvcLr, TrapFrame->Pc);
00596     UNIMPLEMENTED;
00597     ASSERT(FALSE);
00598     return STATUS_SUCCESS;
00599 }

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.