34,13 → 34,12 |
*/ |
|
#include <arch/exception.h> |
#include <arch/debug/print.h> |
#include <arch/memstr.h> |
#include <arch/regutils.h> |
#include <interrupt.h> |
#include <arch/machine.h> |
#include <arch/mm/page_fault.h> |
#include <arch/barrier.h> |
#include <arch/drivers/gxemul.h> |
#include <print.h> |
#include <syscall/syscall.h> |
#include <udebug/udebug.h> |
64,57 → 63,60 |
* |
* Temporary exception stack is used to save a few registers |
* before stack switch takes place. |
* |
*/ |
inline static void setup_stack_and_save_regs() |
{ |
asm volatile( |
"ldr r13, =exc_stack \n" |
"stmfd r13!, {r0} \n" |
"mrs r0, spsr \n" |
"and r0, r0, #0x1f \n" |
"cmp r0, #0x10 \n" |
"bne 1f \n" |
|
asm volatile ( |
"ldr r13, =exc_stack\n" |
"stmfd r13!, {r0}\n" |
"mrs r0, spsr\n" |
"and r0, r0, #0x1f\n" |
"cmp r0, #0x10\n" |
"bne 1f\n" |
|
/* prev mode was usermode */ |
"ldmfd r13!, {r0} \n" |
"ldr r13, =supervisor_sp \n" |
"ldr r13, [r13] \n" |
"stmfd r13!, {lr} \n" |
"stmfd r13!, {r0-r12} \n" |
"stmfd r13!, {r13, lr}^ \n" |
"mrs r0, spsr \n" |
"stmfd r13!, {r0} \n" |
"b 2f \n" |
|
"ldmfd r13!, {r0}\n" |
"ldr r13, =supervisor_sp\n" |
"ldr r13, [r13]\n" |
"stmfd r13!, {lr}\n" |
"stmfd r13!, {r0-r12}\n" |
"stmfd r13!, {r13, lr}^\n" |
"mrs r0, spsr\n" |
"stmfd r13!, {r0}\n" |
"b 2f\n" |
|
/* mode was not usermode */ |
"1:\n" |
"stmfd r13!, {r1, r2, r3} \n" |
"mrs r1, cpsr \n" |
"mov r2, lr \n" |
"bic r1, r1, #0x1f \n" |
"orr r1, r1, r0 \n" |
"mrs r0, cpsr \n" |
"msr cpsr_c, r1 \n" |
|
"mov r3, r13 \n" |
"stmfd r13!, {r2} \n" |
"mov r2, lr \n" |
"stmfd r13!, {r4-r12} \n" |
"mov r1, r13 \n" |
/* the following two lines are for debugging */ |
"mov sp, #0 \n" |
"mov lr, #0 \n" |
"msr cpsr_c, r0 \n" |
|
"ldmfd r13!, {r4, r5, r6, r7} \n" |
"stmfd r1!, {r4, r5, r6} \n" |
"stmfd r1!, {r7} \n" |
"stmfd r1!, {r2} \n" |
"stmfd r1!, {r3} \n" |
"mrs r0, spsr \n" |
"stmfd r1!, {r0} \n" |
"mov r13, r1 \n" |
"2:\n" |
"1:\n" |
"stmfd r13!, {r1, r2, r3}\n" |
"mrs r1, cpsr\n" |
"mov r2, lr\n" |
"bic r1, r1, #0x1f\n" |
"orr r1, r1, r0\n" |
"mrs r0, cpsr\n" |
"msr cpsr_c, r1\n" |
|
"mov r3, r13\n" |
"stmfd r13!, {r2}\n" |
"mov r2, lr\n" |
"stmfd r13!, {r4-r12}\n" |
"mov r1, r13\n" |
|
/* the following two lines are for debugging */ |
"mov sp, #0\n" |
"mov lr, #0\n" |
"msr cpsr_c, r0\n" |
|
"ldmfd r13!, {r4, r5, r6, r7}\n" |
"stmfd r1!, {r4, r5, r6}\n" |
"stmfd r1!, {r7}\n" |
"stmfd r1!, {r2}\n" |
"stmfd r1!, {r3}\n" |
"mrs r0, spsr\n" |
"stmfd r1!, {r0}\n" |
"mov r13, r1\n" |
|
"2:\n" |
); |
} |
|
190,10 → 192,13 |
} |
|
/** Calls exception dispatch routine. */ |
#define CALL_EXC_DISPATCH(exception) \ |
asm("mov r0, %0" : : "i" (exception)); \ |
asm("mov r1, r13"); \ |
asm("bl exc_dispatch"); |
#define CALL_EXC_DISPATCH(exception) \ |
asm volatile ( \ |
"mov r0, %[exc]\n" \ |
"mov r1, r13\n" \ |
"bl exc_dispatch\n" \ |
:: [exc] "i" (exception) \ |
);\ |
|
/** General exception handler. |
* |
202,9 → 207,9 |
* |
* @param exception Exception number. |
*/ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
#define PROCESS_EXCEPTION(exception) \ |
setup_stack_and_save_regs(); \ |
CALL_EXC_DISPATCH(exception) \ |
load_regs(); |
|
/** Updates specified exception vector to jump to given handler. |
255,7 → 260,10 |
/** Low-level Prefetch Abort Exception handler. */ |
static void prefetch_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
asm volatile ( |
"sub lr, lr, #4" |
); |
|
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT); |
} |
|
262,7 → 270,10 |
/** Low-level Data Abort Exception handler. */ |
static void data_abort_exception_entry(void) |
{ |
asm("sub lr, lr, #8"); |
asm volatile ( |
"sub lr, lr, #8" |
); |
|
PROCESS_EXCEPTION(EXC_DATA_ABORT); |
} |
|
274,7 → 285,10 |
*/ |
static void irq_exception_entry(void) |
{ |
asm("sub lr, lr, #4"); |
asm volatile ( |
"sub lr, lr, #4" |
); |
|
setup_stack_and_save_regs(); |
|
switch_to_irq_servicing_mode(); |
294,6 → 308,12 |
istate->r3, istate->r4, istate->r5, istate->r6); |
} |
|
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
return *((uint32_t *) gxemul_irqc); |
} |
|
/** Interrupt Exception handler. |
* |
* Determines the sources of interrupt and calls their handlers. |
300,7 → 320,23 |
*/ |
static void irq_exception(int exc_no, istate_t *istate) |
{ |
machine_irq_exception(exc_no, istate); |
uint32_t sources = gxemul_irqc_get_sources(); |
unsigned int i; |
|
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
printf("cpu%d: spurious interrupt (inum=%d)\n", |
CPU->id, i); |
} |
} |
} |
} |
|
/** Fills exception vectors with appropriate exception handlers. */ |
324,7 → 360,7 |
install_handler((unsigned) irq_exception_entry, |
(unsigned *) EXC_IRQ_VEC); |
|
install_handler((unsigned)fiq_exception_entry, |
install_handler((unsigned) fiq_exception_entry, |
(unsigned *) EXC_FIQ_VEC); |
} |
|
334,17 → 370,23 |
{ |
uint32_t control_reg; |
|
asm volatile("mrc p15, 0, %0, c1, c1" : "=r" (control_reg)); |
asm volatile ( |
"mrc p15, 0, %[control_reg], c1, c1" |
: [control_reg] "=r" (control_reg) |
); |
|
/* switch on the high vectors bit */ |
control_reg |= CP15_R1_HIGH_VECTORS_BIT; |
|
asm volatile("mcr p15, 0, %0, c1, c1" : : "r" (control_reg)); |
asm volatile ( |
"mcr p15, 0, %[control_reg], c1, c1" |
:: [control_reg] "r" (control_reg) |
); |
} |
#endif |
|
/** Initializes exception handling. |
* |
* |
* Installs low-level exception handlers and then registers |
* exceptions and their handlers to kernel exception dispatcher. |
*/ |
368,18 → 410,18 |
*/ |
void print_istate(istate_t *istate) |
{ |
dprintf("istate dump:\n"); |
|
dprintf(" r0: %x r1: %x r2: %x r3: %x\n", |
printf("istate dump:\n"); |
|
printf(" r0: %x r1: %x r2: %x r3: %x\n", |
istate->r0, istate->r1, istate->r2, istate->r3); |
dprintf(" r4: %x r5: %x r6: %x r7: %x\n", |
printf(" r4: %x r5: %x r6: %x r7: %x\n", |
istate->r4, istate->r5, istate->r6, istate->r7); |
dprintf(" r8: %x r8: %x r10: %x r11: %x\n", |
printf(" r8: %x r8: %x r10: %x r11: %x\n", |
istate->r8, istate->r9, istate->r10, istate->r11); |
dprintf(" r12: %x sp: %x lr: %x spsr: %x\n", |
printf(" r12: %x sp: %x lr: %x spsr: %x\n", |
istate->r12, istate->sp, istate->lr, istate->spsr); |
|
dprintf(" pc: %x\n", istate->pc); |
|
printf(" pc: %x\n", istate->pc); |
} |
|
/** @} |