diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
commit | 0edaecc54329048eb91ad6a45338265ef1a4569c (patch) | |
tree | b0695be27ac3b1e14aa944c4820683fcd8adefca /pk/handlers.c | |
parent | e63e4fbe8794c68e1ad846a36e33cba62e801b34 (diff) | |
download | riscv-pk-0edaecc54329048eb91ad6a45338265ef1a4569c.zip riscv-pk-0edaecc54329048eb91ad6a45338265ef1a4569c.tar.gz riscv-pk-0edaecc54329048eb91ad6a45338265ef1a4569c.tar.bz2 |
temporary undoing of renaming
Diffstat (limited to 'pk/handlers.c')
-rw-r--r-- | pk/handlers.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/pk/handlers.c b/pk/handlers.c new file mode 100644 index 0000000..ebc8f2a --- /dev/null +++ b/pk/handlers.c @@ -0,0 +1,169 @@ +#include "pcr.h" +#include "pk.h" + +int have_fp = 1; // initialized to 1 because it can't be in the .bss section! +int have_vector = 1; + +static void handle_vector_disabled(trapframe_t* tf) +{ + if (have_vector) + tf->sr |= SR_EV; + else + panic("No vector hardware! pc %lx, insn %x",tf->epc,(uint32_t)tf->insn); +} + +static void handle_vector_bank(trapframe_t* tf) +{ + dump_tf(tf); + panic("Not enought banks were enabled to execute a vector instruction!"); +} + +static void handle_vector_illegal_instruction(trapframe_t* tf) +{ + dump_tf(tf); + panic("An illegal vector instruction was executed!"); +} + +static void handle_privileged_instruction(trapframe_t* tf) +{ + dump_tf(tf); + panic("A privileged instruction was executed!"); +} + +static void handle_illegal_instruction(trapframe_t* tf) +{ +#ifdef PK_ENABLE_FP_EMULATION + irq_enable(); + + if(emulate_fp(tf) == 0) + { + advance_pc(tf); + return; + } +#endif + + dump_tf(tf); + panic("An illegal instruction was executed!"); +} + +static void handle_fp_disabled(trapframe_t* tf) +{ + irq_enable(); + + if(have_fp && !(mfpcr(PCR_SR) & SR_EF)) + init_fp(tf); + else + handle_illegal_instruction(tf); +} + +static void handle_breakpoint(trapframe_t* tf) +{ + dump_tf(tf); + printk("Breakpoint!\n"); +} + +static void handle_misaligned_fetch(trapframe_t* tf) +{ + dump_tf(tf); + panic("Misaligned instruction access!"); +} + +void handle_misaligned_load(trapframe_t* tf) +{ + // TODO emulate misaligned loads and stores + dump_tf(tf); + panic("Misaligned load!"); +} + +void handle_misaligned_store(trapframe_t* tf) +{ + dump_tf(tf); + panic("Misaligned store!"); +} + +static void handle_fault_fetch(trapframe_t* tf) +{ + dump_tf(tf); + panic("Faulting instruction access!"); +} + +void handle_fault_load(trapframe_t* tf) +{ + dump_tf(tf); + panic("Faulting load!"); +} + +void handle_fault_store(trapframe_t* tf) +{ + dump_tf(tf); + panic("Faulting store!"); +} + +static void handle_bad_interrupt(trapframe_t* tf, int interrupt) +{ + panic("Bad interrupt %d!",interrupt); +} + +static void handle_timer_interrupt(trapframe_t* tf) +{ + mtpcr(PCR_COMPARE, mfpcr(PCR_COMPARE)+TIMER_PERIOD); +} + +static void handle_interrupt(trapframe_t* tf) +{ + int interrupts = (tf->cause & CAUSE_IP) >> CAUSE_IP_SHIFT; + + for(int i = 0; interrupts; interrupts >>= 1, i++) + { + if(interrupts & 1) + { + if(i == TIMER_IRQ) + handle_timer_interrupt(tf); + else + handle_bad_interrupt(tf,i); + } + } +} + +static void handle_syscall(trapframe_t* tf) +{ + irq_enable(); + + long n = tf->gpr[2]; + sysret_t ret = syscall(tf->gpr[4], tf->gpr[5], tf->gpr[6], tf->gpr[7], n); + + tf->gpr[2] = ret.result; + tf->gpr[3] = ret.result == -1 ? ret.err : 0; + + advance_pc(tf); +} + +void handle_trap(trapframe_t* tf) +{ + typedef void (*trap_handler)(trapframe_t*); + + const static trap_handler trap_handlers[NUM_CAUSES] = { + [CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch, + [CAUSE_FAULT_FETCH] = handle_fault_fetch, + [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction, + [CAUSE_PRIVILEGED_INSTRUCTION] = handle_privileged_instruction, + [CAUSE_FP_DISABLED] = handle_fp_disabled, + [CAUSE_INTERRUPT] = handle_interrupt, + [CAUSE_SYSCALL] = handle_syscall, + [CAUSE_BREAKPOINT] = handle_breakpoint, + [CAUSE_MISALIGNED_LOAD] = handle_misaligned_load, + [CAUSE_MISALIGNED_STORE] = handle_misaligned_store, + [CAUSE_FAULT_LOAD] = handle_fault_load, + [CAUSE_FAULT_STORE] = handle_fault_store, + [CAUSE_VECTOR_DISABLED] = handle_vector_disabled, + [CAUSE_VECTOR_BANK] = handle_vector_bank, + [CAUSE_VECTOR_ILLEGAL_INSTRUCTION] = handle_vector_illegal_instruction, + }; + + int exccode = (tf->cause & CAUSE_EXCCODE) >> CAUSE_EXCCODE_SHIFT; + kassert(exccode < ARRAY_SIZE(trap_handlers)); + + trap_handlers[exccode](tf); + + pop_tf(tf); +} |