2008-02-13 05:16:14 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
2008-06-29 02:58:05 +00:00
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
2008-02-13 05:16:14 +00:00
|
|
|
* FILE: ntoskrnl/ke/arm/exp.c
|
|
|
|
* PURPOSE: Implements exception helper routines for ARM machines
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
2008-07-19 06:13:10 +00:00
|
|
|
#include <internal/arm/ksarm.h>
|
2008-02-13 05:16:14 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
KeContextToTrapFrame(IN PCONTEXT Context,
|
|
|
|
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
IN OUT PKTRAP_FRAME TrapFrame,
|
|
|
|
IN ULONG ContextFlags,
|
|
|
|
IN KPROCESSOR_MODE PreviousMode)
|
|
|
|
{
|
2008-07-14 00:04:53 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Do this at APC_LEVEL
|
|
|
|
//
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Start with the Control flags
|
|
|
|
//
|
|
|
|
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// So this basically means all the special stuff
|
|
|
|
//
|
|
|
|
if (PreviousMode == UserMode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// ARM has register banks
|
|
|
|
//
|
|
|
|
TrapFrame->UserSp = Context->Sp;
|
|
|
|
TrapFrame->UserLr = Context->Lr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// ARM has register banks
|
|
|
|
//
|
|
|
|
TrapFrame->SvcSp = Context->Sp;
|
|
|
|
TrapFrame->SvcLr = Context->Lr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// The rest is already in the right mode
|
|
|
|
//
|
|
|
|
TrapFrame->Pc = Context->Pc;
|
|
|
|
TrapFrame->Spsr = Context->Psr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now do the integers
|
|
|
|
//
|
|
|
|
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Basically everything else but FPU
|
|
|
|
//
|
|
|
|
TrapFrame->R0 = Context->R0;
|
|
|
|
TrapFrame->R1 = Context->R1;
|
|
|
|
TrapFrame->R2 = Context->R2;
|
|
|
|
TrapFrame->R3 = Context->R3;
|
|
|
|
TrapFrame->R4 = Context->R4;
|
|
|
|
TrapFrame->R5 = Context->R5;
|
|
|
|
TrapFrame->R6 = Context->R6;
|
|
|
|
TrapFrame->R7 = Context->R7;
|
|
|
|
TrapFrame->R8 = Context->R8;
|
|
|
|
TrapFrame->R0 = Context->R9;
|
|
|
|
TrapFrame->R10 = Context->R10;
|
|
|
|
TrapFrame->R11 = Context->R11;
|
|
|
|
TrapFrame->R12 = Context->R12;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Restore IRQL
|
|
|
|
//
|
|
|
|
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
|
2008-02-13 05:16:14 +00:00
|
|
|
}
|
2008-07-13 23:46:50 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
|
|
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
IN OUT PCONTEXT Context)
|
|
|
|
{
|
2008-07-13 23:58:47 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Do this at APC_LEVEL
|
|
|
|
//
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
|
|
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Start with the Control flags
|
|
|
|
//
|
|
|
|
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// So this basically means all the special stuff
|
|
|
|
//
|
2008-07-14 00:04:53 +00:00
|
|
|
if (KiGetPreviousMode(TrapFrame) == UserMode)
|
2008-07-13 23:58:47 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// ARM has register banks
|
|
|
|
//
|
|
|
|
Context->Sp = TrapFrame->UserSp;
|
|
|
|
Context->Lr = TrapFrame->UserLr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// ARM has register banks
|
|
|
|
//
|
|
|
|
Context->Sp = TrapFrame->SvcSp;
|
|
|
|
Context->Lr = TrapFrame->SvcLr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// The rest is already in the right mode
|
|
|
|
//
|
|
|
|
Context->Pc = TrapFrame->Pc;
|
|
|
|
Context->Psr = TrapFrame->Spsr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now do the integers
|
|
|
|
//
|
|
|
|
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Basically everything else but FPU
|
|
|
|
//
|
|
|
|
Context->R0 = TrapFrame->R0;
|
|
|
|
Context->R1 = TrapFrame->R1;
|
|
|
|
Context->R2 = TrapFrame->R2;
|
|
|
|
Context->R3 = TrapFrame->R3;
|
|
|
|
Context->R4 = TrapFrame->R4;
|
|
|
|
Context->R5 = TrapFrame->R5;
|
|
|
|
Context->R6 = TrapFrame->R6;
|
|
|
|
Context->R7 = TrapFrame->R7;
|
|
|
|
Context->R8 = TrapFrame->R8;
|
|
|
|
Context->R0 = TrapFrame->R9;
|
|
|
|
Context->R10 = TrapFrame->R10;
|
|
|
|
Context->R11 = TrapFrame->R11;
|
|
|
|
Context->R12 = TrapFrame->R12;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Restore IRQL
|
|
|
|
//
|
|
|
|
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
|
2008-07-13 23:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|
|
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
IN PKTRAP_FRAME TrapFrame,
|
|
|
|
IN KPROCESSOR_MODE PreviousMode,
|
|
|
|
IN BOOLEAN FirstChance)
|
|
|
|
{
|
|
|
|
CONTEXT Context;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Increase number of Exception Dispatches
|
|
|
|
//
|
|
|
|
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set the context flags
|
|
|
|
//
|
|
|
|
Context.ContextFlags = CONTEXT_FULL;
|
|
|
|
|
|
|
|
//
|
2008-07-19 06:13:10 +00:00
|
|
|
// FIXME-V6: VFP Support
|
2008-07-13 23:46:50 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get a Context
|
|
|
|
//
|
|
|
|
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Look at our exception code
|
|
|
|
//
|
|
|
|
switch (ExceptionRecord->ExceptionCode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Breakpoint
|
|
|
|
//
|
|
|
|
case STATUS_BREAKPOINT:
|
|
|
|
|
|
|
|
//
|
2008-07-14 00:24:33 +00:00
|
|
|
// We want the instruction right before the int 3
|
2008-07-13 23:46:50 +00:00
|
|
|
//
|
2008-07-14 00:24:33 +00:00
|
|
|
Context.Pc -= sizeof(ULONG);
|
2008-07-13 23:46:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Internal exception
|
|
|
|
//
|
|
|
|
case KI_EXCEPTION_ACCESS_VIOLATION:
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set correct code
|
|
|
|
//
|
|
|
|
ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Handle kernel-mode first, it's simpler
|
|
|
|
//
|
|
|
|
if (PreviousMode == KernelMode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if this is a first-chance exception
|
|
|
|
//
|
|
|
|
if (FirstChance == TRUE)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Break into the debugger for the first time
|
|
|
|
//
|
|
|
|
if (KiDebugRoutine(TrapFrame,
|
|
|
|
ExceptionFrame,
|
|
|
|
ExceptionRecord,
|
|
|
|
&Context,
|
|
|
|
PreviousMode,
|
|
|
|
FALSE))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Exception was handled
|
|
|
|
//
|
|
|
|
goto Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If the Debugger couldn't handle it, dispatch the exception
|
|
|
|
//
|
|
|
|
if (RtlDispatchException(ExceptionRecord, &Context)) goto Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// This is a second-chance exception, only for the debugger
|
|
|
|
//
|
|
|
|
if (KiDebugRoutine(TrapFrame,
|
|
|
|
ExceptionFrame,
|
|
|
|
ExceptionRecord,
|
|
|
|
&Context,
|
|
|
|
PreviousMode,
|
|
|
|
TRUE))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Exception was handled
|
|
|
|
//
|
|
|
|
goto Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Third strike; you're out
|
|
|
|
//
|
|
|
|
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
|
|
|
|
ExceptionRecord->ExceptionCode,
|
|
|
|
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
|
|
|
|
(ULONG_PTR)TrapFrame,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
2008-07-19 06:13:10 +00:00
|
|
|
// FIXME-USER: Do user-mode exception handling
|
2008-07-13 23:46:50 +00:00
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
Handled:
|
|
|
|
//
|
|
|
|
// Convert the context back into Trap/Exception Frames
|
|
|
|
//
|
|
|
|
KeContextToTrapFrame(&Context,
|
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
Context.ContextFlags,
|
|
|
|
PreviousMode);
|
|
|
|
}
|