Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2406 → Rev 2407

/branches/arm/kernel/arch/arm32/src/exception.c
44,18 → 44,37
#include <print.h>
#include <syscall/syscall.h>
 
/** Offset used in calculation of exception handler's relative address.
*
* @see install_handler()
*/
#define PREFETCH_OFFSET 0x8
 
#define PREFETCH_OFFSET 0x8
#define BRANCH_OPCODE 0xea000000
/** LDR instruction's code */
#define LDR_OPCODE 0xe59ff000
#define VALID_BRANCH_MASK 0xff000000
#define EXC_VECTORS_SIZE 0x20
#define EXC_VECTORS 0x8
 
/** Number of exception vectors. */
#define EXC_VECTORS 8
 
/** Size of memory block occupied by exception vectors. */
#define EXC_VECTORS_SIZE (EXC_VECTORS * 4)
 
 
/** Kernel stack pointer.
*
* It is set when thread switches to user mode,
* and then used for exception handling.
*/
extern uintptr_t supervisor_sp;
 
/** Temporary exception stack pointer.
*
* Temporary stack is used in exceptions handling routines
* before switching to thread's kernel stack.
*/
extern uintptr_t exc_stack;
 
 
/** Switches to kernel stack and saves all registers there.
*
* Temporary exception stack is used to save a few registers
113,6 → 132,7
);
}
 
 
/** Returns from exception mode.
*
* Previously saved state of registers (including control register)
148,6 → 168,39
);
}
 
/** Switch CPU to mode in which interrupts are serviced (currently it
* is Undefined mode).
*
* The default mode for interrupt servicing (Interrupt Mode)
* can not be used because of nested interrupts (which can occur
* because interrupt are enabled in higher levels of interrupt handler).
*/
inline static void switchToIrqServicingMode()
{
/* switch to Undefined mode */
asm volatile(
/* save regs used during switching */
"stmfd sp!, {r0-r3} \n"
 
/* save stack pointer and link register to r1, r2 */
"mov r1, sp \n"
"mov r2, lr \n"
 
/* mode switch */
"mrs r0, cpsr \n"
"bic r0, r0, #0x1f \n"
"orr r0, r0, #0x1b \n"
"msr cpsr_c, r0 \n"
 
/* restore saved sp and lr */
"mov sp, r1 \n"
"mov lr, r2 \n"
 
/* restore original regs */
"ldmfd sp!, {r0-r3} \n"
);
}
 
/** Calls exception dispatch routine. */
#define CALL_EXC_DISPATCH(exception) \
asm("mov r0, %0" : : "i" (exception)); \
154,7 → 207,7
asm("mov r1, r13"); \
asm("bl exc_dispatch");
 
 
/** General exception handler.
*
* Stores registers, dispatches the exception,
242,19 → 295,9
{
asm("sub lr, lr, #4");
setup_stack_and_save_regs();
 
/* switch to Undefined mode */
asm("stmfd sp!, {r0-r3}");
asm("mov r1, sp");
asm("mov r2, lr");
asm("mrs r0, cpsr");
asm("bic r0, r0, #0x1f");
asm("orr r0, r0, #0x1b");
asm("msr cpsr_c, r0");
asm("mov sp, r1");
asm("mov lr, r2");
asm("ldmfd sp!, {r0-r3}");
 
switchToIrqServicingMode();
CALL_EXC_DISPATCH(EXC_IRQ)
 
load_regs();